雙向連結串列基礎
阿新 • • 發佈:2018-12-29
定義雙向連結串列
雙向連結串列只是在原來的單鏈表中加入了一個前驅指標,因此,在雙鏈表中執行按值查詢和循秩查詢與單鏈表是相同的。但在插入和刪除操作中和單鏈表有著較大的不同。此外雙鏈表還能很方便的找到其前驅結點,因此,除了找到插入結點外,插入和刪除結點的時間複雜度僅為\(O(1)\)。
typedef struct DNode {
ElemType data; //資料域
struct DNode *pred, *succ; //前驅和後繼域
}DNode, *DLinkList;
雙向連結串列的尾插法初始化:
//尾插法 void InitList(DLinkList &L, int n) { DNode *p, *q; L = (DNode*)malloc(sizeof(DNode)); if(!L) exit(0); L->succ = L->pred = NULL; p = L; for(int i = 1; i <= n; ++i) { q = (DNode*)malloc(sizeof(DNode)); q->data = i; if(!q) exit(0); q->succ = NULL; p->succ = q; q->pred = p; p = q; } }
雙向連結串列中的插入操作
在雙向連結串列中第i個位置插入節點s的演算法:
//在第i個位置之後插入新的元素 bool InsertDNode(DLinkList &L, int i, int e) { int j = 1; DNode *p, *q, *s; p = L; while(p && j < i) { p = p->succ; j++; } if(!p || j > i) return false; s = (DNode*)malloc(sizeof(DNode)); s->data = e; s->pred = p; //第一步 s->succ = p->succ; //第二步 p->succ->pred = s; //第三步 p->succ = s; //第四步 }
上述的語句順序不是唯一的,但也不是任意的,一二步必須在第四步之前,否則*p的後繼結點的指標就丟掉了,導致插入失敗。
雙向連結串列的刪除操作
刪除雙向連結串列中第i個位置的後繼節點q的演算法:只需要越過結點i處理i的前驅結點和後繼節點即可。
bool DeleteDNode(DLinkList &L, int i, int &e) { int j = 1; DNode *p, *q, *s; p = L; while(p && j <= i) { //找到結點i所在位置 p = p->succ; j++; } if(!p || j > i + 1) return false; p->pred->succ = p->succ; p->succ->pred = p->pred; free(p); return true; }
總結
雙向連結串列相對於單鏈表來說,要更復雜一些,因為它多了前驅指標,所以在插入和刪除操作時要格外小心,另外,由於它每個結點都要記錄兩份指標,所以略佔空間,不過,由於它良好的對稱性,使得對某個結點的前後結點的操作帶來了方便,可以有效提高演算法的時間效能,說白了就是用空間置換時間。