精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

周立功新著內容分享:雙向鏈表是什么?

電子工程師 ? 來源:互聯網 ? 作者:佚名 ? 2017-09-22 18:24 ? 次閱讀

近日周立功教授公開了數年的心血之作《程序設計與數據結構》,電子版已無償性分享到電子工程師與高校群體下載,經周立功教授授權,特對本書內容進行連載。

>>>>1.1 雙向鏈表

單向鏈表的添加、刪除操作,都必須找到當前結點的上一個結點,以便修改上一個結點的p_next指針完成相應的操作。由于單向鏈表的結點沒有指向其上一個結點的指針,因此只有從頭結點開始遍歷鏈表。當某一結點的p_next指向當前結點時,表明它為當前結點的上一個結點。顯然每次都要從頭開始遍歷,其效率極為低下。在單向鏈表中,之所以可以直接獲取單向鏈表中當前結點的下一個結點,是因為結點中包含了指向下一個結點的指針p_next。如果在雙向鏈表的結點中再增加一個指向它的前一個結點的前向指針p_prev,則一切問題將迎刃而解。那么,既有指向下一個結點的指針,又有指向前一個結點的指針的鏈表稱之為雙向鏈表,示意圖詳見圖3.15

圖3.15 雙向鏈表示意圖

與單向鏈表一樣,雙向鏈表也定義了一個頭結點,基于單向鏈表將應用數據與鏈表結構相關數據完全分離的設計思想,則雙向鏈表結點僅保留p_next和p_prev指針。其數據結構定義如下:

typedef struct _dlist_node{

struct _dlist_node *p_next;

struct _dlist_node *p_prev;

}dlist_node_t;

其中,dlist是double list 的縮寫,表明該結點是雙向鏈表結點。由此可見,雖然前向指針使得尋找鏈表的上一個結點變得非常容易,但由于結點中新增了一個指針,因此其內存開銷將會是單向鏈表的兩倍。在實際應用中,應該權衡效率與內存空間,在內存資源非常緊缺的場合,如果結點的添加、刪除操作很少,一點效率的影響可以接受,則選擇使用單向鏈表。而不是一味地追求效率,認為雙向鏈表比單向鏈表好,始終選擇使用雙向鏈表。

圖3.15中,頭結點的p_prev和尾結點的p_next直接被設置為了NULL,此時,如果要直接由頭結點找到尾結點,或者由尾結點找到頭結點,都必須遍歷整個鏈表。可以對這兩個指針稍加利用,使頭結點的p_prev指向尾結點,尾結點的p_next指向頭結點,此時,該雙向鏈表就成了一個循環雙向鏈表,示意圖詳見圖3.16

圖3.16 循環雙向鏈表示意圖

由于循環雙向鏈表的效率更高,可以直接從頭結點找到尾結點,或者從尾結點找到頭結點,且沒有額外的內存空間消耗,僅僅是使用了兩個不打算使用的指針,算是廢物利用,因此下面介紹的雙向鏈表均視為循環雙向鏈表。

類似于單向鏈表,雖然頭結點與普通結點的內容完全相同,但它們的含義卻有所區別,頭結點是鏈表的頭,代表了整個鏈表,擁有此頭結點,就表示其擁有了整個鏈表。為了便于區分頭結點與普通結點,可以單獨定義一個頭結點類型。比如:

typedef dlist_node_t dlist_head_t;

當需要使用雙向鏈表時,首先需要使用該類型定義一個頭結點。比如:

dlist_head_t head;

由于此時還沒有添加其它任何結點,僅存在一個頭結點,因此該頭結點既是第一個結點(頭結點),又是最后一個結點(尾結點)。按照循環鏈表的定義,尾結點的p_next指向頭結點,頭結點的p_prev指向尾結點,僅有一個結點的示意圖詳見圖3.17

圖3.17 空鏈

顯然,僅有頭結點時,其p_next和p_prev都指向本身。即:

head.p_next = &head;

head.p_prev = &head;

為了避免用戶直接操作成員,需要定義一個初始化函數,專門用于初始化鏈表頭結點中各個成員的值,其函數原型(dlist.h)為:

int dlist_init(dlist_head_t *p_head);

其中,p_head指向待初始化的鏈表頭結點。其調用形式如下:

dlist_head_t head;

dlist_init(&head);

dlist_init()函數的實現詳見程序清單3.33

程序清單3.33雙向鏈表初始化函數

1 int dlist_init(dlist_head_t *p_head)

2 {

3 if (p_head == NULL){

4 return -1;

5 }

6 p_head -> p_next = p_head;

7 p_head -> p_prev = p_head;

8 return 0;

9 }

與單向鏈表類似,將提供一些基礎的操作接口,它們的函數原型如下:

dlist_node_t *dlist_prev_get (dlist_head_t *p_head, dlist_node_t *p_pos); //尋找某一結點的前一結點

dlist_node_t *dlist_next_get (dlist_head_t *p_head, dlist_node_t *p_pos); //尋找某一結點的后一結點

dlist_node_t *dlist_tail_get (dlist_head_t *p_head); //獲取尾結點

dlist_node_t *dlist_begin_get (dlist_head_t *p_head); //獲取開始位置第一個用戶結點

dlist_node_t *dlist_end_get (dlist_head_t *p_head); //獲取結束位置尾結點下一個結點的位置

對于dlist_prev_get()和dlist_next_get(),在鏈表結點中已經存在指向前驅后后繼的指針,詳見程序清單3.34

程序清單3.34得到結點前驅和后繼的函數實現

1 dlist_node_t *dlist_prev_get(dlist_head_t *p_head, dlist_node_t *p_pos)

