双链表

【1】双链表

双链表即双向链表,双链表的节点结构定义如下:

1 typedef int Elemtype;
2  
3 // 双链表节点结构定义
4 typedef struct dNode 
5 {
6     Elemtype data; /*数据域*/
7     struct dNode *prev;  /*指向前驱节点的指针域*/
8     struct dNode *next;  /*指向后继节点的指针域*/
9 }*pDLinkNode, *DLinkList;

双链表节点结构如下图示:

 

双链表节点比单链表多一个前驱指针域。

【2】C语言版双链表

1、无环双链表。实现部分代码如下:

  1 // C语言实现无环双链表
  2 #include <stdio.h>
  3 #include <memory.h>
  4 #include <assert.h>
  5 #include <stdlib.h>
  6 
  7 // 循环双链表的节点结构
  8 typedef struct DOUBLE_LINK_NODE
  9 {  
 10     int data;  // 数据域
 11     struct DOUBLE_LINK_NODE* prev;  // 前向指针域  
 12     struct DOUBLE_LINK_NODE* next;  // 后向指针域
 13 } DLINK_NODE;
 14 
 15 // 创建双链表的节点
 16 DLINK_NODE* create_link_node(int value)
 17 {  
 18     DLINK_NODE* pDLinkNode = NULL;
 19     pDLinkNode = (DLINK_NODE*)malloc(sizeof(DLINK_NODE));
 20     assert(NULL != pDLinkNode);
 21     memset(pDLinkNode, 0, sizeof(DLINK_NODE));
 22     pDLinkNode->data = value;
 23     return pDLinkNode;
 24 }  
 25 
 26 // 递归删除双链表的所有节点(包括头节点)
 27 void delete_all_link_node(DLINK_NODE** pDLinkNode)  
 28 {  
 29     DLINK_NODE* pNode = NULL;  
 30     if (NULL == *pDLinkNode)  
 31         return;  
 32   
 33     pNode = *pDLinkNode;  
 34     *pDLinkNode = pNode->next;
 35     free(pNode);
 36 
 37     delete_all_link_node(pDLinkNode);  
 38 }  
 39 
 40 // 在双链表中查询数据
 41 DLINK_NODE* find_data_in_link(const DLINK_NODE* pDLinkNode, int data)  
 42 {  
 43     DLINK_NODE* pNode = NULL;  
 44     if (NULL == pDLinkNode)  
 45         return NULL;  
 46   
 47     pNode = (DLINK_NODE*)pDLinkNode;
 48     while (NULL != pNode)
 49     {  
 50         if (data == pNode->data)  
 51             return pNode;
 52 
 53         pNode = pNode ->next;  
 54     }  
 55       
 56     return NULL;
 57 }  
 58 
 59 // 向双链表中添加数据
 60 bool add_data_into_link(DLINK_NODE** ppDLinkNode, int data)  
 61 {  
 62     DLINK_NODE* pNode = NULL;
 63     DLINK_NODE* pIndex = NULL;  
 64   
 65     if (NULL == ppDLinkNode)  
 66         return false;  
 67   
 68     if (NULL == *ppDLinkNode)
 69     {
 70         pNode = create_link_node(data);  
 71         assert(NULL != pNode);  
 72         *ppDLinkNode = pNode;  
 73         (*ppDLinkNode)->prev = (*ppDLinkNode)->next = NULL;  
 74         return true;  
 75     }  
 76   
 77     if (NULL != find_data_in_link(*ppDLinkNode, data))  
 78         return false;  
 79   
 80     pNode = create_link_node(data);  
 81     assert(NULL != pNode);
 82 
 83     pIndex = *ppDLinkNode;  
 84     while (NULL != pIndex->next)  
 85         pIndex = pIndex->next;
 86 
 87     pNode->prev = pIndex;
 88     pNode->next = pIndex->next;
 89     pIndex->next = pNode;  
 90     return true;  
 91 }  
 92 
 93 // 从双链表中删除数据
 94 bool delete_data_from_link(DLINK_NODE** ppDLinkNode, int data)  
 95 {  
 96     DLINK_NODE* pNode = NULL;
 97     if (NULL == ppDLinkNode || NULL == *ppDLinkNode)
 98         return false;
 99   
100     pNode = find_data_in_link(*ppDLinkNode, data); 
101     if (NULL == pNode)
102         return false;
103   
104     if (pNode == *ppDLinkNode)
105     {
106         if (NULL == (*ppDLinkNode)->next)
107         {  
108             *ppDLinkNode = NULL;
109         }
110         else
111         {  
112             *ppDLinkNode = pNode->next;
113             (*ppDLinkNode)->prev = NULL;
114         }
115     }
116     else
117     {
118         if (pNode->next != NULL)
119         {
120             pNode->next->prev = pNode->prev;
121         }
122         pNode->prev->next = pNode->next;
123     }  
124   
125     free(pNode);
126     return true;
127 }  
128 
129 // 统计链表中数据个数
130 int count_number_in_link(const DLINK_NODE* pDLinkNode)  
131 {  
132     int count = 0;  
133     DLINK_NODE* pNode = (DLINK_NODE*)pDLinkNode;  
134   
135     while (NULL != pNode)
136     {  
137         if (pNode->data != -1)  // 头节点除外
138         {
139             ++count;  
140         }
141         pNode = pNode->next;
142     }
143 
144     return count;
145 }  
146 
147 // 打印双链表中数据
148 void print_link_node(const DLINK_NODE* pDLinkNode)  
149 {  
150     printf("打印元素:\n");
151     DLINK_NODE* pNode = (DLINK_NODE*)pDLinkNode;  
152   
153     while (NULL != pNode)
154     {
155         if (pNode->data != -1)
156         {
157             printf("%d ", pNode->data);
158         }
159         pNode = pNode ->next;
160     }  
161 
162     printf("\n");
163 }  
164 
165 void main()
166 {
167     printf("测试无环有头双链表效果:\n");
168     DLINK_NODE* pHeadNode = NULL;
169     add_data_into_link(&pHeadNode, -1);  // 头节点
170     int nItems[10] = {12, 23, 34, 45, 56, 67, 78, 89, 99, 100};
171     for (int i = 0; i < 10; ++i)
172     {
173         if (!add_data_into_link(&pHeadNode, nItems[i]))
174         {
175             break;
176         }
177     }
178 
179     int nCount = count_number_in_link(pHeadNode);
180     printf("无环有头双链表元素个数:%d \n", nCount);
181 
182     print_link_node(pHeadNode);
183 
184     delete_data_from_link(&pHeadNode, 56);
185     printf("删除56后\n");
186     print_link_node(pHeadNode);
187 
188     delete_all_link_node(&pHeadNode);
189     printf("删除所有节点后");
190     print_link_node(pHeadNode);
191 
192     printf("测试无环无头双链表效果:\n");
193     DLINK_NODE* pNode = NULL;
194     int nItems2[10] = {11, 22, 33, 44, 55, 66, 77, 88, 99, 100};
195     for (int i = 0; i < 10; ++i)
196     {
197         if (!add_data_into_link(&pNode, nItems2[i]))
198         {
199             break;
200         }
201     }
202 
203     int nNoHeadCount = count_number_in_link(pNode);
204     printf("无环无头双链表元素个数:%d \n", nNoHeadCount);
205 
206     print_link_node(pNode);
207 
208     delete_data_from_link(&pNode, 55);
209     printf("删除55后\n");
210     print_link_node(pNode);
211 
212     delete_data_from_link(&pNode, 11);
213     printf("删除11后\n");
214     print_link_node(pNode);
215 
216     delete_data_from_link(&pNode, 100);
217     printf("删除100后\n");
218     print_link_node(pNode);
219 
220     delete_all_link_node(&pNode);
221     printf("删除所有节点后");
222     print_link_node(pNode);
223 
224     system("pause");
225 }
226 
227 // run out
228 /*
229 测试无环有头双链表效果:
230 无环有头双链表元素个数:10
231 打印元素:
232 12 23 34 45 56 67 78 89 99 100
233 删除56后
234 打印元素:
235 12 23 34 45 67 78 89 99 100
236 删除所有节点后打印元素:
237 
238 测试无环无头双链表效果:
239 无环无头双链表元素个数:10
240 打印元素:
241 11 22 33 44 55 66 77 88 99 100
242 删除55后
243 打印元素:
244 11 22 33 44 66 77 88 99 100
245 删除11后
246 打印元素:
247 22 33 44 66 77 88 99 100
248 删除100后
249 打印元素:
250 22 33 44 66 77 88 99
251 删除所有节点后打印元素:
252 
253 请按任意键继续. . .
254 */

