实现一个简单的c++ list容器(含sort排序 链表归并算法实现)

      这个其实是很久之前写的,最近参加面试,复习C++,感觉不错,顺便翻出来整理了一遍。

使用过容器的都清楚,容器说白了其实就是一个类模板,它可以存放各种类型。而要对容器元素访问就要通过一个叫

迭代器的东西,迭代器在使用上和指针很相似。因此list容器的实现也主要是对类模板和迭代器的设计,当然也少不了

链表操作,因为list容器是通过链表来存放数据。

一、节点类

 该类主要是存放容器内元素的数据(data)

 1 /*
 2 *节点类 
 3 */ 
 4 template<typename elemType>
 5 class Node
 6 { 
 7      private:
 8         elemType data;
 9         Node *next;
10      public:
11         Node():next(NULL)
12         {}
13         Node(elemType data):data(data),next(NULL) 
14         {}
15         //类Iter、Mylist要设为友元 
16         friend class Iter<elemType>;
17         friend class Mylist<elemType>;
18 
19 };

二、迭代器类

迭代器的实现。看了下面的实现你或许就明白为什么说迭代器和指针很相似,因为它重载了指针的一些基本操作如 ‘*’,'->'等。

记录一个我当时一个很低级的错误:

在实现'->'重载时,我本来是通过间接访问节点数据:

1 elemType * operator ->()const
2  {//重载迭代器->操作  
3     return &(node.getData());
4  }

但这显然是不行的,因为getData()返回的是一个临时变量,对其取到的地址,并非原节点数据的地址。因此要把迭代器类设为节点类的友元类,直接访问节点数据。

如下:

1 elemType * operator ->()const
2 {//重载迭代器->操作  
3     return &(node->data);
4 }

 

 1 /*
 2 *迭代器类
 3 */
 4 template<typename elemType>
 5 class Iter
 6 {
 7      private:
 8         Node<elemType> *node;        
 9      public:
10         Iter(){}
11         Iter(Node<elemType>* a):node(a){}
12         
13         elemType  operator *() const 
14         {//*重载
15             return (node->data);
16         }
17         elemType * operator ->()const
18         {//重载迭代器->操作  
19             return &(node->data);
20         } 
21         bool operator !=(Iter<elemType> &a)const
22         {//重载迭代器!=操作
23             return node != a.node;
24         } 
25         bool operator == (Iter<elemType> &a)const 
26         {//重载迭代器==操作 
27             return node == a.node; 
28         }
29         Iter<elemType>  operator++(int) 
30         {//重载迭代器++作 
31             Iter<elemType>tmp = *this; 
32             this->node = this->node->next;
33             return tmp;
34         }
35         Node<elemType> * getNode(){ return node;}
36 };

三、容器类

在这里实现一些基本的容器操作,如push_front()、push_back()、erase()、sort()等。重点讲一下sort()的实现也是花了我最多时间的地方。

本来想用冒泡直接来的,后来发现c++中list容器的sort()函数是通过归并算法实现的,因此我也采用归并DIY一个。

冒泡ON^2,相比于归并最坏情形运行时间:ONlogN,当问题规模变大时,冒泡显然是吃不消的。

首先是递归二分链表,递归到最后会把链表分为一个个长度为1的单独节点,然后再有序地往上归并这些节点,把长度为1的扩到2,2扩到4,4扩到8……(这

也是分治思想的精髓)。为了提高二分的效率,二分链表时使用了两个步长一快一慢的指针,快指针的遍历的速度是慢指针的两倍,这样当快指针遍历

到末结点时,慢指针刚好指在了链表的中间结点处。

为了对sort()函数的封装,就要使用函数指针了。容器内定义一个函数指针,测试程序写好cmp()排序方式函数,通过sort(cmp)调用,初始化容器内的