2 {

3 if (p_pos != NULL){

4 return p_pos -> p_prev;

5 }

6 return NULL;

7 }

8

9 dlist_node_t *dlist_next_get(dlist_head_t *p_head, dlist_node_t *p_pos)

10 {

11 if (p_pos != NULL){

12 return p_pos -> p_next;

13 }

14 return NULL;

15 }

dlist_tail_get()函數用于得到鏈表的尾結點,在循環雙向鏈表中,頭結點的p_reev即指向了尾結點詳見程序清單3.35

程序清單3.35 dlist_tail_get()函數實現

1 dlist_node_t *dlist_tail_get(dlist_head_t *p_head)

2 {

3 if (p_head != NULL) {

4 return p_head->p_prev;

5 }

6 return NULL;

7 }

dlist_begin_get()函數用于得到第一個用戶結點,詳見程序清單3.36

程序清單3.36 dlist_begin_get()函數實現

1 dlist_node_t *dlist_begin_get(dlist_head_t *p_head)

2 {

3 if (p_head != NULL){

4 return p_head->p_next;

5 }

6 return NULL;

7 }

dlist_end_get()用于得到鏈表的結束位置,當雙向鏈表設計為循環雙向鏈表時則頭結點的p_prev和尾結點的p_next都被有效地利用了任何有效結點的p_nextp_prev都不再為NULL。顯然,不能再以NULL作為結束位置了,當從第一個結點開始順序訪問鏈表的各個結點時,尾結點的下一個結點就是鏈表頭結點(head),因此結束位置就是頭結點本身。dlist_end_get()的實現詳見程序清單3.37

程序清單3.37 dlist_end_get()函數實現

1 dlist_node_t *dlist_end_get(dlist_head_t *p_head)

2 {

3 if (p_head != NULL) {

4 return p_head->p_prev;

5 }

6 return NULL;

7 }

在公眾號后臺回復關鍵字“程序設計”,即可在線閱讀《程序設計與數據結構》;回復關鍵字“編程”,即可在線閱讀《面向AMetal框架與接口的編程(上)》。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • mcu
    mcu
    +關注

    關注

    146

    文章

    16992

    瀏覽量

    350311
  • 周立功
    +關注

    關注

    38

    文章

    130

    瀏覽量

    37584
  • 鏈表
    +關注

    關注

    0

    文章

    80

    瀏覽量

    10547

原文標題:周立功:雙向鏈表是什么?

文章出處:【微信號:Zlgmcu7890,微信公眾號:周立功單片機】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    立功闡釋高效的雙向鏈表如何用

    實際上循環鏈表,無論是頭結點、尾結點還是普通結點,其本質上都是一樣的。
    的頭像 發表于 09-25 14:14 ?6477次閱讀

    立功教授談迭代器模式設計

    近日立功教授公開了數年的心血之作《程序設計與數據結構》,電子版已無償性分享到電子工程師與高校群體下載,經立功教授授權,特對本書內容進行連
    的頭像 發表于 09-26 13:51 ?6278次閱讀
    <b class='flag-5'>周</b><b class='flag-5'>立功</b>教授談迭代器模式設計

    立功大師EASY FPGA原理圖

    本帖最后由 eehome 于 2013-1-5 09:47 編輯 立功EASYFPGA原理圖立功大師經典力作,FPGA原理圖。歡迎大家下載學習
    發表于 03-16 11:02

    立功的NIOS視頻

    立功的NIOS視頻
    發表于 07-19 09:55

    立功CANTest軟件

    立功CANTest軟件
    發表于 01-15 16:52

    立功CANTest軟件

    立功CANTest軟件
    發表于 02-27 09:26

    【HarmonyOS】雙向循環鏈表

    了一個個雙向循環鏈表,把指針的高效能運用到了極致,這也許就是編程的藝術吧!致敬鴻蒙內核開發者貢獻了如此優秀的源碼,鴻蒙內核源碼可作為大學C語言,操作系統,數據結構三門課的教學項目
    發表于 10-20 15:39

    立功Labvie demo分離ID和CAN內容

    請教,立功 Labview demo中怎么將CAN 的ID和內容分別讀取出來。
    發表于 04-04 17:16

    立功ARM培訓精華

    立功ARM培訓精華 ppt模式,還需下載分段壓縮才可以查看
    發表于 02-11 09:13 ?108次下載

    TinyM0配套教程大全 立功

    TinyM0配套教程大全 立功
    發表于 04-20 16:30 ?0次下載

    立功ARM培訓精華

    立功ARM培訓精華,有需要的下來看看。
    發表于 01-13 17:23 ?41次下載

    算法與數據結構——雙向鏈表

    第三章為算法與數據結構,本文為3.3 雙向鏈表
    的頭像 發表于 09-19 17:56 ?7263次閱讀
    算法與數據結構——<b class='flag-5'>雙向</b><b class='flag-5'>鏈表</b>

    了解Linux通用的雙向循環鏈表

    在linux內核中,有一種通用的雙向循環鏈表,構成了各種隊列的基礎。鏈表的結構定義和相關函數均在include/linux/list.h中,下面就來全面的介紹這一鏈表的各種API。
    發表于 05-07 10:44 ?667次閱讀

    單片機教程 立功

    單片機教程 立功
    發表于 11-19 14:17 ?0次下載

    雙向循環鏈表的創建

    需要注意的是,雖然雙向循環鏈表成環狀,但本質上還是雙向鏈表,因此在雙向循環鏈表中,依然能夠找到頭
    的頭像 發表于 05-24 16:27 ?2079次閱讀