2、循环双链表。实现部分代码如下:

  1 // C语言实现循环双链表
  2 #include <stdio.h>
  3 #include <malloc.h>
  4 #include <stdlib.h>
  5 #include <assert.h>
  6 
  7 typedef int Elemtype;
  8  
  9 // 双链表节点结构定义
 10 typedef struct dNode 
 11 {
 12     Elemtype data; /*数据域*/
 13     struct dNode *prev;  /*指向前驱节点的指针域*/
 14     struct dNode *next;  /*指向后继节点的指针域*/
 15 }*pDLinkNode, *DLinkList;
 16  
 17 // 有头节点的空循环双链表
 18 DLinkList GetEmptyDLink() 
 19 {
 20     DLinkList head = (pDLinkNode)malloc(sizeof(struct dNode));
 21     head->data = 0;
 22     head->prev = head;
 23     head->next = head;
 24     return head;
 25 }
 26 
 27 // 由用户输入数据建立循环双链表
 28 void DLink_create(DLinkList head, int n) 
 29 {
 30     pDLinkNode p = head, r = head;
 31     for (int i = 0; i < n; ++i) 
 32     {
 33         p->next = (pDLinkNode)malloc(sizeof(dNode));/*为一个新节点分配空间*/
 34         scanf("%d", &p->next->data); /*从键盘输入值,并保存在新节点数据域中*/
 35         p = p->next; // p指向新节点
 36         p->prev = r;// 新节点的prev指向上一个节点
 37         r = p; // 上一个节点前进到新节点
 38     }
 39     p->next = head; // 指向头节点
 40     head->prev = p; // head的prev指向最后的节点
 41 }
 42 
 43 // 由数组创建双链表
 44 void DLink_createByArray(DLinkList head, int* arrName, int n) 
 45 {
 46     pDLinkNode p = head, r = head;
 47     for (int i = 0; i < n; ++i)
 48     {
 49         p->next = (pDLinkNode)malloc(sizeof(dNode));/*为一个新节点分配空间*/
 50         assert(NULL != p->next);
 51         p->next->data = arrName[i]; /*数据域*/
 52         p = p->next; /*p指向新节点*/
 53         p->prev = r; /*新节点的前驱指针域prev指向上一个节点*/
 54         r = p;       /*r保存新节点为下次添加做准备*/
 55     }
 56     // 处理循环条件
 57     p->next = head; /*最后节点的后驱指针域next指向头节点head*/
 58     head->prev = p; /*头结点head的前驱指针域prev指向最后节点*/
 59 }
 60 
 61 // 正向显示双链表数据
 62 void Show(DLinkList head) 
 63 { 
 64     pDLinkNode p = head->next;
 65     while (p != head) 
 66     {
 67         printf("%d ",p->data);
 68         p = p->next;
 69     }
 70     printf("\n");
 71 }
 72 
 73 // 反向显示双链表数据
 74 void ShowR(DLinkList head) 
 75 {
 76     pDLinkNode p = head->prev;
 77     while (p != head) 
 78     {
 79         printf("%d ",p->data);
 80         p = p->prev;
 81     }
 82     printf("\n");
 83 }
 84  
 85 // 删除循环双链表所有数据节点
 86 void FreeList(DLinkList head) 
 87 { 
 88     pDLinkNode p = head->next;
 89     while (p != head) 
 90     {
 91         pDLinkNode pTemp = p;
 92         p = p->next;
 93         free(pTemp);
 94     }
 95 
 96     head->prev = head->next = head;
 97 }
 98 
 99 // 循环双链表中查找数据
