為什麼需要雙向鍊錶?
在單鏈表中,有了next指標,這就使得要查詢的下乙個結點的時間複雜度為o(1),可是要查詢是上乙個結點的話,最壞的時間複雜度是o(n)了,所以為了克服這一缺點提出雙向鍊錶。
雙向鍊錶:雙向鍊錶是在單鏈表的每個結點中,再設定乙個指向其前驅結點的指標域。
雙向鍊錶中每個結點都有兩個指標域:乙個指向直接後繼,乙個指向直接前驅。
雙向鍊錶中迴圈的帶頭結點的空鍊錶:
非空的迴圈的帶頭結點的雙向鍊錶:
(1)標頭檔案:
實現**:
#pragma once
//雙向鍊錶,帶頭結點,頭的前驅為null,尾的後繼為null
typedef struct dnode
dnode,*dlist;
void initlist(dlist plist);
bool insert_head(dlist plist,int val);//頭插法
bool insert_tail(dlist plist,int val);//尾插法
dnode *search(dlist plist,int key);//查詢
bool delete(dlist plist,int key);//刪除
bool isempty(dlist plist);//判空
int getlength(dlist plist);//獲取長度,資料個數
void show(dlist plist);//列印
dnode *getprio(dlist plist,int key);//獲得key的前驅
dnode *getnext(dlist plist,int key);//獲得key的後繼
void clear(dlist plist);//清空
void destory(dlist plist);//銷毀
(2)原始檔:
實現**:
#include#include#include#include"dlist.h"
void initlist(dlist plist)
plist->next = null;
plist->prio = null;
}bool insert_head(dlist plist,int val)//頭插法
return true;
}bool insert_tail(dlist plist,int val)//尾插法
dnode *search(dlist plist,int key)//查詢
} return null;
}bool delete(dlist plist,int key)//刪除
//將p從鍊錶中剔除
p->prio->next = p->next;
if (p->next != null)
free(p);
return true;
}bool isempty(dlist plist)//判空
int getlength(dlist plist)//獲取長度,資料個數
return count;
}void show(dlist plist)//列印
}dnode *getprio(dlist plist,int key)//獲得key的前驅
} return null;
}dnode *getnext(dlist plist,int key)//獲得key的後繼
return p->next;
}void clear(dlist plist)//清空
void destory(dlist plist)//銷毀
}
測試用例:
1.尾插0-9
2.頭插數字25
3.獲取長度(把頭插25去掉了)
4.查詢8
5.查詢前驅下標
6.查詢後繼下標
7.刪除3
8.清空
9.銷毀
雙向鍊錶的資料結構使用
詳細源自於 在linux核心中,有大量的資料結構需要用到雙迴圈鍊錶,例如程序 檔案 模組 頁面等。若採用雙迴圈鍊錶的傳統實現方式,需要為這些資料結構維護各自的鍊錶,並且為每個鍊錶都要設計插入 刪除等操作函式。因為用來維持鍊錶的next和prev指標指向對應型別的物件,因此一種資料結構的鍊錶操作函式不...
資料結構 鍊錶 雙向鍊錶
注意typedef的定義結構,以及dinklist的資料型別 typedef struct dnode dnode,dinklist 注意插入第乙個結點時,prior指標的空指向問題 if l next null 若l後繼結點為空 則省略該步驟 l next prior p 基本 頭插法建立雙向鍊錶...
資料結構 雙向鍊錶
前幾天寫了乙個單向鍊錶,今天參考自己單向鍊錶改寫了乙個雙向非迴圈鍊錶,下面只討論雙向非迴圈鍊錶。雙向非迴圈鍊錶有如下特點 一 雙向鍊錶每個結點都有乙個前驅指標和後驅指標 當然頭結點和尾結點除外 二 雙向鍊錶中的任意乙個結點開始,都可以很方便地訪問它的前驅結點和後繼結點。三 頭結點只有後驅指標沒有前驅...