具體的說明就不太詳細說了,註釋都加到Code中去了,很詳細,特此記錄~web
如下是維基百科中對雙鏈表的定義:svg
雙向鏈表,又稱爲雙鏈表,是鏈表的一種,它的每一個數據結點中都有兩個指針,分別指向直接後繼和直接前驅。因此,從雙向鏈表中的任意一個結點開始,均可以很方便地訪問它的前驅結點和後繼結點。通常咱們都構造雙向循環鏈表。函數
其實循環雙鏈表只是將一個鏈變成了一個環,他們均可以從任意一個位置開始,訪問鏈上的任意一個元素,循環鏈表的尾節點的next指針指向了頭結點,而頭節點的prior指針則是指向了尾節點.spa
接下來就是雙鏈表的一些基本功能,而循環列表就須要進一步的拓展了,這裏再也不贅述:指針
#include <stdio.h> #include <malloc.h> #ifndef DLNODE_DLINKLIST_H #define DLNODE_DLINKLIST_H #define TRUE 1 #define ERROR 0 //雙鏈表 typedef struct DLNode { int data; struct DLNode *prior; struct DLNode *next; } DLinkList; /** * 頭插法創建雙鏈表 * @param L 雙鏈表 * @param a 鏈表元素 * @param n 鏈表長度 * @return 返回的是生成的鏈表的首節點的地址 */ DLinkList * CreateListByHead(DLinkList *L, int a[], int n) { DLinkList *s; L->prior = L->next = NULL; for (int i = 0; i < n; ++i) { s = (DLinkList *) malloc(sizeof(DLinkList)); s->data = a[i]; s->next = L->next; if (L->next != NULL) L->next->prior = s; L->next = s; s->prior = L; } return L; } /** * 尾插法創建雙鏈表 * @param L 雙鏈表 * @param a 鏈表元素 * @param n 鏈表長度 * @return 返回的是生成的鏈表的首節點的地址 */ DLinkList * CreateListByRoil(DLinkList *L, int a[], int n) { DLinkList *r = L, *s; //r指針用來指向L的尾節點,s 是每次產生的新的節點 for (int i = 0; i < n; ++i) { s = (DLinkList *) malloc(sizeof(DLinkList)); s->data = a[i]; r->next = s; s->prior = r; r = s;//r始終指向鏈表的尾節點 } r->next = NULL; return L; } /** * 在雙鏈表某邏輯位置上插入值爲e的元素 * @param L 傳入的雙鏈表 * @param i 邏輯位置 * @param e 插入的元素 * @return 插入成功返回TRUE(1),失敗返回ERROR(0) */ int ListInsert(DLinkList *L, int i, int e) { DLinkList *r = L, *s; int j = 0; while (r != NULL && j < i - 1) {//找到第i-1個位置 j++; r = r->next; } if (r == NULL) return ERROR; else { s = (DLinkList *) malloc(sizeof(DLinkList)); s->data = e; s->next = r->next; //可能在最後一個節點以後插入,此時最後一個節點的next爲NULL,不包含指針 if (r->next != NULL) r->next->prior = s; r->next = s; s->prior = r; return TRUE; } } /** * 刪除雙鏈表上邏輯位置的元素 * @param L 雙鏈表 * @param i 邏輯位置 * @return 成功返回TRUE(1),失敗返回ERROR(0) */ int ListDelete(DLinkList *L, int i) { DLinkList *p = L, *q; int j = 0; //首先找到邏輯位置第i-1個元素,防止指針斷鏈 //跟下標沒有關係,由於j<i最後出來的是移動次數 while (p != NULL && j < i - 1) { j++; p = p->next; } if (p == NULL) return ERROR; else { q = p->next; //刪除位置爲空 if (q == NULL) { return ERROR; } p->next = q->next; //這裏其實要分紅兩種狀況,可是最後提取了一下代碼 //可能刪除的是最後一個節點 if (q->next != NULL) q->next->prior = p; free(q); return TRUE; } } /** * 輸出雙鏈表 */ void OutputLink(DLinkList *L){ //輸出前i-1個元素 while (L->next != NULL){ printf("%d<=>",L->data); L = L->next; } printf("%d",L->data); } #endif //DLNODE_DLINKLIST_H
#include <stdio.h> #include "DLinkList.h" #define MAX_SIZE 5 int main() { DLinkList *L = (DLinkList *) malloc(sizeof(DLinkList)); int a[MAX_SIZE]; for (int i = 0; i < MAX_SIZE; ++i) { a[i] = i+1; } //頭插法建立雙鏈表 printf("\n頭插法創建的雙鏈表爲: "); OutputLink(CreateListByHead(L, a, MAX_SIZE)); //尾插法建立雙鏈表 printf("\n尾插法創建的雙鏈表爲: "); OutputLink(CreateListByRoil(L, a, MAX_SIZE)); //在特定位置插入(注意,此時的L爲尾插法創建的鏈表) int k = ListInsert(L, 6, 9); if (k == 0) printf("\nERROR!"); else printf("\n在第六個位置插入後的雙鏈表爲: "); OutputLink(L); //刪除特定位置元素(注意,此時的L爲尾插法創建的鏈表) int z = ListDelete(L, 6); if (z == 0) printf("\nERROR!"); else printf("\n刪除第六個位置的元素後的雙鏈表爲: ");OutputLink(L); return 0; }