100 pDLinkNode Find(DLinkList head, int nData)
101 {
102     if (NULL == head || NULL == head->next)
103         return NULL;
104 
105     pDLinkNode p = head->next;
106     while (p != head) 
107     {
108         if (nData == p->data)
109             return p;
110         p = p->next;
111     }
112 
113     return NULL;
114 }
115 
116 // 从循环双链表中删除数据
117 void DeleteListData(DLinkList head, int nValue)
118 {
119     if (NULL == head || NULL == head->next)
120         return;
121 
122     pDLinkNode pNode = Find(head, nValue);
123     if (NULL != pNode)
124     {
125         pNode->next->prev = pNode->prev;
126         pNode->prev->next = pNode->next;
127         free(pNode);
128         pNode = NULL;
129     }
130 }
131 
132 // 在循环双链表中插入一个数据
133 void InsertListData(pDLinkNode pNode, int nValue)
134 {
135     pDLinkNode pNewNode = (pDLinkNode)malloc(sizeof(dNode));
136     assert(NULL != pNewNode);
137     pNewNode->data = nValue;
138     pNewNode->prev = pNode;
139     pNewNode->next = pNode->next;
140     pNode->next->prev = pNewNode;
141     pNode->next = pNewNode;
142 }
143 
144 void main() 
145 {
146     printf("请输入10个整型数据:\n");
147     DLinkList head = GetEmptyDLink();
148     DLink_create(head, 10);
149     printf("输入数据创建双链表后,正向显示:\n");
150     Show(head);
151     printf("反向显示:\n");
152     ShowR(head);
153 
154     printf("\n由数组创建双链表:\n");
155     int nArray[10] = {12, 23, 34, 45, 56, 67, 78, 89, 99, 100};
156     DLinkList head2 = GetEmptyDLink();
157     DLink_createByArray(head2, nArray, 10);
158     printf("正向显示:\n");
159     Show(head2);
160     printf("反向显示:\n");
161     ShowR(head2);
162 
163     printf("删除45后,正向显示:\n");
164     DeleteListData(head2, 45);
165     Show(head2);
166 
167     printf("插入666、888后,正向显示:\n");
168     InsertListData(head2, 666);
169     InsertListData(head2, 888);
170     Show(head2);
171 
172     printf("数据释放后,正向显示:\n");
173     FreeList(head2);
174     Show(head2);
175 
176     system("pause");
177 }
178 // run out
179 /*
180 请输入10个整型数据:
181 1
182 2
183 3
184 4
185 5
186 6
187 7
188 8
189 9
190 10
191 输入数据创建双链表后,正向显示:
192 1 2 3 4 5 6 7 8 9 10
193 反向显示:
194 10 9 8 7 6 5 4 3 2 1
195 
196 由数组创建双链表:
197 正向显示:
198 12 23 34 45 56 67 78 89 99 100
199 反向显示:
200 100 99 89 78 67 56 45 34 23 12
201 删除45后,正向显示:
202 12 23 34 56 67 78 89 99 100
203 插入666、888后,正向显示:
204 888 666 12 23 34 56 67 78 89 99 100
205 数据释放后,正向显示:
206 
207 请按任意键继续. . .
208 */

