链表

来源:互联网 发布:网络推广文案案例 编辑:程序博客网 时间:2024/06/05 15:53

转自:http://blog.csdn.net/u012175089/article/details/54231845?locationNum=7&fps=1

跟Vector一样,我自己也写了一个简单的List来进行研究。

这里实现的是双向链表,因为双向链表包含了单向链表的所以功能,所以就没有单独写一个了。

这个双向链表的实现,在创建的时候,就已经有了两个节点,分别是head和tail。这是抽离出来,不存放数据的节点,是为了让程序简化,被称为哨兵节点。

假如不使用哨兵节点,在表头表尾操作的插入删除的时候,有很多要特殊处理的地方。

加了着两个节点,就可以大大简化这些特殊操作。数据上的表头不再试实际代码的表头。

[cpp] view plain copy
  1. //  
  2. //  List.h 双向链表的实现  
  3. //  HelloWorld  
  4. //  csdn blog:http://blog.csdn.net/u012175089  
  5. //  Created by feiyin001 on 17/1/7.  
  6. //  Copyright (c) 2017年 FableGame. All rights reserved.  
  7. //  
  8.   
  9. #ifndef __HelloWorld__List__  
  10. #define __HelloWorld__List__  
  11.   
  12.   
  13.   
  14. namespace Fable  
  15. {  
  16.     //双向链表,使用模板  
  17.     template<typename Object>  
  18.     class List  
  19.     {  
  20.     private:  
  21.         //节点,只在List内部使用,所有在私有区域内声明  
  22.         struct Node  
  23.         {  
  24.             Object data;//链表内的有效数据  
  25.             Node* prev;//指向前一个数据  
  26.             Node* next;//指向下一个数据  
  27.             Node(const Object& d = Object(), Node* p = nullptr, Node* n = nullptr): data(d),prev(p),next(n){}  
  28.         };  
  29.     public:  
  30.         //const的迭代器  
  31.         class const_iterator  
  32.         {  
  33.         public:  
  34.             //默认构造函数  
  35.             const_iterator():current(nullptr){}  
  36.             //获得Object对象  
  37.             const Object& operator*()const  
  38.             {  
  39.                 return retrieve();  
  40.             }  
  41.             //自增,前缀自增  
  42.             const_iterator& operator++()  
  43.             {  
  44.                 current = current->next;  
  45.                 return *this;  
  46.             }  
  47.             //自增,后缀自增,这里的int只是作为一种标志来使用,并没有什么卵用  
  48.             const_iterator operator++(int)  
  49.             {  
  50.                 const_iterator old = *this;//原来的数据  
  51.                 ++(*this);//调用前缀版本的自增  
  52.                 return old;//返回原来的数据  
  53.             }  
  54.             //自减,前缀自增  
  55.             const_iterator& operator--()  
  56.             {  
  57.                 current = current->prev;  
  58.                 return *this;  
  59.             }  
  60.             //自减,后缀自减,这里的int只是作为一种标志来使用,并没有什么卵用  
  61.             const_iterator operator--(int)  
  62.             {  
  63.                 const_iterator old = *this;//原来的数据  
  64.                 --(*this);//调用前缀版本的自增  
  65.                 return old;//返回原来的数据  
  66.             }  
  67.   
  68.             //==重载  
  69.             bool operator==(const const_iterator& rhs) const  
  70.             {  
  71.                 return current == rhs.current;  
  72.             }  
  73.             //!=重载  
  74.             bool operator!=(const const_iterator& rhs)const  
  75.             {  
  76.                 return !(*this == rhs);  
  77.             }  
  78.         protected:  
  79.             const List<Object> * theList;//把列表传了进来,作为检测的时候使用的  
  80.             Node* current;//迭代器所指向的结点  
  81.             //获得结点的数据,方便给子类使用  
  82.             Object& retrieve()const  
  83.             {  
  84.                 return current->data;  
  85.             }  
  86.             void assertIsValid()const//检测指针是否合法  
  87.             {  
  88.                 if (!theList || !current || current == theList->head)//检测列表为空,当前指针为空,当前在头结点  
  89.                 {  
  90.                     throw ("IteratorOutOfBoundsException");//抛出异常,这里应该使用Exception相关类  
  91.                 }  
  92.             }  
  93.             //构造函数  
  94.             const_iterator(const List<Object>& lst, Node* p):theList(&lst), current(p){}  
  95.             //友元类,方便在List中访问  
  96.             friend class List<Object>;  
  97.               
  98.         };  
  99.         //迭代器  
  100.         class iterator: public const_iterator  
  101.         {  
  102.         public:  
  103.             iterator(){}//默认构造函数  
  104.             //*重载  
  105.             Object& operator*()  
  106.             {  
  107.                 //return retrieve();无法通过编译  
  108.                 return this->retrieve();//也可以用域作用符  
  109.             }  
  110.             //*重载  
  111.             const Object& operator*()const  
  112.             {  
  113.                 return const_iterator::operator*();//调用父类函数  
  114.             }  
  115.             //自增,前缀  
  116.             iterator operator++()  
  117.             {  
  118.                 //current = current->next;无法通过编译  
  119.                 this->current = this->current->next;//也可以用域作用符  
  120.                 return *this;  
  121.             }  
  122.             //自增,后缀  
  123.             iterator operator++(int)  
  124.             {  
  125.                 iterator old = *this;  
  126.                 ++(*this);  
  127.                 return old;  
  128.             }  
  129.             //自减,前缀  
  130.             iterator operator--()  
  131.             {  
  132.                 this->current = this->current->prev;//也可以用域作用符  
  133.                 return *this;  
  134.             }  
  135.             //自减,后缀  
  136.             iterator operator--(int)  
  137.             {  
  138.                 iterator old = *this;  
  139.                 --(*this);  
  140.                 return old;  
  141.             }  
  142.   
  143.             //==重载  
  144.             bool operator==(const iterator& rhs) const  
  145.             {  
  146.                 return this->current == rhs.current;  
  147.             }  
  148.             //!=重载  
  149.             bool operator!=(const iterator& rhs)const  
  150.             {  
  151.                 return !(*this == rhs);  
  152.             }  
  153.   
  154.         protected:  
  155.             //构造函数,list内部调用的  
  156.             iterator(const List<Object>& lst, Node* p) :const_iterator (lst, p){}  
  157.             //友元类  
  158.             friend class List<Object>;  
  159.         };  
  160.           
  161.     public:  
  162.         //默认构造函数  
  163.         List()  
  164.         {  
  165.             init();//初始化  
  166.         }  
  167.         //复制构造函数  
  168.         List(const List& rhs)  
  169.         {  
  170.             init();  
  171.             *this = rhs;  
  172.         }  
  173.         //析构函数  
  174.         ~List()  
  175.         {  
  176.             clear();//清空链表  
  177.             //释放掉两个指针的内存  
  178.             delete head;  
  179.             delete tail;  
  180.         }  
  181.         //复制赋值运算符  
  182.         const List& operator=(const List& rhs)  
  183.         {  
  184.             //如果是相同的地址,就不用复制了。  
  185.             if (this == &rhs)  
  186.             {  
  187.                 return *this;  
  188.             }  
  189.             clear();//清空当前的链表  
  190.             //按顺序一个一个复制进链表中  
  191.             for (const_iterator iter = rhs.begin(); iter != rhs.end(); ++iter)  
  192.             {  
  193.                 push_back(*iter);  
  194.             }  
  195.             return *this;  
  196.         }  
  197.         //获取第一个迭代器  
  198.         iterator begin()  
  199.         {  
  200.             return iterator(*this, head->next);//head是不存放数据的  
  201.         }  
  202.         //获取第一个数据的迭代器  
  203.         const_iterator begin() const  
  204.         {  
  205.             return const_iterator(*this, head->next);//head是不存放数据的  
  206.         }  
  207.         //获取最后一个迭代器  
  208.         iterator end()  
  209.         {  
  210.             return iterator(*this, tail);//在STL里面,end返回的是超界地址,而不是最后一个数据的地址,这里是tail  
  211.         }  
  212.         const_iterator end()const  
  213.         {  
  214.             return const_iterator(tail);//在STL里面,end返回的是超界地址,而不是最后一个数据的地址,这里是tail  
  215.         }  
  216.         //获得链表的大小  
  217.         int size()const  
  218.         {  
  219.             return theSize;  
  220.         }  
  221.         //是否为空链表  
  222.         bool empty()const  
  223.         {  
  224.             return theSize == 0;  
  225.         }  
  226.         //清空整个列表  
  227.         void clear()  
  228.         {  
  229.             while (!empty())  
  230.             {  
  231.                 pop_front();//一个一个从表头开始删除。  
  232.             }  
  233.         }  
  234.         //第一个数据的迭代器  
  235.         Object& front()  
  236.         {  
  237.             return *begin();  
  238.         }  
  239.         //第一个数据的迭代器  
  240.         const Object& front()const  
  241.         {  
  242.             return *begin();  
  243.         }  
  244.         //最后一个数据的迭代器。  
  245.         Object& back()  
  246.         {  
  247.             return *(--end());//end()返回的是超界迭代器,所以要自减才能获得最后一个数据  
  248.         }  
  249.         //在表头插入数据  
  250.         void push_front(const Object& x)  
  251.         {  
  252.             insert(begin(), x);//因为head和tail都是不放数据的,所以无论在哪里插入,都是指定表中的位置插入数据  
  253.         }  
  254.         //在表尾插入收据  
  255.         void push_back(const Object& x)  
  256.         {  
  257.             insert(end(), x);  
  258.         }  
  259.         //弹出最开始的数据  
  260.         void pop_front()  
  261.         {  
  262.             erase(begin());  
  263.         }  
  264.         //弹出最后的数据  
  265.         void pop_back()  
  266.         {  
  267.             erase( --end() );  
  268.         }  
  269.         //在迭代器的位置插入数据  
  270.         iterator insert(iterator iter, const Object& x)  
  271.         {  
  272.             iter.assertIsValid();//检测迭代器是否合法  
  273.             if (iter.theList != this)//检测是否同一个链表的  
  274.             {  
  275.                 throw ("IteratorMismatchException");  
  276.             }  
  277.             Node* p = iter.current;//当前的指针,会被压后一个  
  278.             theSize++;//链表大小+1  
  279.             //p的前一个指针是新的节点,p的原来的前一个指针的后一个指针指向新的节点。  
  280.             return iterator(*this, p->prev = p->prev->next = new Node(x, p->prev, p));//构建新的指针  
  281.         }  
  282.         //erase函数,删除迭代器指向的节点,这个很重要,具体的实现,决定了for循环中删除数据的写法。  
  283.         iterator erase(iterator iter)  
  284.         {  
  285.             Node* p = iter.current;  
  286.             iterator retVal(*this, p->next);  
  287.             p->prev->next = p->next;  
  288.             p->next->prev = p->prev;  
  289.             delete p;//这个写法里面,P指向的节点已经被删除了,  
  290.             theSize--;//减少一  
  291.             return retVal;//返回的是下一个指针。  
  292.         }  
  293.         //删除区间内的节点  
  294.         iterator erase(iterator start, iterator end)  
  295.         {  
  296.             for (iterator iter = start ; iter!= end; )  
  297.             {  
  298.                 iter = erase(iter);//删除之后,返回的是下一个数据,所以这个for循环里面,是不需要iter++的。  
  299.             }  
  300.         }  
  301.     private:  
  302.         int theSize;  
  303.         Node* head;  
  304.         Node* tail;  
  305.         //初始化,把构造函数里面的内容抽出来  
  306.         void init()  
  307.         {  
  308.             //创建了两个节点,把节点指针互相指向,这是一个空链表  
  309.             theSize = 0;  
  310.             head = new Node;  
  311.             tail = new Node;  
  312.             head->next = tail;//指向结尾  
  313.             tail->prev = head;  
  314.         }  
  315.     };  
  316. }  
  317. #endif /* defined(__HelloWorld__List__) */  
