zoukankan      html  css  js  c++  java
  • 线性表的顺序表示实现-C++版

         声明:本文内容属于本人原创,欢迎转载,请大家在转载时注明转贴地址

        使用一个模板类实现了线性表的顺序表示,我对这个模板类进行了简单的测试,大家如果在使用过程中或看代码的过程中遇到错误请及时提出,谢谢!该代码已经在VS2005环境下编译通过

    1. /**
    2. * @file ListSqu.h
    3. * @author Wang Liuqiang
    4. * @version 1.0
    5. * @date 2008-11-30
    6. * @brief 该类实现了线性表的顺序表示
    7. */
    8. #ifndef LISTSQU_H_
    9. #define LISTSQU_H_
    10. #include <assert.h>
    11. #include <iostream>
    12. using namespace std;
    13. #define LIST_INIT_SIZE 100
    14. #define LISTINCREMENT 10
    15. #define SQUSUCCEED 0
    16. #define SQUERROR -1
    17. #define SQUOVERFLOW -2
    18. /*
    19.  * 定义了两个默认的函数,如果用户在调用LocalElem()函数时没有指定
    20.  * 函数,则使用默认的equal()函数;如果指定了自己的比较函数,则将
    21.  * 自己的函数指针赋给LocalElem()函数
    22. */
    23. template <class T>
    24. bool equal(T e1, T e2)
    25. {
    26.     if (e1 == e2)
    27.     {
    28.         return true;
    29.     }
    30.     else
    31.     {
    32.         return false;
    33.     }
    34. }
    35. /*
    36. * 定义了两个默认的函数,如果用户在调用Traverse()函数时没有指定
    37. * 函数,则使用默认的show()函数;如果指定了自己的比较函数,则将
    38. * 自己的函数指针赋给Traverse()函数
    39. */
    40. template <class T>
    41. void show(T e)
    42. {
    43.     cout<<e<<endl;
    44. }
    45. template <class T>
    46. class ListSqu
    47. {
    48. public:
    49.     /*
    50.     *name 构造函数/析构函数
    51.     *@{
    52.     */
    53.     ListSqu();
    54.     ~ListSqu();
    55.     ListSqu(const ListSqu<T>& ls);
    56.     ListSqu<T>& operator=(const ListSqu<T>& ls);
    57.     /** @}*/ //构造函数/析构函数
    58. public:
    59.     /*
    60.      * 清空顺序表
    61.      * @return 返回函数执行结果:
    62.      * -0 表示执行成功
    63.      * -1 表示执行出错
    64.     */
    65.     int ClearList();
    66.     /*
    67.      * 判断顺序表是否为空
    68.      * @return 返回函数执行结果:
    69.      * -true 表示顺序表为空
    70.      * -false 表示顺序表不为空
    71.     */
    72.     bool IsEmpty();
    73.     /*
    74.      * 返回顺序表中元素个数
    75.      * @return 返回顺序表中元素个数
    76.     */
    77.     int Length();
    78.     /*
    79.      * 返回线性表中第一个与e满足关系Compare()的数据元素的位序
    80.      * @param[in] e 待判定的元素
    81.      * @param[in] Compare 函数指针,指向判定元素的函数指针,默认为比较元素是否相等
    82.      * @return 返回线性表中第一个与e满足关系Compare()的数据元素的位序
    83.     */
    84.     int LocalElem(const T& e, bool (*Compare)(T, T)= equal);
    85.     /*
    86.      * 返回顺序表中第i个位置的元素
    87.      * @param[in] i 需要获取元素的位置
    88.      * @param[out] e 顺序表中第i个位置的元素值
    89.      * @return 返回函数执行结果
    90.      * -SQUSUCCEED 表示函数执行成功
    91.      * -SQUERROR 表示函数执行失败
    92.      * @note C++中数组的下标是从0开始,因此第i个位置的元素应该取下标为i-1的元素
    93.     */
    94.     int GetItem(int i, T& e);
    95.     /*
    96.      * 在顺序表的第i个位置之前插入元素
    97.      * @param[in] 元素的插入位置
    98.      * @param[in] 插入元素值
    99.      * @return 返回函数的执行结果
    100.      * -SQUSUCCEED 表示函数执行成功
    101.      * -SQUERROR 表示函数执行失败
    102.     */
    103.     int InsertItem(int i, T& e);
    104.     /*
    105.      * 删除顺序表中第i个位置的元素
    106.      * @param[in] i 待删除元素位置
    107.      * @param[out] e 删除元素的值
    108.      * @return 返回函数的执行结果
    109.      * -SQUSUCCEED 表示函数执行成功
    110.      * -SQUERROR 表示函数执行失败
    111.     */
    112.     int DeleteItem(int i, T& e);
    113.     /*
    114.      * 显示顺序表中元素
    115.      * @return 返回函数的执行结果
    116.      * -SQUSUCCEED 表示函数执行成功
    117.      * -SQUERROR 表示函数执行失败
    118.     */
    119.     int Show(); // 输出表中元素
    120.     /*
    121.      * 遍历线性表中元素
    122.      * @param[in] vi 函数指针,指向处理元素函数,默认为在屏幕打印元素
    123.     */
    124.     void Traverse(void (*vi)(T e) = show);
    125. private:
    126.     T* items;
    127.     int length;
    128.     int listsize;
    129. };
    130. template <class T>
    131. ListSqu<T>::ListSqu()
    132. {
    133.     items = new T[LIST_INIT_SIZE];
    134.     assert(items);
    135.     length = 0;
    136.     listsize = LIST_INIT_SIZE;
    137. }
    138. template <class T>
    139. ListSqu<T>::~ListSqu()
    140. {
    141.     if (items != NULL)
    142.     {
    143.         delete[] items;
    144.         items = NULL;
    145.     }
    146. }
    147. template <class T>
    148. ListSqu<T>::ListSqu(const ListSqu<T>& ls)
    149. {
    150.     length = ls.length;
    151.     listsize = ls.listsize;
    152.     items = new T[listsize + 1];
    153.     memcpy(items, ls.items, _msize(ls.items));
    154. }
    155. template <class T>
    156. ListSqu<T>& ListSqu<T>::operator=(const ListSqu<T>& ls)
    157. {
    158.     ifthis == &ls )
    159.         return *this;
    160.     if (items != NULL)
    161.     {
    162.         delete[] items;
    163.         items = NULL;
    164.     }   
    165.     length = ls.length;
    166.     listsize = ls.listsize;
    167.     items = new T[listsize + 1];
    168.     memcpy(items, ls.items, _msize(ls.items));
    169.     return *this;
    170. }
    171. template <class T>
    172. int ListSqu<T>::ClearList()
    173. {
    174.     length = 0;
    175.     return SQUSUCCEED;
    176. }
    177. template <class T>
    178. bool ListSqu<T>::IsEmpty()
    179. {
    180.     return length == 0;
    181. }
    182. template <class T>
    183. int ListSqu<T>::LocalElem(const T& e, bool (*Compare)(T, T))
    184. {
    185.     int i = 0;
    186.     T* p;
    187.     p = items;
    188.     while ( i < length && !Compare(*p++, e))
    189.     {
    190.         ++i;
    191.     }
    192.     if (i < length)
    193.     {
    194.         return i + 1;
    195.     }
    196.     else
    197.     {
    198.         return 0;
    199.     }
    200. }
    201. template <class T>
    202. int ListSqu<T>::GetItem(int i, T& e)
    203. {
    204.     if ( (i < 1) || ( i > length ))
    205.     {
    206.         cout<<"所给位置超出位置索引!"<<endl;
    207.         return SQUERROR;
    208.     }
    209.     else
    210.     {
    211.         e = items[i -1];
    212.         return SQUSUCCEED;
    213.     }
    214. }
    215. template <class T>
    216. int ListSqu<T>::InsertItem(int i, T& e)
    217. {
    218.     if ( i < 1 || i > length + 1)
    219.     {
    220.         cout<<"所给位置出错!"<<endl;
    221.         return SQUERROR;
    222.     }
    223.     else
    224.     {
    225.         if (length >= listsize)
    226.         {
    227.             T* pNew = new T[LISTINCREMENT];
    228.             memcpy(pNew, items, _msize(items));
    229.             items = pNew;
    230.             if (items == NULL)
    231.             {
    232.                 cout<<"申请内存空间失败!"<<endl;
    233.                 return SQUOVERFLOW;
    234.             }
    235.             listsize += LISTINCREMENT;
    236.         }
    237.         for(int k = length; k >= i - 1; k--)
    238.         {
    239.             items[k+1] = items[k];
    240.         }
    241.         items[i-1] = e;
    242.         length++;
    243.         return SQUSUCCEED;
    244.     }
    245. }
    246. template <class T>
    247. int ListSqu<T>::DeleteItem(int i, T& e)
    248. {
    249.     if ( i < 1 || i > length )
    250.     {
    251.         cout<<"所给删除位置出错!"<<endl;
    252.         return SQUERROR;
    253.     }
    254.     e = items[i-1];
    255.     for (i = i -1; i < length; i++)
    256.     {
    257.         items[i] = items[i + 1];
    258.     }   
    259.     length--;
    260.     return SQUSUCCEED;
    261. }
    262. template <class T>
    263. int ListSqu<T>::Show()
    264. {
    265.     for (int i = 0; i < length; i++)
    266.     {
    267.         cout<<items[i]<<endl;
    268.     }
    269.     return SQUSUCCEED;
    270. }
    271. template <class T>
    272. void ListSqu<T>::Traverse(void (*vi)(T e))
    273. {
    274.     for (int i = 0; i < length; i++)
    275.     {
    276.        vi(items[i]);
    277.     }
    278. }
    279. #endif

        通过编写这段代码,觉得以下几点需要特别注意:

        1. 需要特别注意内存越界的情况,对于动态申请的内存指针,如果对其进行越界操作,在使用delete操作释放该指针时会造成程序崩溃。在编写上面的程序时就将

    template <class T> ListSqu<T>& ListSqu<T>::operator=(const ListSqu<T>& ls)

    函数中items = new T[listsize + 1];错误的写成了items = new T[length + 1];而造成内存越界,详细解释如下:

    template <class T>
    ListSqu <T>& ListSqu <T>::operator=(const ListSqu <T>& ls)
    {
        if( this == &ls )
            return *this;

        delete[] items;
        items = NULL;

        length = ls.length;
        listsize = ls.listsize;

        items = new T[length + 1];  
        memcpy(items, ls.items, _msize(ls.items));
        return *this;
    }

    items = new T[length + 1];
    这里应该是
    items = new T[listsize + 1]; 
    listsize是我在类的构造函数中初始化分配的内存数,而length是当前线性表中存放的元素个数,这里用length+1分配内存,而在memcpy(items, ls.items, _msize(ls.items)); 又将sizeof(T)*listsize长的字节拷贝给items该处发生越界了

    2. 注意模板类的复制构造函数和赋值操作符的声明方法

    3. 注意如何把函数指针当作形参并对其使用默认参数的方法

  • 相关阅读:
    浅析c#中new、override、virtual关键字的区别
    数据解析1113
    Silverlight中xaml之间的跳转方案之一
    silverlight读取client文件的完整路径
    (Transfered)WPF Tutorial:Beginning
    数据解析1112
    邮件发送1
    TortoiseSVN Settings Subversion
    德信无线10Q4净利润同比增进187%
    欧盟中止对我数据卡双反调查
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6167977.html
Copyright © 2011-2022 走看看