注意:双链表循环与无环的区别。

【3】C++版双链表

1、循环双链表,实现部分功能函数代码如下:

  1 #pragma once
  2 #include <iostream>
  3 #include <assert.h>
  4 
  5 template<class _Ty> class Iterator;
  6 template<class _Ty> class List;
  7 
  8 // 双链表节点结构
  9 template<class _Ty>
 10 class Node
 11 {
 12     friend class List<_Ty>;
 13     friend class Iterator<_Ty>;
 14 private:
 15     _Ty data;
 16     Node<_Ty>  *prev, *next;
 17 
 18 public:
 19     typedef _Ty          value_type;
 20     typedef _Ty &        reference;
 21     typedef const _Ty &  const_reference;
 22 
 23 public:
 24     Node(const _Ty &x=_Ty(),Node<_Ty> *p=NULL,Node<_Ty> *n=NULL);
 25     ~Node();
 26 
 27     reference Value();
 28     const_reference Value() const;
 29 
 30     Node<_Ty> *& Prev();
 31     Node<_Ty> * const & Prev() const;
 32 
 33     Node<_Ty> *& Next();
 34     Node<_Ty> * const & Next() const;
 35 }; 
 36 
 37 /////////////////////////////////////////////////////////////////
 38 template<class _Ty>
 39 Node<_Ty>::Node(const _Ty &x, Node<_Ty> *p, Node<_Ty> *n)
 40    : data(x)
 41    , prev(p)
 42    , next(n)
 43 {}
 44 
 45 template<class _Ty>
 46 Node<_Ty>::~Node()
 47 {}
 48 
 49 template<class _Ty>
 50 _Ty & Node<_Ty>::Value()
 51 {
 52     return data;
 53 }
 54 
 55 template<class _Ty>
 56 const _Ty &  Node<_Ty>::Value() const
 57 {
 58     return data;
 59 }
 60 
 61 template<class _Ty>
 62 Node<_Ty> *& Node<_Ty>::Prev()
 63 {
 64     return prev;
 65 }
 66 
 67 template<class _Ty>
 68 Node<_Ty> * const & Node<_Ty>::Prev() const
 69 {
 70     return prev;
 71 }
 72 template<class _Ty>
 73 Node<_Ty> * & Node<_Ty>::Next()
 74 {
 75     return next;
 76 }
 77 
 78 template<class _Ty>
 79 Node<_Ty> * const & Node<_Ty>::Next() const
 80 {
 81     return next;
 82 }
 83 
 84 /////////////////////////////////////////////////////////////////
 85 template<class _Ty>
 86 class List
 87 {
 88     friend class Iterator<_Ty>;
 89 private:
 90     Node<_Ty>  *_Head;
 91     size_t     _Size;
 92 
 93     Node<_Ty> * Buynode(const _Ty& x = _Ty(), Node<_Ty>* p = NULL, Node<_Ty>* n = NULL)
 94     {
 95         Node<_Ty>* s = new Node<_Ty>(x);
 96         s->next = n == NULL ? s: n;
 97         s->prev = p == NULL ? s: p;
 98         return s;
 99     }
100 
101 public:
102     // 构造函数
103     List():_Size(0), _Head(Buynode())    
104     {}
105     // 拷贝构造函数
106     List(const List<_Ty> &Lt);
107     // 赋值函数
108     List<_Ty> & operator=(const List<_Ty> &Lt);
109     // 析构函数    
110     ~List(){}
111 /*****************************************
112 *函数名:size
113 *参数:void
114 *返回值类型:size_t
115 *功能:求双链表的长度
116 *实现思想:return _Size
117 *******************************************/
118 size_t  size() const 
119 { 
120     return _Size;
121 }
122 /********************************************
123 *函数名:empty
124 *参数:void
125 *返回值类型:bool
126 *功能:判空
127 *实现思想:_Size == 0
128 ********************************************/  
129 bool empty() const
130 { 
131     return 0 == _Size;
132 }
133 /*******************************************
134 *函数名:front
135 *参数:void
136 *返回值类型:_Ty &
137 *功能:返回双链表中第一个数值
138 *实现思想: 1> 判空
139            2> 返回第一个节点的值
140 *******************************************/
141 _Ty & front()
142 {
143     assert(!empty());
144     return _Head->next->data;
145 }
146 // const方法
147 const _Ty & front() const 
148 {
149     assert(!empty());
150     return _Head->next->data;
151 }
152 /*******************************************
153 *函数名:back
154 *参数:void
155 *返回值类型:_Ty  &
156 *功能:返回双链表最后一个节点的值
157 *实现思想: 1> 判空
158            2> 返回最后一个节点的值
159 *******************************************/
160 _Ty & back()
161 {
162     assert(!empty());
163     return _Head->prev->data;
164 }
165 // const
166 const _Ty & back() const 
167 {
168     assert(!empty());
169     return _Head->prev->data;
170 }
171 /*****************************************
172 *函数名:push_front
173 *参数:const _Ty& x
174 *返回值类型:void
175 *功能:在双链表最前面插入一个数值
176 *实现思想: 1> 构建节点
177           2> 衔接节点
178           3> 重定长度
179 *****************************************/
180 void push_front(const _Ty& x)
181 {
182     Node<_Ty>* s = Buynode(x, _Head, _Head->next);
183     _Head->next = s;
184     s->next->prev = s; 
185     ++_Size; 
186 }
187 /***************************************
188 *函数名:pop_front
189 *参数:void
190 *返回值类型:void
191 *功能:弹出双链表中最前面的一个数值
192 *实现思想: 1> 锁定(判空)第一个节点
193            2> 移出节点
194            3> 删除节点
195            4> 重定长度
196 ****************************************/
197 void pop_front()
198 {
199     Node<_Ty>* s = _Head->next;
200     if (s != NULL)
201     {
202         _Head->next = s->next;
203         s->next->prev = _Head;
204         delete s;
205     }
206     --_Size;
207 }
208 /**************************************
209 *函数名:push_back
210 *参数:const _Ty& x
211 *返回值类型:void
212 *功能:在双链表中的末尾插入一个数值
213 *实现思想: 1> 构建一个节点
214            2> 衔接节点
215            3> 重定长度
216 ***************************************/
217 void push_back(const _Ty& x)
218 {
219     Node<_Ty>* s = Buynode(x, _Head->prev, _Head);
220     _Head->prev = s;
221     s->prev->next = s;
222     ++_Size;
223 }
224 /***************************************
225 *函数名:pop_back
226 *参数:void
227 *返回值类型:void
228 *功能:弹出双链表中的最后一个数值
229 *实现思想: 1> 锁定(判空)最后一个节点
230            2> 移出节点
231            3> 删除节点
232            4> 重定长度
233 ***************************************/
234 void pop_back()
235 {
236     Node<_Ty>* s = _Head->prev;
237     if (s != NULL)
238     {
239         _Head->prev = s->prev; 
240         s->prev->next = _Head;
241         delete s;
242     }
243     --_Size;
244 
245 }
246 /**********************************************
247 *函数名:findvalue
248 *参数:const _Ty &x
249 *返回值类型:Node<_Ty> *
250 *功能:在双链表中找到某一个值的节点指针
251 *实现思想: 1> 初始化
252            2> 循环定位
253            3> 返回值
254 ***********************************************/
255 Node<_Ty> * findvalue(const _Ty &x)
256 {
257     Node<_Ty>* p = _Head->next;
258     while (p != _Head && p->data != x) //防止重复循环
259     {
260         p = p->next;
261     }
262     return (p == _Head) ? NULL : p;
263 }
264 /******************************************
265 *函数名:prefindvalue
266 *参数:const _Ty &x
267 *返回值类型:Node<_Ty> *
268 *功能:在双链表中按值查找其节点前驱
269 *实现思想: 1> 初始化
270            2> 循环定位
271            3> 返回值
272 ******************************************/
273 Node<_Ty> * prefindvalue(const _Ty &x)
274 {
275     Node<_Ty>* r = findvalue(x);
276     return (NULL == r) ? NULL : r->prev;
277 }
278 /*******************************************
279 *函数名:findpos
280 *参数:int pos
281 *返回值类型:Node<_Ty> *
282 *功能:在双链表中按位置求节点指针
283 *实现思想: 1> 无效pos
284            2> 有效pos 循环初始化
285            3> 循环定位
286 *******************************************/
287 Node<_Ty>* findpos(size_t pos)
288 {
289     if (0 == pos) 
290         return _Head;
291     if (pos < 0 || pos >= _Size)
292         return NULL;
293 
294     size_t j = 0;
295     Node<_Ty>* p = _Head;
296     while (j < pos)
297     {
298         ++j;
299         p = p->next;
300     }
301     return p;
302 }
303 /*********************************************
304 *函数名:findpos
305 *参数:int  pos
306 *返回值类型:Node<_Ty> *
307 *功能:在双链表中按位置求节点指针
308 *实现思想: 1> 无效pos
309            2> 有效pos ,循环初始化
310            3> 循环定位
311 *********************************************/
312 /*
313 Node<_Ty>* findpos(int pos)
314 {
315     if (pos < -1 || pos >= _Size) 
316         return NULL;
317     if (-1 == pos) 
318         return _Head;
319 
320     int j = 0; 
321     Node<_Ty>* p = _Head->next;
322     while (j < pos) 
323     {
324         ++j;
325         p = p->next;
326     }
327     return p;
328 }
329 */
330 /********************************************
331 *函数名:insert
332 *参数:const int pos,const _Ty &x
333 *返回值类型:void
334 *功能:在双链表中的指定位置插入数值
335 *实现思想: 1> 锁定位置的前驱
336            2> 构建节点
337            3> 衔接节点
338            4> 重定长度
339 ********************************************/
340 void insert(const int pos, const _Ty &x)
341 {
342     Node<_Ty>* p = findpos(pos - 1); // 前驱
343     if (NULL == p)
344         return;
345 
346     Node<_Ty>* s = Buynode(x, p, p->next);
347     p->next = s;
348     s->next->prev = s;
349     ++_Size;
350 }
351 /*****************************************
352 *函数名:remove
353 *参数:const _Ty &x
354 *返回值类型:void
355 *功能:从单链表中删除某个值
356 *实现思想: 1> 按值锁定节点
357            2> 移出节点
358            3> 删除节点
359            4> 重定长度
360 ******************************************/
361 void remove(const _Ty &x)
362 {
363     Node<_Ty>* p = findvalue(x);
364     if (p != NULL)
365     {
366         p->prev->next = p->next;
367         p->next->prev = p->prev;
368         delete p;
369         --_Size;
370     }
371 }
372 /******************************************
373 *函数名:removeall
374 *参数:const _Ty &x
375 *返回值类型:void
376 *功能:删除双链表中所有出现的某一值
377 *实现思想: 1> 初始化
378            2> 循环逐个判断
379 *******************************************/
380 void removeall(const _Ty &x)
381 {
382     Node<_Ty>* p = prefindvalue(x);
383     if (NULL == p)
384       return;
385 
386     while (p->next != _Head)
387     {
388         if (p->next->data == x)
389         {
390             remove(x);
391         }
392         else
393         {
394             p = p->next;
395         }
396     }
397 }
398 /*********************************************
399 *函数名:erase
400 *参数:const int pos
401 *返回值类型:void
402 *功能:从双链表中按位置删除
403 *实现思想: 1> 锁定该位置的节点
404            2> 移出节点
405            3> 删除节点
406            4> 重定长度
407 **********************************************/
408 void erase(const int pos)
409 {
410     Node<_Ty>* p = findpos(pos);
411     if (NULL != p && p != _Head)
412     {
413         p->prev->next = p->next;
414         p->next->prev = p->prev;
415         delete p;
416         --_Size;
417     }
418 }
419 /***********************************/
420 // 清空链表
421 void clear()
422 {
423     _Head->next = _Head;
424     _Head->prev = _Head;
425 }
426 /***********************************
427 *函数名:sort
428 *参数:void
429 *返回值类型:void
430 *功能:对双链表中的值进行排序
431 *实现思想:快速排序
432 ***********************************/
433 void sort()
434 {   
435     Node<_Ty> *s = NULL, *p = NULL, *min = NULL;
436     _Ty temp;
437     s = _Head->next;
438     while (s != _Head)
439     {
440         min = s;
441         p = s->next;
442         while (p != _Head)
443         {
444             if (min->data > p->data)
445             {
446                 temp = min->data;
447                 min->data = p->data;
448                 p->data = temp;
449             }
450             p = p->next ;
451         }
452         s = s->next;
453     }
454 }
455 /************************************
456 *函数名:print
457 *参数:void
458 *返回值类型:void
459 *功能:输出链表中每个结点数据
460 *实现思想:循环输出
461 ************************************/
462 void print()
463 {
464     Node<_Ty> *p = _Head->next;
465     while (p != _Head)
466     {
467         cout << p->data << " ";
468         p = p->next;
469     }
470     cout << endl;
471 }
472 /************************************
473 *函数名:reverse
474 *参数:void
475 *返回值类型:void
476 *功能:重置链表数据
477 *实现思想:调换每个节点的prev和next
478 ************************************/
479 void reverse()
480 {
481     Node<_Ty> *r = NULL, *p = _Head;
482     for (size_t i = 0; i <= _Size; ++i)
483     {
484         p = p->next;
485         r = p->next;
486         p->next = p->prev;
487         p->prev = r;
488     }
489 }
490 };
491 //////////////////////////////////////////////////////////////
492 template<class _Ty> class Iterator
493 {
494 private:
495     List<_Ty> &list;
496     Node<_Ty> *Ptr;
497 public:
498     Iterator(List<_Ty> &Lt): list(Lt), Ptr(NULL)
499     {}
500 
501     ~Iterator()
502     {}
503 
504     void First()
505     {
506         Ptr = list._Head->next;
507     }
508 
509     bool IsDone()  const
510     {
511         return Ptr == list._Head;
512     }
513 
514     _Ty & operator*()
515     {
516         return Ptr->data;
517     }
518 
519     _Ty * operator->()
520     {
521         return &(Ptr->data);
522     }
523 
524     Iterator & operator++()
525     {
526         Ptr = Ptr->next;
527         return *this;
528     }
529 
530     Iterator & operator--()
531     {
532         Ptr = Ptr->prev;
533         return *this;
534     }
535 };

