我們會發現,單鏈表由於只有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...