函数指针,使其指向cmp函数。(如果你没使用过STL中的sort()函数,可能你会不明白我在说什么。。)

 

  1 /*
  2 *容器类
  3 */
  4 template<typename elemType>
  5 class Mylist
  6 {
  7     private:
  8         int _size;//容器长度
  9         Node<elemType> *head;//指向头结点(不放数据)
 10         Node<elemType> *_end;//指向容器的最后一个元素
 11         bool (*cmp)(elemType a,elemType b);//指针函数,指向给定排序方式的函数
 12         
 13     public:
 14         Mylist()
 15         {
 16             head = new Node<elemType>();
 17             head->next = NULL;
 18             _end = head;
 19             this->_size = 0;
 20         }
 21         ~Mylist()
 22         {
 23             Node<elemType> *p,*tem;
 24             p = head;
 25             while( p != NULL)
 26             {
 27                 tem = p;
 28                 p = p->next;
 29                 delete tem;
 30             }
 31         }
 32         typedef Iter<elemType> iterator;//定义迭代器类型 
 33         void push_back(elemType data)
 34         {//在容器的尾部添加元素
 35             _end->next = new Node<elemType>(data);                           
 36             _end = _end->next;
 37             _size++;
 38         }
 39         void push_front(elemType data)
 40         {//在容器的前端添加元素
 41             Node<elemType> *p = new Node<elemType>(data); 
 42             p->next = head->next;
 43             head->next = p;
 44             if(head == _end)
 45                 _end = p;
 46             _size++;
 47         }
 48         int size()
 49         {//返回容器中的元素个数
 50             return _size;
 51         }
 52         iterator begin()
 53         {//返回一个迭代器,它指向容器的第一个元素
 54             iterator iter(head->next);
 55             return iter;
 56         }
 57         iterator end()
 58         {//返返回一个迭代器,它指向容器的最后一个元素的下一位置
 59             iterator iter(_end->next);
 60             return iter;
 61         }
 62         bool erase(iterator iter)
 63         {//删除迭代器 iter 所指向的元素
 64             Node<elemType> *p1 = iter.getNode();
 65             Node<elemType> *p2 = head;
 66             while(p2->next != NULL)
 67             {
 68                 if(p2->next == p1)
 69                 {
 70                     p2->next = p1->next;
 71                     if(_end == p1)
 72                         _end = p2;
 73                     delete p1;
 74                     p1 = NULL;
 75                     return true;
 76                 }
 77                 p2 = p2->next;
 78             }
 79             return false;
 80         }
 81         void clear()
 82         {//清空容器
 83             Node<elemType> *p,*tem;
 84             p = head->next;
 85             while( p != NULL)
 86             {
 87                 tem = p;
 88                 p = p->next;
 89                 delete tem;
 90             }
 91             head->next = NULL;
 92             _end = head;
 93         }
 94         /*******以下采用归并算法实现了容器的排序操作*****/
 95         void sort(bool (*cmp)(elemType ,elemType ));
 96         Node<elemType>* mergeSort(Node<elemType> *temHead);
 97         Node<elemType>* merge(Node<elemType> *first,Node<elemType> *second);
 98 };
 99 
100 /*
101 *初始化排序函数指针
102 */
103 template<typename elemType>
104 void Mylist<elemType>::sort(bool (*cmp)(elemType ,elemType ))
105 {
106     this->cmp = cmp; 
107     head->next=mergeSort(head->next);
108 }
109 
110 /*
111 *二分链表
112 */
113 template<typename elemType>
114 Node<elemType>* Mylist<elemType>::mergeSort(Node<elemType> *temHead)
115 {
116     Node<elemType> *first;  
117     Node<elemType> *second;  
118     first=temHead;  
119     second=temHead;  
120     if(first==NULL||first->next==NULL)
121     {  //若只有一个节点直接返回(递归临界) 
122         return first;  
123     }  
124     while(second->next!=NULL && second->next->next!=NULL)
125     {  //利用一快一慢的指针把链表二分
126         first=first->next; //慢指针 
127         second=second->next->next;//快指针
128     }  
129     if(first->next!=NULL)
130     {  
131         second=first->next;  
132         first->next=NULL;  
133         first=temHead;  
134     }   
135     return  merge( mergeSort(first),mergeSort(second) ); //递归二分各个子链表
136 }
137 
138 /*
139 *归并两路链表
140 */
141 template<typename elemType>
142 Node<elemType>* Mylist<elemType>::merge(Node<elemType> *first,Node<elemType> *second)
143 {//注意到这里链表first,second已经是顺序的了
144     Node<elemType> *resList=new Node<elemType>(); //开辟一个临时头节点 
145     Node<elemType> *current;  
146     current=resList;  
147     while(first!=NULL && second!=NULL)
148     {//某一条链表空时结束  
149         if((*cmp )(first->data,second->data))
150         {//根据函数指针来确定排序方式  
151             current->next=first;  
152             current=current->next;                              
153             first=first->next;  
154         }
155         else
156         {  
157             current->next=second;  
158             current=current->next;                               
159             second=second->next;            
160         }  
161     }
162                 
163     //把还剩下不空的链表继续接到临时头结点所在的链表
164     while(first!=NULL)
165     {  
166         current->next=first;   
167         current=current->next;                    
168         first=first->next;  
169     }  
170     while(second!=NULL)
171     {  
172         current->next=second;    
173         current=current->next;                             
174         second=second->next;                    
175     } 
176     current = resList->next;
177     delete resList;//记得释放头结点
178     return current;  
179 }

 

 

 

 四、测试程序

