国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

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

    文章

    4417

    瀏覽量

    67509
  • 鏈表
    +關注

    關注

    0

    文章

    80

    瀏覽量

    11061

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

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

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    功率循環基礎篇(二) —— 功率循環壽命曲線解讀

    功率循環壽命曲線是評估功率半導體器件(如 ?IGBT?模塊)在溫度交變應力下長期可靠性的核心工具。該曲線通常以 結溫波動幅度?ΔTj 為橫坐標,以器件達到指定失效判據前所經歷的 循環次數?Nf 為
    的頭像 發表于 03-02 11:55 ?60次閱讀
    功率<b class='flag-5'>循環</b>基礎篇(二) —— 功率<b class='flag-5'>循環</b>壽命曲線解讀

    CS5801搭配AS721芯片實現HDMI轉DP雙向互轉方案

    CS5801與AS721芯片組合實現HDMI與DP雙向互轉。CS5801支持HDMI2.0b轉DP1.4a,提供4K@60Hz傳輸;AS721作為低功耗交換機芯片實現雙向信號切換。方案
    的頭像 發表于 01-21 10:20 ?237次閱讀
    CS5801搭配AS721芯片<b class='flag-5'>實現</b>HDMI轉DP<b class='flag-5'>雙向</b>互轉方案

    如何在Zephyr RTOS中實現延時和計時函數

    多種延時與計時實現方案,滿足不同應用場景的需求。那么,大家平時都是怎么在MCU程序中實現計時函數實現延時的呢?
    的頭像 發表于 12-26 10:32 ?5454次閱讀
    如何在Zephyr RTOS中<b class='flag-5'>實現</b>延時和計時<b class='flag-5'>函數</b>

    內存拷貝函數 memcpy原理及實現

    內存拷貝函數memcpymemcpy是memory copy的縮寫,意為內存復制,在寫C語言程序的時候,我們常常會用到的函原型如下:void *memcpy(void *dest, const
    發表于 12-26 08:03

    雙向保護開關評估套件使用指南

    負載斷開。今天,我們就來詳細介紹雙向開關評估套件EVAL_BDPS_DD_TOLL/G和EVAL_BDPS_DRIVER,主要用于測試和評估MOSFET的性能。 文件下載: Infineon
    的頭像 發表于 12-20 20:35 ?1082次閱讀

    無數據域雙向鏈表的代碼

    ); return 0; } 在這個示例中,我們定義了一個包含指向前一個節點和后一個節點的結構體 Node,以及一個包含整數數據和 Node 結構體的結構體 Data。然后實現了插入和打印鏈表函數。在打
    發表于 12-11 06:56

    實現一個嵌入式的軟件定時器

    所有運行中的軟件定時器,將各個到期時間與全局時鐘標記做比較,以判斷對應軟件定時器是否到期,到期則執行相應的回調函數,并關閉該定時器。 以上是單次定時器的實現,若要實現周期定時器,即到期后接
    發表于 12-10 08:29

    控制流和函數調用的精細調整

    特性,避免不必要的計算。 函數調用涉及開銷,因為需要保存當前執行環境并跳轉到新的執行環境。減少函數調用,尤其是在頻繁執行的循環中,可以顯著提高性能。 對于簡單且頻繁調用的
    發表于 11-14 06:32

    使用函數實現三相電機正反轉控制

    在使用西門子S1200PLC,所使用的軟件是博途軟件,在這個軟件里運用了塊的概念。比如我們常見的組織塊(OB)、函數塊(FB)、數據塊(DB)以及函數FC等。今天我們來具體交流一下這個函數塊(FB)的具體使用方法。
    的頭像 發表于 10-15 14:40 ?2718次閱讀
    使用<b class='flag-5'>函數</b>塊<b class='flag-5'>實現</b>三相電機正反轉控制

    rt_object_get_information獲取到的鏈表為空怎么解決?

    rtt啟動過程,在初始化堆的時候,進入rt_object_init,調用rt_object_get_information獲取到的鏈表為空,導致系統起不來。
    發表于 10-11 11:44

    人工智能行業如何使用for循環語句進行循環

    : 支持range()函數生成數字序列 可結合else語句使用 Java中的for循環: 傳統結構:for(初始化; 條件; 增量) 增強for循環:for(類型 變量 : 集合) 主要用于數組和集合
    的頭像 發表于 09-10 12:55 ?567次閱讀

    如何實現高效雙向電能變換

    隨著電動汽車、家庭和工商業儲能產品快速普及,雙向電能變換系統的熱度也在不斷攀升。作為電網與電池的功率橋梁,雙向電能變換系統基于一套硬件電路就能控制電池充放電,實現能量雙向流動,相比傳統
    的頭像 發表于 07-23 11:40 ?1556次閱讀

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

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

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

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

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

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