循环链表的C++实现

头文件:

 1 //功能代码已经全部改写完成了,只剩下的就是测试部分了,单链表改循环链表还是很容易改的!
 2 //采用模板类来写的代码,不能分开写!
 3 
 4 #ifndef LINKEDCircList_H
 5 #define LINKEDCircList_H
 6 
 7 template <class T>
 8 struct CircLinkNode
 9 {
10     T data;
11     CircLinkNode<T> *link;
12     CircLinkNode(CircLinkNode<T> *ptr=NULL){link=ptr;}
13     CircLinkNode(const T& item,CircLinkNode<T> *ptr=NULL){data=item;link=ptr;}
14     //初始化的方式很有特性啊
15 };
16 
17 template <class T>
18 class CircList
19 {
20 public:
21     CircList();
22     CircList(const T &x);
23     CircList(CircList<T>& L);               //复制构造函数
24     ~CircList(){makeEmpty();}
25     void makeEmpty();
26     int Length()const;
27     CircLinkNode<T> *getHead()const {return first;}        //返回头结点的地址
28     CircLinkNode<T> *Search(T &x);
29     CircLinkNode<T> *Locate(int i);
30     bool getData(int i,T &x);
31     bool setData(int i,T &x);
32     bool Insert(int i,T &x);
33     bool Remove(int i,T &x);
34     void Sort();
35     void inputFront(T endTag);
36     void inputRear(T endTag);
37     void output();
38     CircList<T>& operator=(CircList<T>&L);
39 protected:
40     CircLinkNode<T> *first;
41     CircLinkNode<T> *last;
42 };
43 //#include "LinkedCircList.hpp"
44 #endif
View Code

