双向链表list
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了双向链表list相关的知识,希望对你有一定的参考价值。
Bi_list
之前使用STL里的数据结构做了一些小程序,自己试着实现完成基本功能。开始写的是单向链表,后来又扩展加了一个反向指针,能够在头部,尾部,中部自由增删改查,结果做出了如下程序,算是自己搞的一个数据类型吧。
在main函数中可以自行测试一下自定义的功能。
1.Bi_list.h
1 #pragma once 2 3 #include <iostream> 4 using namespace std; 5 6 7 //定义链表的节点数据类型,双向链表 8 template<typename T> 9 class List_Node 10 { 11 public: 12 T data; //链表中的数据域, T类型 13 List_Node * pNext_Node; //下一个节点指针 14 List_Node * pPrior_Node; //前一个节点指针 15 }; 16 17 18 19 20 //链表的操作方法 21 template<typename T> 22 class List 23 { 24 private: 25 List_Node<T> * pHead; //头结点指针 26 List_Node<T> * pTail; //尾节点指针 27 28 29 int iNum_List; //节点总数,除头结点 30 31 32 public: 33 List(); //构造函数初始化头结点 34 void Push_Back(T t); //向链表的尾部压入数据 35 void Push_Front(T t); //向链表的头部压入数据 36 T Get_Back() const; //获取尾部元素 37 T Get_Front() const; //获取首部元素 38 int Pop_Back(); //弹出尾部节点 39 int Pop_Front(); //弹出首部节点 40 int Insert(const int pos, T t); //在pos位置插入元素t,并返回pos 41 int Len() const; //获取链表大小 42 T Find(const int pos); //查找pos位置的元素, 并返回该元素 43 int Delete(const int pos); //pos位置删除节点,并返回pos 44 int Traverse(); //遍历节点,错误返回-1 45 int Change(const int pos, T t); //修改pos位置的元素 46 }; 47 48 template<typename T> 49 int List<T>::Change(const int pos, T t) 50 { 51 List_Node<T> * pTempt = new List_Node<T>; //新建一个临时指针,指向头指针 52 pTempt = pHead; 53 if (iNum_List > 0 && pos < iNum_List) 54 { 55 for (int i = 0; i < pos; i++) 56 pTempt = pTempt->pNext_Node; 57 pTempt->data = t; 58 59 return 0; 60 } 61 62 else 63 { 64 cout << "Change失败!返回值-1" << endl; 65 return -1; 66 } 67 } 68 69 template<typename T> 70 T List<T>::Find(const int pos) 71 { 72 if (pos >= 0 && pos < iNum_List) 73 { 74 List_Node<T> * pTempt = new List_Node<T>; //新建一个临时指针,指向头指针 75 pTempt = pHead; 76 for (int i = 0; i < pos; i++) 77 pTempt = pTempt->pNext_Node; 78 return pTempt->data; 79 } 80 else 81 { 82 cout << "Find失败!返回值-1" << endl;; 83 return -1; 84 } 85 } 86 87 88 89 //构造函数初始化 90 template<typename T> 91 List<T>::List() 92 { 93 pHead = new List_Node<T>; //初始化头结点指针,指向空 94 pHead = nullptr; 95 96 pTail = new List_Node<T>; //初始化尾结点指针,指向空 97 pTail = nullptr; 98 99 iNum_List = 0; 100 } 101 102 103 104 105 106 //pos位置删除节点,并返回pos 107 template<typename T> 108 int List<T>::Delete(const int pos) 109 { 110 if (iNum_List != 0 && pos == 0) //如果链表不为空,删除第一个节点 111 { 112 List_Node<T> * pTempt1 = new List_Node<T>; 113 pTempt1 = pHead; 114 List_Node<T> * pTempt = new List_Node<T>; 115 pTempt = pHead->pNext_Node; 116 pTempt->pPrior_Node = nullptr; 117 pHead = pTempt; 118 119 delete pTempt1; //释放删除节点 120 iNum_List--; 121 return pos; 122 } 123 124 if (iNum_List != 0 && pos == iNum_List - 1) //链表不为空,删除最后一个节点 125 { 126 List_Node<T> * pTempt1 = new List_Node<T>; 127 pTempt1 = pTail; 128 129 List_Node<T> * pTempt = new List_Node<T>; 130 pTempt = pTail->pPrior_Node; 131 pTempt->pNext_Node = nullptr; 132 pTail = pTempt; 133 134 delete pTempt1; //释放删除节点 135 iNum_List--; 136 return pos; 137 } 138 139 if (iNum_List != 0 && pos < iNum_List - 1) //链表不为空,删除中间节点 140 { 141 List_Node<T> * pTempt1 = new List_Node<T>; //新建一个临时指针,指向删除节点前的节点 142 pTempt1 = pHead; 143 144 List_Node<T> * pTempt2 = new List_Node<T>; //新建一个临时指针,指向删除节点后的节点 145 pTempt2 = pHead->pNext_Node->pNext_Node; 146 147 List_Node<T> * pTempt3 = new List_Node<T>; //新建一个临时指针,指向删除节点 148 pTempt3= pHead->pNext_Node; 149 150 for (int i = 0; i < pos - 1; i++) 151 { 152 pTempt1 = pTempt1->pNext_Node; 153 pTempt2 = pTempt2->pNext_Node; 154 pTempt3 = pTempt3->pNext_Node; 155 } 156 157 pTempt1->pNext_Node = pTempt2; 158 pTempt2->pPrior_Node = pTempt1; 159 160 delete pTempt3; 161 iNum_List--; 162 return pos; 163 } 164 } 165 166 167 168 //在pos位置插入元素t,并返回pos 169 template<typename T> 170 int List<T>::Insert(const int pos, T t) 171 { 172 if (iNum_List == 0 && pos == 0) //如果原来为空表,只需将pHead指向新建节点 173 { 174 List_Node<T> * list_node = new List_Node<T>; // 新建第一个节点 175 176 pHead = list_node; //给头指针赋值第一个节点地址 177 pTail = list_node; //将新建节点地址赋给pTail 178 179 list_node->pNext_Node = nullptr; //第一个节点后指针域为空 180 list_node->pPrior_Node = nullptr; //第一个节点前指针域为空 181 list_node->data = t; //第一个节点数据域赋值t 182 183 pHead = list_node; //给头指针赋值第一个节点地址 184 pTail = list_node; //将新建节点地址赋给pTail 185 186 iNum_List++; 187 188 return pos; 189 } 190 191 if (iNum_List > 0 && pos == 0) //如果原链表有节点,在第一个节点前插入元素 192 { 193 List_Node<T> * list_node = new List_Node<T>; 194 195 list_node->data = t; 196 list_node->pNext_Node = pHead; 197 pHead->pPrior_Node = list_node; 198 pHead = list_node; 199 200 iNum_List++; 201 202 return pos; 203 } 204 205 if (pos == iNum_List) //在结尾插入 206 { 207 List_Node<T> * list_node = new List_Node<T>; 208 list_node->data = t; 209 pTail->pNext_Node = list_node; 210 list_node->pPrior_Node = pTail; 211 list_node->pNext_Node = nullptr; 212 pTail = list_node; 213 214 iNum_List++; 215 216 return pos; 217 } 218 219 if (iNum_List > 0 && pos > 0 && pos != iNum_List) //在中间位置插入 220 { 221 List_Node<T> * pTempt1 = new List_Node<T>; //新建一个临时指针,指向插入节点前的节点 222 pTempt1 = pHead; 223 224 List_Node<T> * pTempt2 = new List_Node<T>; //新建一个临时指针,指向插入节点后的节点 225 pTempt2 = pHead->pNext_Node; 226 227 for (int i = 0; i < pos - 1; i++) 228 { 229 pTempt1 = pTempt1->pNext_Node; 230 pTempt2 = pTempt2->pNext_Node; 231 } 232 233 234 List_Node<T> * list_node = new List_Node<T>; //新建一个要插入的节点 235 list_node->data = t; 236 list_node->pNext_Node = pTempt2; 237 pTempt1->pNext_Node = list_node; 238 pTempt2->pPrior_Node = list_node; 239 list_node->pPrior_Node = pTempt1; 240 241 242 243 iNum_List++; 244 245 return pos; 246 } 247 else 248 { 249 cout << "插入失败!返回值-1" << endl; 250 return -1; 251 } 252 } 253 254 255 256 257 258 //获取尾部元素 259 template<typename T> 260 T List<T>::Get_Front() const 261 { 262 if (iNum_List > 0) 263 return pHead->data; 264 else 265 { 266 cout << "Get_Front()失败!返回值-1" << endl; 267 return -1; 268 } 269 } 270 271 272 273 274 //获取首部元素 275 template<typename T> 276 T List<T>::Get_Back() const 277 { 278 if (iNum_List > 0) 279 return pTail->data; 280 else 281 { 282 cout << "Get_Back()失败!返回值-1" << endl; 283 return -1; 284 } 285 } 286 287 288 289 290 291 292 //弹出首部节点 293 template<typename T> 294 int List<T>::Pop_Front() 295 { 296 if (iNum_List == 1) //只有一个节点,弹出即为销毁链表 297 { 298 iNum_List = 0; 299 delete pHead; 300 return 0; 301 } 302 303 if (iNum_List > 1) //不止一个节点,则弹出第一个节点,pHead自动后移 304 { 305 List_Node<T> * pTempt1 = new List_Node<T>; //新建一个临时节点,保存第一个节点地址 306 List_Node<T> * pTempt2 = new List_Node<T>; //新建一个临时节点,保存第二个节点地址 307 pTempt1 = pHead; 308 pTempt2 = pHead->pNext_Node; 309 pHead = pTempt2; 310 pTempt2->pPrior_Node = nullptr; 311 312 delete pTempt1; 313 314 iNum_List--; 315 316 return 0; 317 } 318 319 else 320 { 321 cout << "Pop_Back()失败! 返回值-1" << endl; 322 return -1; 323 } 324 325 } 326 327 328 329 //弹出尾部节点 330 template<typename T> 331 int List<T>::Pop_Back() 332 { 333 if (iNum_List == 1) //只有一个节点,弹出即为销毁链表 334 { 335 iNum_List = 0; 336 delete pHead; 337 return 0; 338 } 339 340 if (iNum_List > 1) //不止一个节点,则弹出最后一个节点,pTail自动前移 341 { 342 List_Node<T> * pTempt1 = new List_Node<T>; //新建一个临时节点,保存倒数第二个节点地址 343 List_Node<T> * pTempt2 = new List_Node<T>; //新建一个临时节点,保存最后一个节点地址 344 pTempt2 = pTail; 345 pTempt1 = pTail->pPrior_Node; 346 pTail = pTempt1; 347 pTempt1->pNext_Node = nullptr; 348 349 delete pTempt2; 350 351 iNum_List--; 352 353 return 0; 354 } 355 356 else 357 { 358 cout << "Pop_Back()失败! 返回值-1" << endl; 359 return -1; 360 } 361 } 362 363 364 365 366 //向链表的尾部压入数据 367 template<typename T> 368 void List<T>::Push_Back(T t) 369 { 370 if (iNum_List == 0) //如果是一个空链表 371 { 372 List_Node<T> * list_node = new List_Node<T>; // 新建第一个节点 373 374 375 pHead = list_node; //给头指针赋值第一个节点地址 376 pTail = list_node; //将新建节点地址赋给pTail 377 378 list_node->pNext_Node = nullptr; //第一个节点后指针域为空 379 list_node->pPrior_Node = nullptr; //第一个节点前指针域为空 380 list_node->data = t; //第一个节点数据域赋值t 381 382 iNum_List++; 383 } 384 else 385 { 386 List_Node<T> * list_node = new List_Node<T>; //新建节点 387 388 list_node->pPrior_Node = pTail; 389 list_node->pNext_Node = nullptr; 390 pTail->pNext_Node = list_node; 391 pTail = list_node; 392 list_node->data = t; 393 394 iNum_List++; 395 } 396 } 397 398 399 400 401 402 //向链表的头部压入数据 403 template<typename T> 404 void List<T>::Push_Front(T t) 405 { 406 if (iNum_List == 0) //如果是一个空链表 407 { 408 List_Node<T> * list_node = new List_Node<T>; // 新建第一个节点 409 410 411 pHead = list_node; //给头指针赋值第一个节点地址 412 pTail = list_node; 413 list_node->pNext_Node = nullptr; //第一个节点后指针域为空 414 list_node->pPrior_Node = nullptr; //第一个节点前指针域为空 415 list_node->data = t; //第一个节点数据域赋值t 416 417 iNum_List++; 418 } 419 else 420 { 421 List_Node<T> * list_node = new List_Node<T>; //新建节点 422 423 list_node->pPrior_Node = nullptr; 424 list_node->pNext_Node = pHead; 425 pHead = list_node; 426 list_node->data = t; 427 428 iNum_List++; 429 } 430 } 431 432 433 434 //获取链表大小 435 template<typename T> 436 int List<T>::Len() const 437 { 438 return iNum_List; 439 } 440 441 442 443 //遍历节点,错误返回-1 444 template<typename T> 445 int List<T>::Traverse() 446 { 447 if (iNum_List > 0) //如果链表不为空 448 { 449 List_Node<T> * pTempt = new List_Node<T>; //新建一个临时指针,指向头结点 450 pTempt = pHead; 451 for (int i = 0; i < iNum_List; i++) 452 { 453 cout << pTempt->data << " "; 454 pTempt = pTempt->pNext_Node; 455 } 456 cout << endl; 457 return 0; 458 } 459 460 else //链表为空 461 { 462 cout << "Traverse失败! 返回值-1" << endl; 463 return -1; 464 } 465 466 }
2.main.cpp
1 #include "Bi_List.h" 2 3 4 int main() 5 { 6 //----------------------------第1个链表----------------------------------- 7 8 List<int> list01; 9 list01.Traverse(); 10 cout << "list01.Get_Back() = " << list01.Get_Back() << endl; 11 cout << "list01.Get_Front() = " << list01.Get_Front() << endl; 12 13 list01.Push_Back(1); 14 list01.Push_Back(2); 15 list01.Push_Front(999); 16 list01.Push_Front(888); 17 list01.Push_Back(3); 18 list01.Traverse(); 19 cout << endl; 20 cout << "list01.Get_Back() = " << list01.Get_Back() << endl; 21 cout << "list01.Get_Front() = " << list01.Get_Front() << endl; 22 cout << endl << endl; 23 24 25 26 27 //----------------------------第2个链表----------------------------------- 28 29 List<int> list02; 30 //list01.Push_Back(0); 31 list02.Pop_Back(); 32 list02.Push_Front(1); 33 list02.Push_Front(2); 34 list02.Push_Back(3); 35 list02.Pop_Back(); 36 list02.Traverse(); 37 cout << endl << "list02.Len() = " << list02.Len() << endl; 38 cout << endl << endl; 39 40 41 42 43 44 //----------------------------第3个链表----------------------------------- 45 46 List<double> list03; 47 list03.Push_Back(1.111); 48 list03.Pop_Front(); 49 list03.Push_Back(1.111); 50 list03.Push_Back(2.222); 51 list03.Push_Back(3.333); 52 list03.Pop_Front(); 53 list03.Traverse(); 54 cout << endl << endl; 55 56 57 58 //----------------------------第4个链表----------------------------------- 59 List<double> list04; 60 list04.Insert(0, 0.001); 61 list04.Insert(0, 0.022); 62 list04.Insert(2, 3.333); 63 list04.Insert(1, 9.999); 64 list04.Traverse(); 65 cout << endl << endl; 66 67 68 69 //----------------------------第5个链表----------------------------------- 70 71 List<double> list05; 72 list05.Push_Back(1); 73 list05.Push_Back(2); 74 list05.Push_Back(3); 75 list05.Push_Back(4); 76 list05.Push_Back(5); 77 list05.Traverse(); 78 list05.Delete(0); 79 list05.Traverse(); 80 list05.Delete(3); 81 list05.Traverse(); 82 list05.Delete(1); 83 list05.Traverse(); 84 cout << "list05.Find(1) = " << list05.Find(1) << endl; 85 cout << endl << endl; 86 87 //----------------------------第6个链表----------------------------------- 88 89 List<int> list06; 90 list06.Push_Back(1); 91 list06.Push_Back(2); 92 list06.Push_Back(3); 93 list06.Push_Back(4); 94 list06.Push_Back(5); 95 list06.Traverse(); 96 list06.Change(2, 999); 97 list06.Traverse(); 98 system("pause"); 99 return 0; 100 }
以上是关于双向链表list的主要内容,如果未能解决你的问题,请参考以下文章