循环链表的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
实现文件:

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 };
测试文件:

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