View Code
  1 #include<iostream>
  2 using namespace std;
  3 
  4 template<typename elemType>
  5 class Iter;
  6 template<typename elemType>
  7 class Mylist;
  8 
  9 /*
 10 *节点类 
 11 */ 
 12 template<typename elemType>
 13 class Node
 14 { 
 15      private:
 16         elemType data;
 17         Node *next;
 18      public:
 19         Node():next(NULL)
 20         {}
 21         Node(elemType data):data(data),next(NULL) 
 22         {}
 23         //类Iter、Mylist要设为友元 
 24         friend class Iter<elemType>;
 25         friend class Mylist<elemType>;
 26 
 27 };
 28 
 29 
 30 /*
 31 *迭代器类
 32 */
 33 template<typename elemType>
 34 class Iter
 35 {
 36      private:
 37         Node<elemType> *node;        
 38      public:
 39         Iter(){}
 40         Iter(Node<elemType>* a):node(a){}
 41         
 42         elemType  operator *() const 
 43         {//*重载
 44             return (node->data);
 45         }
 46         elemType * operator ->()const
 47         {//重载迭代器->操作  
 48             return &(node->data);
 49         } 
 50         bool operator !=(Iter<elemType> &a)const
 51         {//重载迭代器!=操作
 52             return node != a.node;
 53         } 
 54         bool operator == (Iter<elemType> &a)const 
 55         {//重载迭代器==操作 
 56             return node == a.node; 
 57         }
 58         Iter<elemType>  operator++(int) 
 59         {//重载迭代器++作 
 60             Iter<elemType>tmp = *this; 
 61             this->node = this->node->next;
 62             return tmp;
 63         }
 64         Node<elemType> * getNode(){ return node;}
 65 };
 66 
 67 /*
 68 *容器类
 69 */
 70 template<typename elemType>
 71 class Mylist
 72 {
 73     private:
 74         int _size;//容器长度
 75         Node<elemType> *head;//指向头结点(不放数据)
 76         Node<elemType> *_end;//指向容器的最后一个元素
 77         bool (*cmp)(elemType a,elemType b);//指针函数,指向给定排序方式的函数
 78         
 79     public:
 80         Mylist()
 81         {
 82             head = new Node<elemType>();
 83             head->next = NULL;
 84             _end = head;
 85             this->_size = 0;
 86         }
 87         ~Mylist()
 88         {
 89             Node<elemType> *p,*tem;
 90             p = head;
 91             while( p != NULL)
 92             {
 93                 tem = p;
 94                 p = p->next;
 95                 delete tem;
 96             }
 97         }
 98         typedef Iter<elemType> iterator;//定义迭代器类型 
 99         void push_back(elemType data)
100         {//在容器的尾部添加元素
101             _end->next = new Node<elemType>(data);                           
102             _end = _end->next;
103             _size++;
104         }
105         void push_front(elemType data)
106         {//在容器的前端添加元素
107             Node<elemType> *p = new Node<elemType>(data); 
108             p->next = head->next;
109             head->next = p;
110             if(head == _end)
111                 _end = p;
112             _size++;
113         }
114         int size()
115         {//返回容器中的元素个数
116             return _size;
117         }
118         iterator begin()
119         {//返回一个迭代器,它指向容器的第一个元素
120             iterator iter(head->next);
121             return iter;
122         }
123         iterator end()
124         {//返返回一个迭代器,它指向容器的最后一个元素的下一位置
125             iterator iter(_end->next);
126             return iter;
127         }
128         bool erase(iterator iter)
129         {//删除迭代器 iter 所指向的元素
130             Node<elemType> *p1 = iter.getNode();
131             Node<elemType> *p2 = head;
132             while(p2->next != NULL)
133             {
134                 if(p2->next == p1)
135                 {
136                     p2->next = p1->next;
137                     if(_end == p1)
138                         _end = p2;
139                     delete p1;
140                     p1 = NULL;
141                     return true;
142                 }
143                 p2 = p2->next;
144             }
145             return false;
146         }
147         void clear()
148         {//清空容器
149             Node<elemType> *p,*tem;
150             p = head->next;
151             while( p != NULL)
152             {
153                 tem = p;
154                 p = p->next;
155                 delete tem;
156             }
157             head->next = NULL;
158             _end = head;
159         }
160         /*******以下采用归并算法实现了容器的排序操作*****/
161         void sort(bool (*cmp)(elemType ,elemType ));
162         Node<elemType>* mergeSort(Node<elemType> *temHead);
163         Node<elemType>* merge(Node<elemType> *first,Node<elemType> *second);
164 };
165 
166 /*
167 *初始化排序函数指针
168 */
169 template<typename elemType>
170 void Mylist<elemType>::sort(bool (*cmp)(elemType ,elemType ))
171 {
172     this->cmp = cmp; 
173     head->next=mergeSort(head->next);
174     while(_end->next != NULL)
175     {//记得更新_end指向
176         _end = _end->next;
177     }
178 }
179 
180 /*
181 *二分链表
182 */
183 template<typename elemType>
184 Node<elemType>* Mylist<elemType>::mergeSort(Node<elemType> *temHead)
185 {
186     Node<elemType> *first;  
187     Node<elemType> *second;  
188     first=temHead;  
189     second=temHead;  
190     if(first==NULL||first->next==NULL)
191     {  //若只有一个节点直接返回(递归临界) 
192         return first;  
193     }  
194     while(second->next!=NULL && second->next->next!=NULL)
195     {  //利用一快一慢的指针把链表二分
196         first=first->next; //慢指针 
197         second=second->next->next;//快指针
198     }  
199     if(first->next!=NULL)
200     {  
201         second=first->next;  
202         first->next=NULL;  
203         first=temHead;  
204     }   
205     return  merge( mergeSort(first),mergeSort(second) ); //递归二分各个子链表
206 }
207 
208 /*
209 *归并两路链表
210 */
211 template<typename elemType>
212 Node<elemType>* Mylist<elemType>::merge(Node<elemType> *first,Node<elemType> *second)
213 {//注意到这里链表first,second已经是顺序的了
214     Node<elemType> *resList=new Node<elemType>(); //开辟一个临时头节点 
215     Node<elemType> *current;  
216     current=resList;  
217     while(first!=NULL && second!=NULL)
218     {//某一条链表空时结束  
219         if((*cmp )(first->data,second->data))
220         {//根据函数指针来确定排序方式  
221             current->next=first;  
222             current=current->next;                              
223             first=first->next;  
224         }
225         else
226         {  
227             current->next=second;  
228             current=current->next;                               
229             second=second->next;            
230         }  
231     }
232                 
233     //把还剩下不空的链表继续接到临时头结点所在的链表
234     while(first!=NULL)
235     {  
236         current->next=first;   
237         current=current->next;                    
238         first=first->next;  
239     }  
240     while(second!=NULL)
241     {  
242         current->next=second;    
243         current=current->next;                             
244         second=second->next;                    
245     } 
246     current = resList->next;
247     delete resList;//记得释放头结点
248     return current;  
249 }
250 
251 
252 bool cmp(int a, int b)
253 {//从小到大排序
254     return a <= b;
255 }
256 int main(int argc, char** argv)
257 {
258     Mylist<int> test;
259     Mylist<int>::iterator iter;
260     for(int i = 0; i < 10; i++)
261     {
262         i < 5 ? test.push_back(i): test.push_front(i);
263     }
264     cout<<"未排序:";
265     for(iter = test.begin(); iter != test.end(); iter++)
266     {
267         printf("%d ", *iter);
268     }
269     cout<<endl;
270     test.sort(cmp);
271     cout<<"已排序:";
272     for(iter = test.begin(); iter != test.end(); iter++)
273     {
274         printf("%d ", *iter);
275     }
276     cout<<endl;
277     return 0;
278 }

运行结果如下:

 

 

posted @ 2012-11-18 21:17  CoderZhuang  阅读(6347)  评论(3编辑  收藏  举报