线性表的顺序表示实现-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. 注意如何把函数指针当作形参并对其使用默认参数的方法

原文地址:https://www.cnblogs.com/zhangyunlin/p/6167977.html