在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

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

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

3天內不再提示

雙向循環鏈表函數是什么?如何去實現它?

Android編程精選 ? 來源:編程學習總站 ? 作者:寫代碼的牛頓 ? 2021-06-17 12:50 ? 次閱讀

1、雙向循環鏈表結點定義和函數聲明

雙向循環鏈表結點內部有2個指針prev和next分別指向前后的結點,結點定義代碼如下:

typedefstructdlist{ intdata; structdlist*next; structdlist*prev; }dlist_t;

現在我們聲明一些雙向循環鏈表操作函數,代碼如下:

externdlist_t *new_dlist_node(intdata); //新建一個結點 externdlist_t *dlist_add(dlist_t*list, intdata); //插入一個結點 externdlist_t *dlist_delete(dlist_t*list, intindex); //刪除索引對應的結點(索引從0開始) externdlist_t *dlist_index_of(dlist_t*list, intindex); //查找索引對應的結點 externvoiddlist_destroy(dlist_t*list); //銷毀雙向循環鏈表 externvoiddlist_print(dlist_t*list); //打印鏈表數據

可以看到很多函數都會返回一個dlist_t類型的指針,其實這是頭結點。很多時候為了書寫方便我們會采用typedef定義自己的數據類型,結點定義里為什么next和prev指針可以那樣寫,參考我上一篇文章,后面會大量這樣使用。

2、雙向循環鏈表函數實現

為了更方便釋放一個結點內存,我們定義了一個文件作用域靜態函數free_dlist_node。

voidfree_dlist_node(dlist_t*node){ if(node == NULL){ return; } node->next = NULL; node->prev = NULL; free(node); node = NULL; }

該函數只負責釋放內存的操作。

新建鏈表結點

dlist_t*new_dlist_node(intdata){ dlist_t*node = (dlist_t*)malloc(sizeof(dlist_t)); if(node == NULL){ returnNULL; } node->data = data; node->next = node; node->prev = node; returnnode; }

這里我們主要注意一點就是新建立的結點next和prev指針會初始化為指向自身,事實上雙向循環鏈表頭結點必須這樣初始化才能更好的利用雙向循環鏈表特性執行插入、刪除和查詢等操作。

插入結點

