C++双向循环链表
先说一说双向循环链表的逆置,网上搜了一箩筐,用VS2017,基本上不成功,尽管明白道理是怎么回事,但是总感觉,不像c++的类,感觉用起来还得传指针啊,传链表啊等参数,不太像双向循环链表类的专属函数。虽然c语言写出来双向循环链表最好,但是既然学了c++,就尽量用一下c++的特点,能用多少是多少,也有利于对c++理解。好了废话不多说,凉一凉自己写的一般一般的双向循环链表吧。
1 #include<iostream> 2 3 using namespace std; 4 5 template<class T> class DoubleLinkedList; 6 7 template<class T> 8 class MyNode 9 { 10 friend class DoubleLinkedList<T>; 11 private: 12 T elem; 13 MyNode *prev; 14 MyNode *next; 15 MyNode(){} 16 MyNode(const T &theelem) 17 :elem(theelem) { 18 prev = NULL; 19 next = NULL; 20 } 21 }; 22 23 template<class T> 24 class DoubleLinkedList 25 { 26 public: 27 DoubleLinkedList() 28 { 29 first = new MyNode<T>(); 30 first->prev = first->next = first; 31 } 32 ~DoubleLinkedList(){ makeEmpty(); } 33 34 bool IsEmpty(); // 判断链表是否为空 35 void makeEmpty(); // 清空链表 36 int Length(); // 计算链表的长度 37 void Insert(int index, const T &x); // 按照索引插入值(节点) 38 void Push_head(const T &x); // 向链表的头部插入值 头插法 39 void Push_back(const T &x); // 向链表的尾部插入值 尾插法 40 void Delete(T x); // 按值删除节点 41 void Index_Delete(const int &n); // 按索引删除节点 42 void Invert(); // 逆置 43 void Concatenate(DoubleLinkedList<T> &b); // 连接链表 44 void show(); // 显示链表,这只是方便,一般得做成迭代器 45 private: 46 MyNode<T> *first; 47 }; 48 template<class T> 49 bool DoubleLinkedList<T>::IsEmpty() 50 { 51 return first == NULL; 52 } 53 54 template<class T> 55 void DoubleLinkedList<T>::makeEmpty() 56 { 57 MyNode<T> *p; 58 MyNode<T> *pNode = first->next; 59 while (pNode != first) 60 { 61 p = pNode; 62 pNode = pNode->next; 63 delete p; 64 } 65 delete first; 66 first = NULL; 67 } 68 69 template<class T> 70 int DoubleLinkedList<T>::Length() 71 { 72 int size = 0; 73 MyNode<T> * p = first->next; 74 if (IsEmpty()) cout << "The size is 0" << endl; 75 else 76 { 77 while (p != first) 78 { 79 size++; 80 p = p->next; 81 } 82 } 83 return size; 84 } 85 86 template<class T> 87 void DoubleLinkedList<T>::Insert(int index, const T &x) 88 { 89 MyNode<T> * insertNode = new MyNode<T>(x); 90 MyNode<T> * p = first->next; 91 if (Length() < index) { 92 Push_back(x); 93 return; 94 } 95 if (index < 1) { 96 Push_head(x); 97 return; 98 } 99 int count = 1; 100 while (count < index && p != first) 101 { 102 count++; 103 p = p->next; 104 } 105 insertNode->next = p; 106 p->prev->next = insertNode; 107 insertNode->prev = p->prev; 108 p->prev = insertNode; 109 return; 110 } 111 112 template<class T> 113 void DoubleLinkedList<T>::Push_head(const T &x) 114 { 115 MyNode<T>* newNode = new MyNode<T>(x); 116 newNode->prev = first; 117 newNode->next = first->next; 118 first->next->prev = newNode; 119 first->next = newNode; 120 } 121 122 template<class T> 123 void DoubleLinkedList<T>::Push_back(const T &x) 124 { 125 MyNode<T>* newNode = new MyNode<T>(x); 126 newNode->prev = first->prev; 127 newNode->next = first; 128 first->prev->next = newNode; 129 first->prev = newNode; 130 } 131 132 template<class T> 133 void DoubleLinkedList<T>::Delete(T x) 134 { 135 MyNode<T>* p = first->next; 136 while (p->elem != x && p != first) 137 { 138 p = p->next; 139 } 140 p->next->prev = p->prev; 141 p->prev->next = p->next; 142 delete p; 143 return; 144 } 145 146 template<class T> 147 void DoubleLinkedList<T>::Index_Delete(const int &n) 148 { 149 MyNode<T>* del = NULL; 150 MyNode<T>* p = first->next; 151 int count = 0; 152 if (n < 0) 153 { 154 del = p; 155 p->next->prev = first; 156 first->next = p->next; 157 delete del; 158 return; 159 } 160 else if(n > Length()) 161 { 162 del = first->prev; 163 first->prev = del->prev; 164 del->prev->next = first; 165 delete del; 166 return; 167 } 168 while (count < n && p != first) 169 { 170 count++; 171 p = p->next; 172 } 173 del = p; 174 p->next->prev = p->prev; 175 p->prev->next = p->next; 176 delete del; 177 } 178 179 template<class T> 180 void DoubleLinkedList<T>::Invert() 181 { 182 // 我这里只考虑链表至少有一个实数节点的情况 183 // 让p指向下一个节点,再把首节点与第一个实数节点做成一个循环链表, 184 MyNode<T>* p = first->next; 185 MyNode<T>* q = p; 186 p = p->next; 187 first->prev = q; 188 q->next = first; 189 190 // 只要把接下来的节点一个一个放到头部就行了 191 while (p != first) 192 { 193 MyNode<T> *r; 194 r = p; 195 p = p->next; 196 r->prev = first; 197 r->next = first->next; 198 first->next->prev = r; 199 first->next = r; 200 } 201 } 202 203 // 我选择将循环链表b的数值直接放到所连接链表的后面,这样改变b就不会改变连接后的链表 204 205 template<class T> 206 void DoubleLinkedList<T>::Concatenate(DoubleLinkedList<T> &b) 207 { 208 MyNode<T>* p = b.first; 209 210 if(IsEmpty()) 211 { 212 first = p; 213 } 214 else if(b.IsEmpty()) 215 { 216 return; 217 } 218 else { 219 while (p->next != b.first) 220 { 221 p = p->next; 222 Push_back(p->elem); 223 } 224 return; 225 } 226 return; 227 } 228 229 template<class T> 230 void DoubleLinkedList<T>::show() 231 { 232 if (IsEmpty()) 233 { 234 return; 235 } 236 MyNode<T>* p=first->next; 237 while (p != first) 238 { 239 cout << p->elem << " "; 240 p = p->next; 241 } 242 cout << endl; 243 244 } 245 246 // 下面测试的代码没啥可看的 247 248 int main() 249 { 250 cout << "hello world!" << endl; 251 252 DoubleLinkedList<int> a; 253 a.Push_head(30); 254 a.Push_head(20); 255 a.Push_head(10); 256 a.Push_back(40); 257 a.Push_back(50); 258 a.Push_back(60); 259 a.Index_Delete(2); 260 a.show(); 261 a.Insert(1, 35); 262 a.Insert(-1, 100); 263 a.show(); 264 int size; 265 266 a.Delete(100); 267 size = a.Length(); 268 a.Index_Delete(20); 269 a.show(); 270 cout << "size: " << size << endl; 271 272 DoubleLinkedList<int> intList; 273 DoubleLinkedList<int> intList1; 274 275 intList.Push_back(1); 276 intList.Push_back(2); 277 intList.Push_back(3); 278 intList.Push_back(4); 279 280 intList1.Push_back(5); 281 intList1.Push_back(6); 282 intList1.Push_back(7); 283 intList1.Push_back(8); 284 intList.Concatenate(intList1); 285 intList.show(); 286 intList.Invert(); 287 intList.show(); 288 intList.Push_head(125); 289 intList.Push_back(21); 290 intList.Invert(); 291 intList.show(); 292 intList1.Delete(5); 293 intList1.Delete(6); 294 intList1.Delete(7); 295 intList1.Delete(8); 296 intList1.show(); 297 return 0; 298 }