数据结构基础(11) --循环链表的设计与实现

循环链表:最后一个结点的指针域的指针又指回第一个结点的链表;

    循环单链表与单链表的区别在于:表中最有一个节点的指针不再是NULL, 而改为指向头结点(因此要对我们原来的MyList稍作修改), 从而整个链表形成一个环.

    因此, 循环单链表的判空条件不再是头结点的指针是否为空, 而是他是否等于头结点;

    其实如果只是单纯的实现循环链表对单链表的性能提升是不明显的, 反而增加了代码上实现的复杂度, 但是如果与下一篇中的双向链表相结合的话, 在速度上的提升是十分惊人的, 因此这篇博客权当做是一个过渡吧, 为上一篇博客和下一篇博客的结合起着承上启下的作用.

 

    下面是MyList.h的完整代码与解析, 由于代码较多, 希望能够仔细阅读, 但其实下面的大部分代码都与前面类似只是对其中几处稍作修改, 遇到与单链表的不同之处, 我会与++符号作为注释指出:

  1. #ifndef MYLIST_H_INCLUDED  
  2. #define MYLIST_H_INCLUDED  
  3.   
  4. #include <iostream>  
  5. #include <stdexcept>  
  6. using namespace std;  
  7.   
  8. //循环链表  
  9. //前向声明  
  10. template <typename Type>  
  11. class MyList;  
  12. template <typename Type>  
  13. class ListIterator;  
  14.   
  15. //链表节点  
  16. template <typename Type>  
  17. class Node  
  18. {  
  19.     //可以将MyList类作为Node的友元  
  20.     //同时也可以将Node类做成MyList的嵌套类, 嵌套在MyList中, 也可以完成该功能  
  21.     friend class MyList<Type>;  
  22.     friend class ListIterator<Type>;  
  23.   
  24.     template <typename T>  
  25.     friend ostream &operator<<(ostream &os, const MyList<T> &list);  
  26. private:  
  27.     //constructor说明:  
  28.     //next = NULL;    //因为这是一个新生成的节点, 因此下一个节点为空  
  29.     Node(const Type &dataValue):data(dataValue), next(NULL) {}  
  30.   
  31.     Type data;  //数据域:节点数据  
  32.     Node *next; //指针域:下一个节点  
  33. };  
  34.   
  35. //链表  
  36. template <typename Type>  
  37. class MyList  
  38. {  
  39.     template <typename T>  
  40.     friend ostream &operator<<(ostream &os, const MyList<T> &list);  
  41.   
  42.     friend class ListIterator<Type>;  
  43. public:  
  44.     MyList();  
  45.     ~MyList();  
  46.   
  47.     //将元素插入表头  
  48.     void insertFront(const Type &data);  
  49.     //将元素插入到位置index上(index从1开始)  
  50.     void insert(const Type &data, int index);  
  51.     //删除表中所有值为data的节点  
  52.     void remove(const Type &data);  
  53.     bool isEmpty() const;  
  54.   
  55. private:  
  56.     //指向第一个节点的指针  
  57.     Node<Type> *first;  
  58. };  
  59.   
  60. template <typename Type>  
  61. MyList<Type>::MyList()  
  62. {  
  63.     //first指向一个空节点  
  64.     first = new Node<Type>(0);  
  65.   
  66.     // ++ 这是一个关键点  
  67.     //first的下一个元素就指向first  
  68.     //此时, 代表链表是否已经到达结尾处的判断已经不再是(是否等于NULL)  
  69.     //而改为(是否等于first)  
  70.     //因为此时first代表链表的最后一个元素  
  71.     //同时,first又是第一个元素的前一个元素  
  72.     first -> next = first;  
  73. }  
  74.   
  75. template <typename Type>  
  76. MyList<Type>::~MyList()  
  77. {  
  78.     Node<Type> *deleteNode = NULL;  
  79.     // ++ 保存链表尾元素  
  80.     Node<Type> *tmp = first;  
  81.   
  82.     // ++ first首先指向第一个真实的元素  
  83.     first = first->next;  
  84.     //一路到达链表结尾  
  85.     while (first != tmp)  
  86.     {  
  87.         deleteNode = first;  
  88.         first = first -> next;  
  89.         delete deleteNode;  
  90.     }  
  91.     // ++ 释放到链表的空节点  
  92.     delete tmp;  
  93. }  
  94.   
  95. //这一步与前一版链表相同  
  96. template <typename Type>  
  97. void MyList<Type>::insertFront(const Type &data)  
  98. {  
  99.     Node<Type> *newNode = new Node<Type>(data);  
  100.     newNode -> next = first -> next;  
  101.     first -> next = newNode;  
  102. }  
  103.   
  104. template <typename Type>  
  105. void MyList<Type>::insert(const Type &data, int index)  
  106. {  
  107.     //由于我们在表头添加了一个空节点  
  108.     //因此如果链表为空, 或者在链表为1的位置添加元素  
  109.     //其操作与在其他位置添加元素相同  
  110.   
  111.     int count = 1;  
  112.     //此时searchNode肯定不为first  
  113.     Node<Type> *searchNode = first;  
  114.   
  115.     //++ 注意:此处将NULL修改为first  
  116.     // 找到要插入的位置  
  117.     // 如果所给index过大(超过了链表的长度)  
  118.     // 则将该元素插入到链表表尾  
  119.     // 原因是 searchNode->next != first 这个条件已经不满足了  
  120.     while (count < index && searchNode->next != first)  
  121.     {  
  122.         ++ count;  
  123.         searchNode = searchNode->next;  
  124.     }  
  125.   
  126.     // 插入链表  
  127.     Node<Type> *newNode = new Node<Type>(data);  
  128.     newNode->next = searchNode->next;  
  129.     searchNode->next = newNode;  
  130. }  
  131.   
  132. template <typename Type>  
  133. void MyList<Type>::remove(const Type &data)  
  134. {  
  135.     if (isEmpty())  
  136.         return ;  
  137.   
  138.     Node<Type> *previous = first;   //保存要删除节点的前一个节点  
  139.     for (Node<Type> *searchNode = first->next;  
  140.             //searchNode != NULL; // ++ 注意此处不再是判断是否为NULL  
  141.             searchNode != first;     // ++ 而是不能等于first, first代表链表的末尾  
  142.             searchNode = searchNode->next)  
  143.     {  
  144.         if (searchNode->data == data)  
  145.         {  
  146.             previous->next = searchNode->next;  
  147.             delete searchNode;  
  148.             //重新调整searchNode指针  
  149.             //继续遍历链表查看是否还有相等元素  
  150.   
  151.             // ++ 注意  
  152.             //如果当前searchNode已经到达了最后一个节点  
  153.             //也就是searchNode->next已经等于first了, 则下面这条语句不能执行  
  154.             if (previous->next == first)  
  155.                 break;  
  156.   
  157.             searchNode = previous->next;  
  158.         }  
  159.         previous = searchNode;  
  160.     }  
  161. }  
  162. //注意判空条件  
  163. template <typename Type>  
  164. bool MyList<Type>::isEmpty() const  
  165. {  
  166.     return first->next == first;  
  167. }  
  168.   
  169. //显示链表中的所有数据(测试用)  
  170. template <typename Type>  
  171. ostream &operator<<(ostream &os, const MyList<Type> &list)  
  172. {  
  173.     for (Node<Type> *searchNode = list.first -> next;  
  174.             searchNode != list.first;   //++ 注意  
  175.             searchNode = searchNode -> next)  
  176.     {  
  177.         os << searchNode -> data;  
  178.         if (searchNode -> next != list.first) // ++ 注意(尚未达到链表的结尾)  
  179.             cout << " -> ";  
  180.     }  
  181.   
  182.     return os;  
  183. }  
  184.   
  185. //ListIterator 除了判空函数的判空条件之外, 没有任何改变  
  186. template <typename Type>  
  187. class ListIterator  
  188. {  
  189. public:  
  190.     ListIterator(const MyList<Type> &_list):  
  191.         list(_list),  
  192.         currentNode((_list.first)->next) {}  
  193.   
  194.     //重载 *operator  
  195.     const Type &operator*() const throw (std::out_of_range);  
  196.     Type &operator*() throw (std::out_of_range);  
  197.   
  198.     //重载 ->operator  
  199.     const Node<Type> *operator->() const throw (std::out_of_range);  
  200.     Node<Type> *operator->() throw (std::out_of_range);  
  201.   
  202.     //重载 ++operator  
  203.     ListIterator &operator++() throw (std::out_of_range);  
  204.     //注意:此处返回的是值,而不是reference  
  205.     ListIterator operator++(intthrow (std::out_of_range);  
  206.   
  207.     bool isEmpty() const;  
  208.   
  209. private:  
  210.     const MyList<Type> &list;  
  211.     Node<Type> *currentNode;  
  212. };  
  213.   
  214. template <typename Type>  
  215. bool ListIterator<Type>::isEmpty() const  
  216. {  
  217.     // ++ 注意:判空条件改为list.first  
  218.     if (currentNode == list.first)  
  219.         return true;  
  220.     return false;  
  221. }  
  222. template <typename Type>  
  223. const Type &ListIterator<Type>::operator*() const  
  224. throw (std::out_of_range)  
  225. {  
  226.     if (isEmpty())  
  227.         throw std::out_of_range("iterator is out of range");  
  228.     // 返回当前指针指向的内容  
  229.     return currentNode->data;  
  230. }  
  231. template <typename Type>  
  232. Type &ListIterator<Type>::operator*()  
  233. throw (std::out_of_range)  
  234. {  
  235.     //首先为*this添加const属性,  
  236.     //以调用该函数的const版本,  
  237.     //然后再使用const_case,  
  238.     //将该函数调用所带有的const属性转除  
  239.     //operator->()的non-const版本与此类同  
  240.     return  
  241.         const_cast<Type &>(  
  242.             static_cast<const ListIterator<Type> &>(*this).operator*()  
  243.         );  
  244. }  
  245.   
  246. template <typename Type>  
  247. const Node<Type> *ListIterator<Type>::operator->() const  
  248. throw (std::out_of_range)  
  249. {  
  250.     if (isEmpty())  
  251.         throw std::out_of_range("iterator is out of range");  
  252.     //直接返回指针  
  253.     return currentNode;  
  254. }  
  255.   
  256. template <typename Type>  
  257. Node<Type> *ListIterator<Type>::operator->()  
  258. throw (std::out_of_range)  
  259. {  
  260.     // 见上  
  261.     return  
  262.         const_cast<Node<Type> *> (  
  263.             static_cast<const ListIterator<Type> >(*this).operator->()  
  264.         );  
  265. }  
  266.   
  267. template <typename Type>  
  268. ListIterator<Type> &ListIterator<Type>::operator++()  
  269. throw (std::out_of_range)  
  270. {  
  271.     if (isEmpty())  
  272.         throw std::out_of_range("iterator is out of range");  
  273.     //指针前移  
  274.     currentNode = currentNode->next;  
  275.     return *this;  
  276. }  
  277. template <typename Type>  
  278. ListIterator<Type> ListIterator<Type>::operator++(int)  
  279. throw (std::out_of_range)  
  280. {  
  281.     ListIterator tmp(*this);  
  282.     ++ (*this); //调用前向++版本  
  283.   
  284.     return tmp;  
  285. }  
  286.   
  287. #endif // MYLIST_H_INCLUDED  

附-测试代码:

  1. int main()  
  2. {  
  3.     MyList<int> iMyList;  
  4.     for (int i = 0; i < 10; ++i)    //1 2 3 4 5 6 7 8 9 10  
  5.         iMyList.insert(i+1, i+1);  
  6.   
  7.     for (int i = 0; i < 5; ++i)     //40 30 20 10 0 1 2 3 4 5 6 7 8 9 10  
  8.         iMyList.insertFront(i*10);  
  9.   
  10.     iMyList.insertFront(100);//100 40 30 20 10 0 1 2 3 4 5 6 7 8 9 10  
  11.     iMyList.remove(10);      //100 40 30 20 0 1 2 3 4 5 6 7 8 9  
  12.     iMyList.remove(8);       //100 40 30 20 0 1 2 3 4 5 6 7 9  
  13.   
  14.     cout << "------------ MyList ------------" << endl;  
  15.     for (ListIterator<int> iter(iMyList);  
  16.             !(iter.isEmpty());  
  17.             ++ iter)  
  18.         cout << *iter << ' ';  
  19.     cout << endl;  
  20.     cout << "Test: \n\t" << iMyList << endl;  
  21.   
  22.     return 0;  


原文地址:http://blog.csdn.net/zjf280441589/article/details/42430955

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值