实现文件:

  1 #include <iostream>
  2 #include <stdlib.h>
  3 #include "LinkedCircList.h"
  4 using namespace std;
  5 
  6 template <class T>
  7 CircList<T>::CircList()
  8 {
  9     first=new CircLinkNode<T>;                  //创建头结点
 10     last=first;
 11     last->link=first;
 12 };
 13 
 14 template <class T>
 15 CircList<T>::CircList(const T &x)
 16 {
 17     first=new CircLinkNode<T>(x);               //头节点中是链表的长度
 18     last=first;
 19     first->link=NULL;
 20     last->link=first;
 21 };
 22 
 23 //复制构造函数中,指针方面还是有问题,不过不知道如何调试
 24 template <class T>
 25 CircList<T>::CircList(CircList<T>& L)
 26 {
 27     T value;
 28     CircLinkNode<T> *srcptr=L.first;            //获取附加头节点
 29     value=srcptr->data;                         //取得附加头节点的值
 30     CircLinkNode<T> *desptr=first=new CircLinkNode<T>(value);                 //构造函数的指针
 31     if (srcptr->link==L.first)               //如果被复制的链表为空链表的情况下
 32     {
 33         last=desptr;
 34         last->link=first;
 35     }
 36     else
 37     {
 38         //desptr=desptr->link;
 39         srcptr=srcptr->link;
 40         while(srcptr->link!=L.first)                            //找到尾指针,尾指针指向first;
 41         {
 42             value=srcptr->data;
 43             desptr->link=new CircLinkNode<T>(value);
 44             desptr=desptr->link;
 45             srcptr=srcptr->link;
 46         }
 47         value=srcptr->data;
 48         desptr->link=new CircLinkNode<T>(value);
 49         last=desptr->link;
 50         last->link=first;
 51     }
 52 };
 53 
 54 template <class T>
 55 void CircList<T>::makeEmpty()
 56 {
 57     CircLinkNode<T> *q;
 58     CircLinkNode<T> *p=first;             //仅仅作为一种标记
 59     while(p->link!=first)
 60     {
 61         p=first;
 62         q=first->link;
 63         first->link=q->link;
 64         delete q;              //仅仅保留表头节点
 65     }
 66 };
 67 
 68 template <class T>
 69 int CircList<T>::Length()const                  //不能改变的最好还是用const修饰符
 70 {
 71     CircLinkNode<T> *p=first->link;            //从第一个节点开始算起,也就是说不算附加头结点啦
 72     int count=1;
 73     while(p->link!=first)
 74     {
 75         p=p->link;
 76         count++;
 77     }
 78     return count;
 79 };
 80 
 81 
 82 template <class T>
 83 CircLinkNode<T> *CircList<T>::Locate(int i)
 84 {
 85     if(i<0)
 86         cout<<"输入的位置不存在!"<<endl;
 87     CircLinkNode<T> *current=first->link;
 88     int k=1;
 89     while (current!=first&&k<i)
 90     {
 91         current=current->link;
 92         k++;
 93     }
 94     if (current==first&&k<i)
 95     {
 96         cout<<"您要查找的位置不存在"<<endl;
 97         current=NULL;
 98     }
 99     return current;
100 };
101 
102 template <class T>
103 CircLinkNode<T> *CircList<T>::Search(T &x)
104 {
105     CircLinkNode<T> *p=first->link;
106     while(p!=first)
107     {
108         if(p->data==x)
109             return p;
110         else
111         {
112             p=p->link;
113         }
114     }
115     if (p==first)
116     {
117         p=NULL;
118         return p;               //没有找到就返回空指针
119     }
120 };
121 
122 template <class T>
123 bool CircList<T>::getData(int i,T& x)            //找到找不到,找到是否符合!
124 {
125     if (i<0)
126     {
127         cout<<"The "<<i<<"is not illegal!"<<endl;
128         return false;
129     }
130     CircLinkNode<T> *current=Locate(i);
131     if (x==current->data)
132     {
133         return true;
134     }
135     else
136         return false;
137 };
138 
139 template <class T>
140 bool CircList<T>::setData(int i,T &x)              //修改数据
141 {
142     if (i<0)
143     {
144         cout<<"i is illegal!";
145         return false;
146     }
147     CircLinkNode<T> *current=Locate(i);
148     current->data=x;
149     return true;
150 };
151 
152 template <class T>
153 bool CircList<T>::Insert(int i,T &x)
154 {
155     CircLinkNode<T> *current=Locate(i-1);
156     CircLinkNode<T> *newNode=new CircLinkNode<T>(x);            //新建节点
157     newNode->link=current->link;
158     current->link=newNode;
159     return true;
160 };
161 
162 template <class T>
163 bool CircList<T>::Remove(int i,T &x)                //删除节点!的确是删除了,但是总是感觉不知道是删除了哪个节点呢
164 {
165     CircLinkNode<T> *current=Locate(i-1);
166     if (current->link==first)               //不能删除尾节点,头节点是肯定删除不掉的
167     {
168         cout<<"i is not illegal!";
169         return false;
170     }
171     CircLinkNode<T> *del=new CircLinkNode<T>;
172     del=current->link;
173     current->link=del->link;
174     x=del->data;
175     delete del;
176     return true;
177 }
178 
179 template <class T>
180 void CircList<T>::output()
181 {
182     CircLinkNode<T> *current = first->link;                         //first->link找不到
183     while(current!=first)                                           //这里内存泄露,也就是说,current指针是没有指向的内容的 
184     {
185         cout<<current->data<<endl;
186         current=current->link;
187     }
188 
189 };
190 
191 /**
192 template <class T>
193 CircList<T>& CircList<T>::operator=(CircList<T> &L)
194 {
195     T value;
196     CircLinkNode<T> *srcptr=L.first;
197     CircLinkNode<T> *destptr=first;                //很简单的一个错误,在这里为destprt分配了一个空间,但是在循环里面,再次为desptr分配了一个空间
198     value=srcptr->data;
199     destptr=new CircLinkNode<T>(value);
200     first=destptr;
201     destptr=destptr->link;
202     srcptr=srcptr->link;                        //头结点出现重大错误!
203     while(srcptr!=L.last)
204     {
205         value=srcptr->data;
206         destptr=new CircLinkNode<T>(value);
207         destptr=destptr->link;
208         srcptr=srcptr->link;
209     }
210     value=srcptr->data;
211     destptr=new CircLinkNode<T>(value);
212     last=destptr;
213     last->link=first;
214     return *this;
215     //当调用一个成员函数时,有一个指向请求这个调用的对象的指针作为一个参数将自动被传送给这个函数,这个指针叫做this.
216 };
217 **/
218 
219 template <class T>
220 CircList<T>& CircList<T>::operator=(CircList<T> &L)
221 {
222     T value;
223     CircLinkNode<T> *srcptr=L.first;            //获取附加头节点
224     value=srcptr->data;                         //取得附加头节点的值
225     CircLinkNode<T> *desptr=first=new CircLinkNode<T>(value);                 //构造函数的指针
226     if (srcptr->link==L.first)               //如果被复制的链表为空链表的情况下
227     {
228         last=desptr;
229         last->link=first;
230     }
231     else
232     {
233         //desptr=desptr->link;
234         srcptr=srcptr->link;
235         while(srcptr->link!=L.first)                            //找到尾指针,尾指针指向first;
236         {
237             value=srcptr->data;
238             desptr->link=new CircLinkNode<T>(value);
239             desptr=desptr->link;
240             srcptr=srcptr->link;
241         }
242         value=srcptr->data;
243         desptr->link=new CircLinkNode<T>(value);
244         last=desptr->link;
245         last->link=first;
246     }
247     cout<<"头指针指向的内容:"<<first<<endl;
248 
249     return *this;
250 };
251 
252 //前插法,需要专门处理一次才能进入while循环中。。。。。。。
253 template <class T>
254 void CircList<T>::inputFront(T endTag)
255 {
256     CircLinkNode<T> *newNode;T val;
257     makeEmpty();                         //先置空
258 
259     cin>>val;
260     if (val!=endTag)
261     {
262         newNode=new CircLinkNode<T>(val);
263     }
264     if (newNode==NULL)
265     {
266         cout<<"存储分配错误!"<<endl;
267         exit(1);
268     }
269     last->link=newNode;
270     last=newNode;
271     last->link=first;
272     cin>>val;
273     while(val!=endTag)
274     {
275         newNode=new CircLinkNode<T>(val);
276         if (newNode==NULL)
277         {
278             cout<<"存储分配错误!"<<endl;
279             exit(1);
280         }
281         newNode->link=first->link;
282         first->link=newNode;           //新建立元素总是在前面
283         cin>>val;
284     }
285 };
286 
287 template <class T>
288 void CircList<T>::inputRear(T endTag)
289 {
290     CircLinkNode<T> *newNode;
291     newNode=last=first;                      //这里附加头结点只能为空,因为附加头结点完全没有办法输入!
292     T val;
293     //makeEmpty();                          //已经在主程序里清空过了。。。
294     cin>>val;
295     while(val!=endTag)
296     {
297         newNode=new CircLinkNode<T>(val);
298         if (newNode==NULL)
299         {
300             cout<<"存储分配错误!"<<endl;
301             exit(1);
302         }
303         last->link=newNode;
304         last=newNode;
305         cin>>val;
306     }
307     last->link=first;
308 };
View Code

