双链表
【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.
顺序 选择 循环 总结