dlist_t *dlist_add(dlist_t *list, int data){ if(list== NULL){ returnNULL; } //新建一個結點 dlist_t *node = new_dlist_node(data); if(node == NULL){ returnlist; } //將結點插入雙向循環鏈表 list->prev->next = node; //最后的結點next指針指向node node->next = list; //node的next指針指向頭結點 node->prev = list->prev; //node的prev指針指向原尾結點 list->prev = node; //頭結點的prev指針指向新尾結點 returnlist; }

這里list是傳入的頭結點,我們采用尾插法插入一個結點,最后返回頭結點。這里需要注意:每次插入結點都要更新頭結點的prev指針。

刪除指定位置的結點

dlist_t *dlist_delete(dlist_t *list, int index){ if(list== NULL|| index < 0){ ????????return?list; ????} ????dlist_t *head = list; ????int list_index = 0; ????//刪除鏈表頭結點 ????if(index == 0){ ????????//鏈表只有一個結點 ????????if(head == list->next){ free_dlist_node(list); list= NULL; returnNULL; }else{ //鏈表有大于1個結點 head = head->next; //頭結點往后移一個 head->prev = list->prev; //頭結點的prev指向尾部結點 list->prev->next = head; //尾部結點的next指針指向頭結點 free_dlist_node(list); //釋放結點內存 returnhead; } } list= list->next; list_index++; //查詢目標結點,通過檢查當前結點是否是頭結點判斷是否已經把雙線循環鏈表遍歷了一遍 while(list_index < index && head != list){ ????????list?= list->next; list_index++; } //沒有找到即將刪除的結點 if(head == list){ returnhead; } //找到即將刪除的結點 else{ list->prev->next = list->next; //目標結點的上一個結點的next指針指向目標結點的下一個結點 list->next->prev = list->prev; //目標結點的下一個結點的prev指針指向目標結點的上一個結點 free_dlist_node(list); //釋放結點內存 returnhead; //返回頭結點 } }

刪除結點一定要注意:

判斷被刪除的結點是否是頭結點

指定的位置是否超出了鏈表的長度。

查找指定位置的結點

dlist_t*dlist_index_of(dlist_t*list, intindex){ if(list== NULL|| index < 0){ ????????return?NULL; ????} ????//如果想要獲取頭結點,則直接返回頭結點 ????if(index == 0){ ????????return?list; ????} ????dlist_t?*head = list; ????list?= list->next; intlist_index = 1; //遍歷鏈表查找指定的索引,通過檢查當前結點是否等于頭結點判斷是否已遍歷完畢 while(list_index < index && list?!= head){ ????????list_index++; ????????list?= list->next; } //沒有找到索引對應的結點 if(list== head){ returnNULL; } //找到了索引對應的結點 returnlist; }

查找指定位置結點要注意幾個地方:

是否是頭結點

是否超出了鏈表長度

銷毀鏈表

void dlist_destroy(dlist_t *list){ if(list== NULL){ return; } //如果只有一個結點 if(list->next == list){ free_dlist_node(list); return; } dlist_t *temp = list; list= list->next; while(list!= temp){ list= list->next; //遍歷下一個結點 temp->prev->next = list; list->prev = temp->prev; temp->next = NULL; temp->prev = NULL; free(temp); temp = list; } free_dlist_node(list); }

打印鏈表數據

voiddlist_print(dlist_t*list){ if(list== NULL){ return; } dlist_t*head = list; printf("%d, ", list->data); list= list->next; while(list!= head){ printf("%d, ", list->data); list= list->next; } printf(" "); }

最后我們寫個小程序驗證一下雙向循環鏈表函數實現是否正確。

#include #include"dlist.h" intmain(){ dlist_t*list= new_dlist_node(2); inti = 0; for(i = 0; i < 7; i++){ ????????list?= dlist_add(list, 3?+ i); ????} ????printf("打印未處理過的完整鏈表 "); ????dlist_print(list); ????list?= dlist_delete(list, 0); //刪除第一個結點 ????list?= dlist_delete(list, 3); //刪除第四個結點 ????printf("打印刪除2個結點后的鏈表 "); ????dlist_print(list); ????dlist_t?*node = dlist_index_of(list, 2); ????printf("第3個結點是:%d ", node->data); printf("銷毀鏈表 "); dlist_destroy(list); list= NULL; return0; }

編譯運行輸出:

打印未處理過的完整鏈表 2, 3, 4, 5, 6, 7, 8, 9, 打印刪除2個結點后的鏈表 3, 4, 5, 7, 8, 9, 第3個結點是:5 銷毀鏈表

驗證完全正確。

責任編輯:lq6

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

    關注

    3

    文章

    4371

    瀏覽量

    64255
  • 鏈表
    +關注

    關注

    0

    文章

    80

    瀏覽量

    10791

原文標題:數據結構與算法篇-雙向循環鏈表

文章出處:【微信號:AndroidPush,微信公眾號:Android編程精選】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦
    熱點推薦

    什么是光伏雙向電表?雙向電表有哪些應用?

    電能的雙向流動軌跡。在用戶側并網運行模式下,不僅計量用戶從公共電網獲取的用電量(正向有功電能),同時精準統計光伏系統向電網回饋的發電量(逆向有功電能),實現能源流量的全維度監控。 技術支持 安科瑞 程瑜 187 0211 2087 雙向
    的頭像 發表于 05-12 09:42 ?217次閱讀
    什么是光伏<b class='flag-5'>雙向</b>電表?<b class='flag-5'>雙向</b>電表有哪些應用?

    函數指針的六個常見應用場景

    函數指針在嵌入式開發中有著廣泛的應用,讓代碼更加靈活,減少冗余,提高可擴展性。很多時候,我們需要根據不同的情況動態調用不同的函數,而函數指針正是
    的頭像 發表于 04-07 11:58 ?376次閱讀
    <b class='flag-5'>函數</b>指針的六個常見應用場景

    給uint32_t數組填充整型值,除使用循環賦值外有沒有c庫函數可以實現?

    給uint32_t數組填充整型值,除使用循環賦值外有沒有c庫函數可以實現
    發表于 03-07 17:05

    技術干貨驛站 ▏深入理解C語言:嵌套循環循環控制的底層原理

    大家好!在上一節中,我們學習了C語言中的基本循環語句,如for、while和do...while循環。今天,我們將進一步探討嵌套循環循環控制,這些技巧可以幫助我們
    的頭像 發表于 02-21 18:26 ?493次閱讀
    技術干貨驛站  ▏深入理解C語言:嵌套<b class='flag-5'>循環</b>與<b class='flag-5'>循環</b>控制的底層原理

    stdio.h實現了printf函數?

    我們平時包含的 stdio.h 頭文件,里面是不是實現了 printf 函數? 為什么會有這個疑問?因為每次使用 printf,就得包含 stdio.h ,這就導致很多同學誤以為,stdio.h
    的頭像 發表于 12-18 10:28 ?545次閱讀

    深入理解C語言:循環語句的應用與優化技巧

    在程序設計中,我們常常需要重復執行某一段代碼。為了提高效率和簡化代碼,循環語句應運而生。C語言作為一門經典的編程語言,提供了多種循環控制結構,幫助程序員高效地實現重復操作。掌握循環語句
    的頭像 發表于 12-07 01:11 ?534次閱讀
    深入理解C語言:<b class='flag-5'>循環</b>語句的應用與優化技巧

    使用C語言實現函數模板

      用C語言能不能實現一個通用的函數,既能完成整數的相加,又能完成浮點數的相加?
    的頭像 發表于 11-09 11:38 ?871次閱讀

    利用位反轉尋址實現循環緩沖器

    電子發燒友網站提供《利用位反轉尋址實現循環緩沖器.pdf》資料免費下載
    發表于 10-28 10:01 ?0次下載
    利用位反轉尋址<b class='flag-5'>實現</b><b class='flag-5'>循環</b>緩沖器

    兩個循環里后臺讀取串口信息了,和前面板有一個按鈕 怎么控制另外的同一個動作呢

    我在兩個循環里 讀取串口信息了, 怎么控制另外的同一個動作呢 大佬們,這個可以實現嗎,。目前搞到了是串口接收循環里,收到字符串,就比較長度,符合就觸發來另外
    發表于 10-19 09:25

    雙向晶閘管交流調壓的工作原理

    雙向晶閘管(Bidirectional Thyristor,簡稱Triac)交流調壓技術是一種重要的電力電子技術,利用雙向晶閘管的特性來實現對交流電壓的精確控制。
    的頭像 發表于 10-18 17:51 ?3320次閱讀

    什么叫系統的頻率響應函數?和傳遞函數有何關系

    系統的頻率響應函數(Frequency Response Function, FRF)是描述線性時不變(Linear Time-Invariant, LTI)系統在不同頻率下輸入和輸出之間關系的數學
    的頭像 發表于 10-18 09:29 ?4217次閱讀

    什么是雙向散射分布函數?新思科技BSDF測量解決方案

    質地不同,在表面產生了優化和不同效果。這些現象背后都可以使用一個科學概念──雙向散射分布函數(BSDF)來進行解釋和描述。通過測量散射數據,我們可以更深入地了解材料如何影響光線的散射,并進一步優化產品設計以提升視覺體驗。
    的頭像 發表于 08-12 09:56 ?1647次閱讀
    什么是<b class='flag-5'>雙向</b>散射分布<b class='flag-5'>函數</b>?新思科技BSDF測量解決方案

    TS3DV621雙向復用器/復用器數據表

    電子發燒友網站提供《TS3DV621雙向復用器/復用器數據表.pdf》資料免費下載
    發表于 07-10 09:14 ?0次下載
    TS3DV621<b class='flag-5'>雙向</b>復用器/<b class='flag-5'>去</b>復用器數據表

    DS64BR401帶均衡和加重功能的四路雙向中繼器數據表

    電子發燒友網站提供《DS64BR401帶均衡和加重功能的四路雙向中繼器數據表.pdf》資料免費下載
    發表于 07-05 09:37 ?0次下載
    DS64BR401帶均衡和<b class='flag-5'>去</b>加重功能的四路<b class='flag-5'>雙向</b>中繼器數據表

    循環神經網絡的基本原理是什么

    具有循環,能夠將前一個時間步的信息傳遞到下一個時間步,從而實現對序列數據的建模。本文將介紹循環神經網絡的基本原理。 RNN的基本結構 1.1 神經元模型 RNN的基本單元是神經元,每個神經元接收輸入信號,通過激活
    的頭像 發表于 07-04 14:26 ?1082次閱讀
    主站蜘蛛池模板: 日本free护士姓交 | 中文字幕天堂网 | 欧美色图28p | 喷潮白浆直流在线播放 | 色在线视频免费 | 色婷综合 | 天堂网在线www | 日韩欧美亚洲综合久久影院d3 | 四虎永久在线精品国产 | 国产三级日本三级韩国三级在线观看 | 黄色国产在线视频 | 欧美日韩精品一区二区在线线 | 濑亚美莉vs黑人欧美视频 | 被cao到合不拢腿腐男男 | 亚洲大尺度视频 | 亚洲 欧美 丝袜 制服 在线 | 男人和女人做a免费视频 | 中文天堂在线观看 | 精品伊人久久大线蕉色首页 | 国产美女一级高清免费观看 | 色多多视频在线观看免费大全 | 国产色秀视频在线观看 | 月夜免费观看高清在线完整 | 特级aaaaaaaaa毛片免费视频 | 天天操bb| 一区二区三区免费视频播放器 | 天天天天天操 | 亚洲影视久久 | 伊人小婷婷色香综合缴缴情 | 男人都懂的网址在线看片 | 国产精品久久自在自2021 | 欧美高清在线播放 | 天堂网在线www | 婷婷资源 | 久久精品视频5 | 欧美精品成人久久网站 | 人人射人人干 | 天天色天天干天天 | 男人不识本网站上遍色站也枉然 | 特一级黄色毛片 | 三级毛片免费观看 |