複習之資料結構 帶頭結點的雙向鍊錶

2021-10-20 10:17:37 字數 3825 閱讀 8765

我們會發現,單鏈表由於只有next域,所以,如果想要訪問某個元素的前驅結點,那麼只能從頭開始遍歷到該元素的前乙個元素。效率非常的低下。

於是,為了方便的訪問前驅、後繼,雙向鍊錶應運而生。

如上圖所示,就是乙個簡單的雙向煉表示意圖。

雙向鍊錶共含有三個元素:

1、存放資料;

2、後繼指標域;

3、前驅指標域。

雙向鍊錶的插入和刪除操作需要特別注意邊界問題。

正常的插入如下圖:

插入情景:將新結點 p 插入到指定結點 q 的後面

看上去這四個步驟好像沒有什麼問題,但是,步驟2在處理邊界問題的時候容易崩潰,原因如下圖:

故,正確的插入操作需要對步驟2新增條件判斷:

p->next = q->next;

if(p->next !=

null

) q->next = p;

p->prio = q;

刪除操作原理同上,在此就不多做贅述了。

我們來看**:

標頭檔案命名為:dlist.h

#pragma once

// 帶頭結點的雙向鍊錶,不迴圈

typedef

struct dnode

dnode,

*dlist;

// 初始化函式

void

initlist

(dlist plist)

;// 判空

bool isempty

(dlist plist)

;// 獲取資料長度

intgetlength

(dlist plist)

;// 頭插

bool insert_head

(dlist plist,

int val)

;// 尾插

bool insert_tail

(dlist plist,

int val)

;// 在plist中查詢關鍵字key,找到返回目標位址,失敗返回null

dlist search

(dlist plist,

int key)

;// 刪除plist中的第乙個key

bool deleteval

(dlist plist,

int key)

;// 列印輸出所有資料

void

show

(dlist plist)

;// 逆置

void

reverse

(dlist plist)

;// 清空資料

void

clear

(dlist plist)

;// 銷毀動態記憶體

void

destroy

(dlist plist)

;

**檔案命名為:dlist.cpp

#include

#include

#include

#include

"dlist.h"

// 初始化函式

void

initlist

(dlist plist)

// 判空

bool isempty

(dlist plist)

// 獲取資料長度

intgetlength

(dlist plist)

return count;

}// 頭插

bool insert_head

(dlist plist,

int val)

plist->next = p;

p->prio = plist;

return true;

}// 尾插

bool insert_tail

(dlist plist,

int val)

dnode* q =

(dnode*

)malloc

(sizeof

(dnode));

q->data = val;

// 將q插入在尾結點p的後面

q->next = p->next;

p->next = q;

q->prio = p;

return true;

}// 在plist中查詢關鍵字key,找到返回目標位址,失敗返回null

dlist search

(dlist plist,

int key)

}return

null;}

// 刪除plist中的第乙個key

bool deleteval

(dlist plist,

int key)

// 將p從鍊錶中剔除

p->prio->next = p->next;

if(p->next !=

null

)free

(p);

return true;

}// 列印輸出所有資料

void

show

(dlist plist)

printf

("\n");

}// 逆置

void

reverse

(dlist plist)

// 處理頭結點

plist->next = p;

// 處理所有的next域

while

(p->prio != plist)

if(p->prio == plist)

// 接著處理prio域

p = plist->next;

dnode* q = plist;

while

(p !=

null)}

// 清空資料

void

clear

(dlist plist)

// 銷毀動態記憶體

void

destroy

(dlist plist)

}

用如下的測試**來檢驗我們所寫的程式:

#include

#include

#include

"dlist.h"

intmain()

show

(&head)

;reverse

(&head)

;show

(&head)

;return0;

}

輸出結果如下:

筆者這裡著重檢查了逆置函式,順帶檢驗了插入和列印函式,其他的沒有在本測試**中體現,有興趣的可以自行驗證。

嚴蔚敏. 資料結構(c語言版). 北京:清華大學出版社,2009:30.

資料結構 雙向迴圈帶頭結點鍊錶

前面我們寫過了不帶頭結點的單鏈表,由於沒有頭結點,在對單鏈表進行頭插 刪的時候需要傳入二級指標 在需要進行尾插 刪的時候,需要先根據頭指標找到頭結點,然後從頭往後遍歷找到最後乙個結點再進行相應操作。而我們今天要寫的雙向迴圈帶頭結點鍊錶,相對於不帶頭結點的單鏈表做增刪時,將會方便許多。typedef ...

資料結構 帶頭結點雙向迴圈鍊錶相關操作

鍊錶結構如下 相關操作結構 因為帶頭結點,所以在任何結點的操作都是一致的,相對單鏈表來說簡單一些。ifndef linklist h define linklist h include include include 帶頭結點迴圈雙鏈表 typedef int datatype typedef st...

資料結構 帶頭結點的雙向鍊錶操作 C實現

typedef struct dulnode dulnode,dulinklist 鍊錶初始化 void initdulinklist dulinklist plist plist prior plist next null 為了實現以下插入,刪除等一系列操作,先封裝以下功能 int getleng...