本文双链表介绍部分参考自博文数组、单链表和双链表介绍 以及 双向链表的C/C++/Java实现

  1 双链表介绍

  双向链表(双链表)是链表的一种。和单链表一样,双链表也是由节点组成,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

  双链表的示意图如下:

  "《算法导论》之‘线性表’":双向循环链表

  表头为空,表头的后继节点为"节点10"(数据为10的节点);"节点10"的后继节点是"节点20"(数据为10的节点),"节点20"的前继节点是"节点10";"节点20"的后继节点是"节点30","节点30"的前继节点是"节点20";...;末尾节点的后继节点是表头。

   1.1 双链表添加节点

  "《算法导论》之‘线性表’":双向循环链表

  在"节点10"与"节点20"之间添加"节点15"
  添加之前:"节点10"的后继节点为"节点20","节点20" 的前继节点为"节点10"。
  添加之后:"节点10"的后继节点为"节点15","节点15" 的前继节点为"节点10"。"节点15"的后继节点为"节点20","节点20" 的前继节点为"节点15"。

  对于“添加节点”功能,在具体实现的时候,我们可以分为三种情况(个人觉得这样逻辑比较清晰,当然有些代码是可以合并的。):

  1)在链表第0位置添加。关键代码如下:

 1 NodePointer ptr = new Node(), prePtr, postPtr;
 2 // assert(ptr != NULL);
 3 ptr->data = val;
 4 if (pos == 0)    // insert node right behind 'head'
 5 {
 6     postPtr = head->next;
 7     head->next = ptr;
 8     postPtr->pre = ptr;
 9 
10     ptr->pre = head;
11     ptr->next = postPtr;
12 }

  2)在链表最后添加结点(即第len位置,其中len为链表原长度)。关键代码如下:

 1 ...
 2 if (pos == 0)    // insert node right behind 'head'
 3 {
 4     ...
 5 }
 6 else if (pos == len)    // append node
 7 {
 8     prePtr = head->pre;
 9     head->pre = ptr;
10     prePtr->next = ptr;
11 
12     ptr->pre = prePtr;
13     ptr->next = head;
14 }

  3)在链表的中间结点间添加结点。关键代码如下:

 1 ...
 2 if (pos == 0)    // insert node right behind 'head'
 3 {
 4     ...
 5 }
 6 else if (pos == len)    // append node
 7 {
 8     ...
 9 }
10 else                  // others
11 {
12     prePtr = head->next;
13     int count = 0;
14     while (prePtr != head && count < pos - 1)
15     {
16         prePtr = prePtr->next;
17         count++;
18     }
19     postPtr = prePtr->next;
20 
21     ptr->next = postPtr;
22     ptr->pre = prePtr;
23     prePtr->next = ptr;
24     postPtr->pre = ptr;
25 }

   1.2 双链表删除节点

  "《算法导论》之‘线性表’":双向循环链表

  删除"节点30"
  删除之前:"节点20"的后继节点为"节点30","节点30" 的前继节点为"节点20"。"节点30"的后继节点为"节点40","节点40" 的前继节点为"节点30"。
  删除之后:"节点20"的后继节点为"节点40","节点40" 的前继节点为"节点20"。

  对于“添加节点”功能,在具体实现的时候,我们可以分为三种情况:

  1)删除链表第1个结点。关键代码如下:

 1 NodePointer ptr, prePtr, postPtr;
 2 if (pos == 0)            // delete the first node
 3 {
 4     ptr = head->next;
 5     postPtr = ptr->next;
 6 
 7     head->next = postPtr;
 8     postPtr->pre = head;
 9     delete ptr;
10 }

  2)删除链表最后一个结点。关键代码如下:

 1 ...
 2 if (pos == 0)            // delete the first node
 3 {
 4     ...
 5 }
 6 else if (pos == len - 1)    // delete the last one
 7 {
 8     ptr = head->pre;
 9     prePtr = ptr->pre;
10 
11     prePtr->next = head;
12     head->pre = prePtr;
13     delete ptr;
14 }

  3)删除链表的中间结点。关键代码如下:

 1 ...
 2 if (pos == 0)            // delete the first node
 3 {
 4     ...
 5 }
 6 else if (pos == len - 1)    // delete the last one
 7 {
 8     ...
 9 }
