双向链表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的主要内容,如果未能解决你的问题,请参考以下文章

数据结构之带头结点的循环双向链表详细图片+文字讲解

双向链表

list双向链表容器

List双向链表容器

双向链表/list

List双向链表容器