2、测试程序如下:

 1 #include <iostream>
 2 #include "List.h"
 3 using namespace std;
 4 
 5 int sum(List<int> &Lt)
 6 {
 7     Iterator<int> it(Lt);
 8     int ret = 0;
 9     it.First();
10     while (!it.IsDone())
11     {
12         ret += *it;
13         ++it;
14     }
15     return ret;
16 }
17 
18 void main()
19 {
20     List<int> mylist;
21     int i = 0;
22     for (i = 12; i > 0; --i)
23     {
24         mylist.push_back(i); // 方法1
25     }
26     cout << sum(mylist) <<endl;
27 
28     mylist.push_back(2);   // 方法1
29     mylist.print();   // 方法2
30 
31     mylist.sort();    // 方法3
32     mylist.print();
33 
34     mylist.reverse();   // 方法4
35     mylist.print();
36     
37     mylist.insert(2, 30); // 方法5
38     mylist.insert(4, 30);
39     mylist.insert(5, 30);
40     mylist.insert(8, 30);
41     mylist.print();
42 
43     mylist.push_front(11); // 方法6
44     mylist.print();
45 
46     mylist.remove(3); // 方法7
47     mylist.print();
48     
49     mylist.removeall(30); // 方法8
50     mylist.print();
51 
52     mylist.erase(7);// 方法9
53     mylist.print();
54 
55     cout << mylist.size() << endl; // 方法10
56 
57     mylist.clear();   // 方法11
58     mylist.print();
59     system("pause");
60 }
61 
62 // 备注:
63 // 数据结构双链表实现代码
64 // 整理于2013-11-27
65 // 双链表的节点结构为:前驱~数据~后驱 (三部分)
66 // 该双链表是有头结点的
67 // 该双链表的头结点索引为0,第一个数据节点为1,以此类推。
68 // 尤其注意findpos函数的pos为size_t类型
69 // 认真琢磨双链表的功能实现函数