写的过程中,发现还是有好多好多细节要实现的,其实非常繁琐。

估计还有很多很多地方是没有实现的,例如异常检测,还是少了点。

不过可以大致看到原理。

再写个简单的测试程序:

[cpp] view plain copy
  1. //  
  2. //  List.cpp  
  3. //  HelloWorld  
  4. //  csdn blog:http://blog.csdn.net/u012175089  
  5. //  Created by feiyin001 on 17/1/7.  
  6. //  Copyright (c) 2017年 FableGame. All rights reserved.  
  7. //  
  8.   
  9. #include "List.h"  
  10. #include <iostream>  
  11. using namespace Fable;  
  12. int main(int argc, char* argv[])  
  13. {  
  14.     List<int> li;  
  15.     for (int i = 0; i < 100; i++)  
  16.     {  
  17.         li.push_back(i);  
  18.     }   
  19.      
  20.     for ( List<int>::iterator iter = li.begin(); iter != li.end(); )  
  21.     {  
  22.         if (*iter % 3 == 0)  
  23.         {  
  24.             iter = li.erase(iter);  
  25.         }  
  26.         else  
  27.         {  
  28.             std::cout << *iter << std::endl;  
  29.             ++iter;  
  30.         }  
  31.     }  
  32.     return 0;  
  33. }  

原创粉丝点击