双向链表
单链表的缺陷
1.单链表的结点都只有一个指向下一个结点的指针
2.单链表的数据元素无法直接访问其前驱元,有时单链表会带来访问效率上的问题
二、双向链表的新操作
1.获取当前游标指向的数据元素
2.将游标重置指向链表中的第一个数据元素
3.将游标移动指向到链表中的下一个数据元素
4.将游标移动指向到链表中的上一个数据元素
5.直接指定删除链表中的某个数据元素
1 #include <stdio.h> 2 #include <malloc.h> 3 #include "DLinkList.h" 4 5 typedef struct _tag_DLinkList 6 { 7 DLinkListNode header; 8 DLinkListNode* slider; 9 int length; 10 } TDLinkList; 11 12 DLinkList* DLinkList_Create() // O(1) 13 { 14 TDLinkList* ret = (TDLinkList*)malloc(sizeof(TDLinkList)); 15 16 if( ret != NULL ) 17 { 18 ret->length = 0; 19 ret->header.next = NULL; 20 ret->header.pre = NULL; 21 ret->slider = NULL; 22 } 23 24 return ret; 25 } 26 27 void DLinkList_Destroy(DLinkList* list) // O(1) 28 { 29 free(list); 30 } 31 32 void DLinkList_Clear(DLinkList* list) // O(1) 33 { 34 TDLinkList* sList = (TDLinkList*)list; 35 36 if( sList != NULL ) 37 { 38 sList->length = 0; 39 sList->header.next = NULL; 40 sList->header.pre = NULL; 41 sList->slider = NULL; 42 } 43 } 44 45 int DLinkList_Length(DLinkList* list) // O(1) 46 { 47 TDLinkList* sList = (TDLinkList*)list; 48 int ret = -1; 49 50 if( sList != NULL ) 51 { 52 ret = sList->length; 53 } 54 55 return ret; 56 } 57 58 int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos) // O(n) 59 { 60 TDLinkList* sList = (TDLinkList*)list; 61 int ret = (sList != NULL) && (pos >= 0) && (node != NULL); 62 int i = 0; 63 64 if( ret ) 65 { 66 DLinkListNode* current = (DLinkListNode*)sList; 67 DLinkListNode* next = NULL; 68 69 for(i=0; (i<pos) && (current->next != NULL); i++) 70 { 71 current = current->next; 72 } 73 74 next = current->next; 75 76 current->next = node; 77 node->next = next; 78 79 if( next != NULL ) 80 { 81 next->pre = node; 82 } 83 84 node->pre = current; 85 86 if( sList->length == 0 ) 87 { 88 node->pre = NULL; 89 sList->slider = node; 90 } 91 92 sList->length++; 93 } 94 95 return ret; 96 } 97 98 DLinkListNode* DLinkList_Get(DLinkList* list, int pos) // O(n) 99 { 100 TDLinkList* sList = (TDLinkList*)list; 101 DLinkListNode* ret = NULL; 102 int i = 0; 103 104 if( (sList != NULL) && (0 <= pos) && (pos < sList->length) ) 105 { 106 DLinkListNode* current = (DLinkListNode*)sList; 107 108 for(i=0; i<pos; i++) 109 { 110 current = current->next; 111 } 112 113 ret = current->next; 114 } 115 116 return ret; 117 } 118 119 DLinkListNode* DLinkList_Delete(DLinkList* list, int pos) // O(n) 120 { 121 TDLinkList* sList = (TDLinkList*)list; 122 DLinkListNode* ret = NULL; 123 int i = 0; 124 125 if( (sList != NULL) && (0 <= pos) && (pos < sList->length) ) 126 { 127 DLinkListNode* current = (DLinkListNode*)sList; 128 DLinkListNode* next = NULL; 129 130 for(i=0; i<pos; i++) 131 { 132 current = current->next; 133 } 134 135 ret = current->next; 136 next = ret->next; 137 138 current->next = next; 139 140 if( next != NULL ) 141 { 142 next->pre = current; 143 144 if( current == (DLinkListNode*)sList ) 145 { 146 next->pre = NULL; 147 } 148 } 149 150 if( sList->slider == ret ) 151 { 152 sList->slider = next; 153 } 154 155 sList->length--; 156 } 157 158 return ret; 159 } 160 161 DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node) 162 { 163 TDLinkList* sList = (TDLinkList*)list; 164 DLinkListNode* ret = NULL; 165 int i = 0; 166 167 if( sList != NULL ) 168 { 169 DLinkListNode* current = (DLinkListNode*)sList; 170 171 for(i=0; i<sList->length; i++) 172 { 173 if( current->next == node ) 174 { 175 ret = current->next; 176 break; 177 } 178 179 current = current->next; 180 } 181 182 if( ret != NULL ) 183 { 184 DLinkList_Delete(sList, i); 185 } 186 } 187 188 return ret; 189 } 190 191 DLinkListNode* DLinkList_Reset(DLinkList* list) 192 { 193 TDLinkList* sList = (TDLinkList*)list; 194 DLinkListNode* ret = NULL; 195 196 if( sList != NULL ) 197 { 198 sList->slider = sList->header.next; 199 ret = sList->slider; 200 } 201 202 return ret; 203 } 204 205 DLinkListNode* DLinkList_Current(DLinkList* list) 206 { 207 TDLinkList* sList = (TDLinkList*)list; 208 DLinkListNode* ret = NULL; 209 210 if( sList != NULL ) 211 { 212 ret = sList->slider; 213 } 214 215 return ret; 216 } 217 218 DLinkListNode* DLinkList_Next(DLinkList* list) 219 { 220 TDLinkList* sList = (TDLinkList*)list; 221 DLinkListNode* ret = NULL; 222 223 if( (sList != NULL) && (sList->slider != NULL) ) 224 { 225 ret = sList->slider; 226 sList->slider = ret->next; 227 } 228 229 return ret; 230 } 231 232 DLinkListNode* DLinkList_Pre(DLinkList* list) 233 { 234 TDLinkList* sList = (TDLinkList*)list; 235 DLinkListNode* ret = NULL; 236 237 if( (sList != NULL) && (sList->slider != NULL) ) 238 { 239 ret = sList->slider; 240 sList->slider = ret->pre; 241 } 242 243 return ret; 244 }
1 #ifndef _DLINKLIST_H_ 2 #define _DLINKLIST_H_ 3 4 typedef void DLinkList; 5 typedef struct _tag_DLinkListNode DLinkListNode; 6 struct _tag_DLinkListNode 7 { 8 DLinkListNode* next; 9 DLinkListNode* pre; 10 }; 11 12 DLinkList* DLinkList_Create(); 13 14 void DLinkList_Destroy(DLinkList* list); 15 16 void DLinkList_Clear(DLinkList* list); 17 18 int DLinkList_Length(DLinkList* list); 19 20 int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos); 21 22 DLinkListNode* DLinkList_Get(DLinkList* list, int pos); 23 24 DLinkListNode* DLinkList_Delete(DLinkList* list, int pos); 25 26 DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node); 27 28 DLinkListNode* DLinkList_Reset(DLinkList* list); 29 30 DLinkListNode* DLinkList_Current(DLinkList* list); 31 32 DLinkListNode* DLinkList_Next(DLinkList* list); 33 34 DLinkListNode* DLinkList_Pre(DLinkList* list); 35 36 #endif
#include <stdio.h> #include <stdlib.h> #include "DLinkList.h" /* run this program using the console pauser or add your own getch, system("pause") or input loop */ struct Value { DLinkListNode header; int v; }; int main(int argc, char *argv[]) { int i = 0; DLinkList* list = DLinkList_Create(); struct Value* pv = NULL; struct Value v1; struct Value v2; struct Value v3; struct Value v4; struct Value v5; v1.v = 1; v2.v = 2; v3.v = 3; v4.v = 4; v5.v = 5; DLinkList_Insert(list, (DLinkListNode*)&v1, DLinkList_Length(list)); DLinkList_Insert(list, (DLinkListNode*)&v2, DLinkList_Length(list)); DLinkList_Insert(list, (DLinkListNode*)&v3, DLinkList_Length(list)); DLinkList_Insert(list, (DLinkListNode*)&v4, DLinkList_Length(list)); DLinkList_Insert(list, (DLinkListNode*)&v5, DLinkList_Length(list)); for(i=0; i<DLinkList_Length(list); i++) { pv = (struct Value*)DLinkList_Get(list, i); printf("%d\n", pv->v); } printf("\n"); DLinkList_Delete(list, DLinkList_Length(list)-1); DLinkList_Delete(list, 0); for(i=0; i<DLinkList_Length(list); i++) { pv = (struct Value*)DLinkList_Next(list); printf("%d\n", pv->v); } printf("\n"); DLinkList_Reset(list); DLinkList_Next(list); pv = (struct Value*)DLinkList_Current(list); printf("%d\n", pv->v); DLinkList_DeleteNode(list, (DLinkListNode*)pv); pv = (struct Value*)DLinkList_Current(list); printf("%d\n", pv->v); DLinkList_Pre(list); pv = (struct Value*)DLinkList_Current(list); printf("%d\n", pv->v); printf("Length: %d\n", DLinkList_Length(list)); DLinkList_Destroy(list); return 0; }
三、双向链表的当前位置可以访问其前驱和后继,这是它重要的特性,在根本程度上可以完全取代单链表