循环双链表的应用很广,此例测试程序很简单。

【4】双链表的分类

1、不带头节点的循环非空双链表

2、带头节点的循环双链表

示例1:

示例2:

示例3:

示例4:

 

3、带头节点的无环双链表

示例1:

示例2:

 

4、无环与循环双链表的区别

5、双链表分类

6、各种表的对比图

【5】双链表中插入节点

(1)插入节点代码描述:

 1 // 在循环双链表中插入一个数据
 2 void InsertListData(pDLinkNode pNode, int nValue)
 3 {
 4     pDLinkNode pNewNode = (pDLinkNode)malloc(sizeof(dNode));
 5     assert(NULL != pNewNode);
 6 
 7     pNewNode->data = nValue;
 8     pNewNode->prev = pNode;
 9     pNewNode->next = pNode->next;
10     pNode->next->prev = pNewNode;
11     pNode->next = pNewNode;
12 }

(2)思路分析:

步骤1、新节点的前驱

步骤2、新节点的后驱

步骤3、新节点后一个节点的前驱

步骤4、新节点前一个节点的后驱

(3)为了更形象的理解这个过程,搜集如下逻辑结构示意图:

图1:

图2:

图3:

图4:

图5:

图6:

【6】双链表中删除节点

(1)双链表删除节点代码:

 1 // 从循环双链表中删除数据
 2 void DeleteListData(DLinkList head, int nValue)
 3 {
 4     if (NULL == head || NULL == head->next)
 5         return;
 6 
 7     pDLinkNode pNode = Find(head, nValue);
 8     if (NULL != pNode)
 9     {
10         pNode->next->prev = pNode->prev;
11         pNode->prev->next = pNode->next;
12         free(pNode);
13         pNode = NULL;
14     }
15 }

(2)删除节点的思路分析:

步骤1、找到即将被删除的节点 pNode

步骤2、将 pNode 的后继的前驱指向 pNode 的前驱,即 pNode->next->prev = pNode->prev;

步骤3、将 pNode 的前驱的后继指向 pNode 的后继,即 pNode->prev->next = pNode->next;

步骤4、删除节点 pNode, 即 free(pNode);

(3)为了更形象的理解这个过程,搜集如下逻辑结构示意图:

图1:

图2:

图3:

图4:

图5:

图6:

 

【7】单链表与双链表的区别

单链表: 结构简单,存储空间小,但是只能向前访问节点,如果需要访问之前的节点,需要建立循环链表。
双链表: 存储前一节点和后一节点地址,可以自由访问各个节点,存储空间比单链要大。

 

Good  Good  Study,  Day  Day  Up.

顺序  选择  循环  总结

posted @ 2017-02-17 10:13  kaizenly  阅读(853)  评论(0编辑  收藏  举报
打赏