資料結構之鍊錶的高階 雙向鍊錶

2021-10-24 11:10:03 字數 4165 閱讀 1073

上一章提到了鍊錶,表中各節點均只有乙個指標,且都統一指向直接後繼節點,通常這類鍊錶稱為單向鍊錶(或單鏈表)。

雖然單鏈錶能100%解決「一對一」資料的儲存問題,但是在解決某些特殊問題時,單鏈表並不是效率最優的儲存結構,例如在某個場景需要大量的查詢前驅節點,這種情況下使用單鏈表無疑是災難性的問題,因為單鏈表更適合「從前往後」找,「從後往前」並不是它的強項。而為了解決這種逆向查詢(從後往前)問題,本章將會講解雙向鍊錶,使解決問題事半功倍。

雙向鍊錶,簡稱雙鏈表, 從名字上可以理解,即鍊錶是雙向的,如圖所示:

雖然鍊錶節點之間邏輯關係是雙向的,但是通常頭指標只設定乙個

前驅指標:指向該節點的前驅節點

資料域:存放資料元素

後繼指標:指向該節點的後繼

因此,雙鏈表的節點結構用c語言表示為:

typedef

struct lineline;

鍊錶的建立

跟單鏈表相比,雙鏈表多了乙個指向前驅節點的指標,因此,我們可以用建立單鏈表的思路實現對雙鏈表的建立。

與建立單鏈表不同的是,建立雙鏈表的過程中,每乙個新節點都要和前驅節點之間建立兩次連線:

如下:

line*

initline

(line * head)

//返回新建立的鍊錶

return head;

}

雙向鍊錶的操作

與單鏈表類似,需要分三種情況

1)新增至表頭

將新資料元素新增到表頭,只需要將該元素與表頭元素建立雙層邏輯關係即可。

換句話說,假設新元素節點為 temp,表頭節點為 head,則需要做以下 2 步操作即可:

temp->next=head; head->prior=temp;

將 head 移至 temp,重新指向新的表頭;

2)新增至中間位置

同單鏈表新增資料類似,雙向鍊錶中間位置新增資料需要經過以下 2 個步驟,如圖所示:

新節點先與其直接後繼節點建立雙層邏輯關係;

新節點的直接前驅節點與之建立雙層邏輯關係;

3)新增至表尾

與新增到表頭是乙個道理,實現過程如下:

找到雙鏈表中最後乙個節點;

讓新節點與最後乙個節點進行雙層邏輯關係;、

參考**如下:

//data 為要新增的新資料,add 為新增到鍊錶中的位置

line *

insertline

(line * head,

int data,

int add)

else}if

(body)

else}}

return head;

}

過程與單鏈表刪除類似,遍歷找到後摘除節點即可:

c語言**實現如下:

//刪除結點的函式,data為要刪除結點的資料域的值

line *

delline

(line * head,

int data)

temp = temp->next;

}printf

("鍊錶中無該資料元素\n");

return head;

}

因為雙鏈表和單鏈表都是只有乙個頭指標,因此,查詢與單鏈表類似,都是從表頭依次遍歷表中元素:

//head為原雙鏈表,elem表示被查詢元素

intselectelem

(line * head,

int elem)

i++; t = t->next;

}//程式執行至此處,表示查詢失敗

return-1

;}

與單鏈表類似,更改時基於查詢的基礎上完成的,通過遍歷查詢到儲存有該元素的節點,直接更改資料域內容即可

實現操作如下:

//更新函式,其中,add 表示更改結點在雙鏈表中的位置,newelem 為新資料的值

line *

amendelem

(line * p,

int add,

int newelem)}if

(temp)

return p;

}

總結

日常總結**:

#include

#include

typedef

struct line line;

//雙鏈表的建立

line*

initline

(line * head)

;//雙鏈表插入元素,add表示插入位置

line *

insertline

(line * head,

int data,

int add)

;//雙鏈表刪除指定元素

line *

delline

(line * head,

int data)

;//雙鏈表中查詢指定元素

intselectelem

(line * head,

int elem)

;//雙鏈表中更改指定位置節點中儲存的資料,add表示更改位置

line *

amendelem

(line * p,

int add,

int newelem)

;//輸出雙鏈表的實現函式

void

display

(line * head)

;int

main()

line*

initline

(line * head)

return head;

}line *

insertline

(line * head,

int data,

int add)

else}if

(body)

else}}

return head;

}line *

delline

(line * head,

int data)

temp = temp->next;

}printf

("鍊錶中無該資料元素\n");

return head;

}//head為原雙鏈表,elem表示被查詢元素

intselectelem

(line * head,

int elem)

i++; t = t->next;

}//程式執行至此處,表示查詢失敗

return-1

;}//更新函式,其中,add 表示更改結點在雙鏈表中的位置,newelem 為新資料的值

line *

amendelem

(line * p,

int add,

int newelem)}if

(temp)

return p;

}//輸出鍊錶的功能函式

void

display

(line * head)

else

temp = temp->next;

}}

資料結構 鍊錶 雙向鍊錶

注意typedef的定義結構,以及dinklist的資料型別 typedef struct dnode dnode,dinklist 注意插入第乙個結點時,prior指標的空指向問題 if l next null 若l後繼結點為空 則省略該步驟 l next prior p 基本 頭插法建立雙向鍊錶...

資料結構之雙向鍊錶

簡述 指標域有乙個指標 而言,占用資源更大,但相應的 雙向鍊錶遍歷的時候只需要乙個指標就可以,而且 只有得到其中任何乙個節點就是得到整個鍊錶,單向鍊錶必須得到他的頭節點,才能遍歷整個鍊錶,而且得有兩個指標。實現 bothwaylinklist.h ifndef mymodule h define m...

資料結構之 雙向鍊錶

單鏈表的結點都只有乙個指向下乙個結點的指標。單鏈表的資料元素無法直接訪問其前驅元素。建立鍊錶 銷毀鍊錶 獲取鍊錶長度 清空鍊錶 獲取第pos個元素操作 插入元素到位置pos 刪除位置pos處的元素 dlinklist dlinklist creat 建立乙個鍊錶 void dlinklist des...