测试文件:

  1 #include <iostream>
  2 #include "LinkedCircList.cpp"
  3 using namespace std;
  4 
  5 int main()
  6 {
  7     CircList<int> a;
  8     CircList<int> b(10);
  9     cout<<"以前插法建立循环链表,并且以0符号结束!"<<endl;
 10     b.inputFront(0);
 11     cout<<"输出刚建立的循环链表为:"<<endl;
 12     b.output();
 13 
 14     cout<<"测试复制构造函数c"<<endl;
 15     CircList<int> c(b);
 16     cout<<"输出复制构造函数c"<<endl;
 17     c.output();
 18     cout<<"测试重载‘=’运算"<<endl;
 19     a=b;
 20     cout<<"输出a链表"<<endl;
 21     a.output();
 22 
 23     cout<<"清空该循环链表"<<endl;
 24     b.makeEmpty();
 25     cout<<"以后插法建立循环链表,并以符号0结束!"<<endl;
 26     b.inputRear(0);
 27     cout<<"输出刚建立的循环链表"<<endl;
 28     b.output();
 29     cout<<"输出链表的长度"<<endl;
 30     cout<<b.Length()<<endl;
 31     cout<<"请输入要查找的元素"<<endl;
 32     int x;
 33     CircLinkNode<int> *p;
 34     cin>>x;
 35     p=b.Search(x);
 36     if (p!=NULL)
 37     {
 38         cout<<"找到该元素,在链表中!"<<endl;
 39     }
 40     else
 41         cout<<"你要查找的元素不存在!"<<endl;
 42     cout<<"请输入要查找的元素位置"<<endl;
 43     int i;                              //使用没有初始化的变量,运行会出现严重的错误,但是编译时可以通过的
 44     cin>>i;
 45     p=b.Locate(i);
 46     if (p!=NULL)
 47     {
 48         cout<<"在链表中找到该位置"<<endl;
 49     }
 50     else
 51         cout<<"您输入的位置不正确"<<endl;
 52     cout<<"请输入您要查找的位置和数据"<<endl;
 53     int m,n;
 54     cin>>m>>n;
 55     if (b.getData(m,n)==true)
 56     {
 57         cout<<"正确找到!"<<endl;
 58     }
 59     else
 60         cout<<"您输入的位置和数据不匹配"<<endl;
 61     cout<<"请输入要插入的位置和数据"<<endl;
 62     cin>>m>>n;
 63     if (b.setData(m,n)==true)
 64     {
 65         cout<<"插入成功!"<<endl;
 66     } 
 67     else
 68     {
 69         cout<<"插入失败!"<<endl;
 70     }
 71     cout<<"输出该循环链表"<<endl;
 72     b.output();
 73     cout<<"请输入要插入的节点"<<endl;
 74     cin>>m>>n;
 75     if (b.Insert(m,n)==true)
 76     {
 77         cout<<"插入成功"<<endl;
 78     } 
 79     else
 80     {
 81         cout<<"插入失败"<<endl;
 82     }
 83     cout<<"插入后输出"<<endl;
 84     b.output();
 85     cout<<"请输入要删除的节点"<<endl;
 86     cin>>m>>n;
 87     if (b.Remove(m,n)==true)
 88     {
 89         cout<<"删除成功"<<endl;
 90     } 
 91     else
 92     {
 93         cout<<"删除失败"<<endl;
 94     }
 95     cout<<"删除节点以后"<<endl;
 96     b.output();
 97     cout<<"将链表b的全部复制给a"<<endl;
 98     a=b;
 99     cout<<"输出a链表"<<endl;
100     a.output();
101     cout<<"测试完成"<<endl;
102     return 0;
103 }
View Code

将单链表改为循环链表,只需要注意last指针就可以了,last->link=first,这是循环链表的关键,晚点我会把循环链表的典型运用,约瑟夫环代码的实现也发上来的

posted @ 2013-10-31 14:50  ruirui610  阅读(755)  评论(0编辑  收藏  举报