10 else                        // others
11 {
12     ptr = head->next;
13     int count = 0;
14     while (ptr != head && count < pos)
15     {
16         ptr = ptr->next;
17         count++;
18     }
19     prePtr = ptr->pre;
20     postPtr = ptr->next;
21 
22     prePtr->next = postPtr;
23     postPtr->pre = prePtr;
24     delete ptr;
25 }

  2. 代码实现

  在这里,我设计的类如下:

 1 #ifndef DOUBLELINKEDLIST
 2 #define DOUBLELINKEDLIST
 3 
 4 #include <iostream>
 5 #include <cassert>
 6 using namespace std;
 7 
 8 typedef int ElementType;
 9 class Node
10 {
11 public:
12     ElementType data;
13     Node * pre;
14     Node * next;
15 };
16 typedef Node * NodePointer;
17 
18 class LinkedList
19 {
20 public:
21     LinkedList();
22     virtual ~LinkedList();
23     LinkedList(const LinkedList& orig);
24     LinkedList& operator=(const LinkedList& orig);
25     bool isEmpty();
26     bool addNode(const int pos, const ElementType val);
27     bool deleteNode(const int pos);
28     void displayNodes();
29     NodePointer getNode(const int pos);
30     int getLenOfList();
31 
32 private:
33     NodePointer head;
34 
35 };
36 
37 #endif

  相应的实现代码为:

  1 // linkedlist.cpp
  2 #include "linkedlist.h"
  3 
  4 LinkedList::LinkedList()
  5 {
  6     head = new Node();
  7     //assert(head != NULL);
  8     head->next = head;
  9     head->pre = head;
 10 }
 11 
 12 LinkedList::~LinkedList()
 13 {
 14     NodePointer ptr = head->next, postPtr;
 15     while (ptr != head)
 16     {
 17         postPtr = ptr;
 18         ptr = ptr->next;
 19         delete postPtr;
 20     }
 21     delete head;
 22 }
 23 
 24 LinkedList::LinkedList(const LinkedList& orig)
 25 {
 26     // head 初始化这一块不能缺,因为当新声明一个新对象并调用该拷贝构造函数时,
 27     // 新对象的head并不会被初始化,也就没有调用默认构造函数。要不会出错,因为
 28     // 在其他地方有用到了类似ptr = head->next的语句,如在函数getLenOfList()
 29     // 中,当新对象没有被初始化时,调用该函数就会发生“内存访问错误”。
 30     head = new Node();
 31     //assert(head != NULL);
 32     head->next = head;
 33     head->pre = head;
 34 
 35     NodePointer ptr = orig.head->next;
 36     int i = 0;
 37     while (ptr != orig.head)
 38     {
 39         addNode(i, ptr->data);
 40         ptr = ptr->next;
 41         i++;
 42     }
 43 
 44 }
 45 
 46 LinkedList& LinkedList::operator=(const LinkedList& orig)
 47 {
 48     NodePointer ptr = orig.head->next;
 49     int i = 0;
 50     while (ptr != orig.head)
 51     {
 52         addNode(i, ptr->data);
 53         ptr = ptr->next;
 54         i++;
 55     }
 56 
 57     return *this;
 58 }
 59 
 60 bool LinkedList::isEmpty()
 61 {
 62     return head->next == head && head->pre == head;
 63 }
 64 
 65 bool LinkedList::addNode(const int pos, const ElementType val)
 66 {
 67     bool isSuccess = true;
 68     int len = getLenOfList();
 69     // assert(0 <= pos <= len);
 70     if (pos < 0 || pos > len)
 71     {
 72         cerr << "The node at position " << pos << " you want to add is less than zero or larger than "
 73             << "the length of list ." << endl;
 74         isSuccess = false;
 75         throw out_of_range("out_of_range");
 76     }
 77     else
 78     {
 79         NodePointer ptr = new Node(), prePtr, postPtr;
 80         // assert(ptr != NULL);
 81         ptr->data = val;
 82         if (pos == 0)    // insert node right behind 'head'
 83         {
 84             postPtr = head->next;
 85             head->next = ptr;
 86             postPtr->pre = ptr;
 87 
 88             ptr->pre = head;
 89             ptr->next = postPtr;
 90         }
 91         else if (pos == len)    // append node
 92         {
 93             prePtr = head->pre;
 94             head->pre = ptr;
 95             prePtr->next = ptr;
 96 
 97             ptr->pre = prePtr;
 98             ptr->next = head;
 99         }
100         else                  // others
101         {
102             prePtr = head->next;
103             int count = 0;
104             while (prePtr != head && count < pos - 1)
105             {
106                 prePtr = prePtr->next;
107                 count++;
108             }
109             postPtr = prePtr->next;
110 
111             ptr->next = postPtr;
112             ptr->pre = prePtr;
113             prePtr->next = ptr;
114             postPtr->pre = ptr;
115         }
116     }
117     return isSuccess;
118 }
119 
120 bool LinkedList::deleteNode(const int pos)
121 {
122     bool isSuccess = true;
123     int len = getLenOfList();
124     // assert(0 <= pos <= len);
125     if (len == 0)
126     {
127         cerr << "There is no elements in the list." << endl;
128         isSuccess = false;
129     }
130     else
131     {
132         if (pos < 0 || pos > len - 1)
133         {
134             cerr << "The node at position " << pos << " you want to delete is out of range." << endl;
135             isSuccess = false;
136             throw out_of_range("out_of_range");
137         }
138         else
139         {
140             NodePointer ptr, prePtr, postPtr;
141             if (pos == 0)            // delete the first node
142             {
143                 ptr = head->next;
144                 postPtr = ptr->next;
145 
146                 head->next = postPtr;
147                 postPtr->pre = head;
148                 delete ptr;
149             }
150             else if (pos == len - 1)    // delete the last one
151             {
152                 ptr = head->pre;
153                 prePtr = ptr->pre;
154 
155                 prePtr->next = head;
156                 head->pre = prePtr;
157                 delete ptr;
158             }
159             else                        // others
160             {
161                 ptr = head->next;
162                 int count = 0;
163                 while (ptr != head && count < pos)
164                 {
165                     ptr = ptr->next;
166                     count++;
167                 }
168                 prePtr = ptr->pre;
169                 postPtr = ptr->next;
170 
171                 prePtr->next = postPtr;
172                 postPtr->pre = prePtr;
173                 delete ptr;
174             }
175         }
176     }
177 
178     return isSuccess;
179 }
180 
181 void LinkedList::displayNodes()
182 {
183     NodePointer ptr = head->next;
184     while (ptr != head)
185     {
186         cout << ptr->data << endl;
187         ptr = ptr->next;
188     }
189 }
190 
191 NodePointer LinkedList::getNode(const int pos)
192 {
193     int len = getLenOfList();
194     if (len == 0)
195     {
196         cerr << "There is no element in the list." << endl;
197         return NULL;
198     }
199     else
200     {
201         // assert(0 <= pos <= len);
202         if (pos < 0 || pos > len - 1)
203         {
204             cerr << "The item at position " << pos << " you want to get is less than zero or "
205                 << "larger than the length of list." << endl;
206             throw out_of_range("out_of_range");
207             // return NULL;
208         }
209         else
210         {
211             NodePointer ptr = head->next;
212             int count = 0;
213             while (ptr != head && count < pos)
214             {
215                 ptr = ptr->next;
216                 count++;
217             }
218             return ptr;
219         }
220     }
221 }
222 
223 int LinkedList::getLenOfList()
224 {
225     NodePointer ptr = head->next;
226     int len = 0;
227     while (ptr != head)
228     {
229         ptr = ptr->next;
230         len++;
231     }
232 
233     return len;
234 
235 }
linkedlist.cpp

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-10-21
  • 2021-09-26
  • 2021-09-30
  • 2022-03-04
猜你喜欢
  • 2021-07-21
  • 2021-10-07
  • 2021-04-26
  • 2020-10-12
  • 2018-09-25
  • 2021-07-14
  • 2021-04-06
相关资源
相似解决方案