【數據結構和算法初階(C語言)】雙向循環帶頭鏈表的增刪查改詳解(天才設計的鏈表結構,應用簡單逆天!!!!!)

目錄

?編輯?編輯

1.雙向鏈表的定義:前赴后繼?

2.帶頭鏈表的定義-----哨兵位?

3.增刪查改

3.1創建新節點函數----方便后續增加節點調用

3.2創建哨兵位----創建頭結點?

3.3增加節點,尾部插入數據?

3.4尾刪除?

3.5查找函數----遍歷+對比,返回節點地址?

3.6頭刪函數

3.7頭插函數?

3.8 計算數組的長度

3.9在任意位置pos前插入?

3.10在任意位置刪除

3.11鏈表的銷毀?

?4、結語及整個源碼含測試用例


1.雙向鏈表的定義:前赴后繼?

typedef int LTDataTYpe;
typedef struct ListNode
{struct ListNode* next;struct ListNode* prev;LTDataTYpe data;
}LTNode;

2.帶頭鏈表的定義-----哨兵位?

3.增刪查改

先寫一個打印函數來方便后續測試:

?

void LTPrint(LTNode* phead)
{assert(phead);LTNode* cur= phead->next;while (cur != phead){//printf("phead");printf("%d<=>", cur->data);cur = cur->next;}}

3.1創建新節點函數----方便后續增加節點調用

申請節點,將前后指針置空同時可以給節點賦值,返回這個節點的地址,也就是指向這個節點的指針

LTNode* BuyNode(LTDataTYpe x)
{LTNode* phead = (LTNode*)malloc(sizeof(LTNode));if (phead == NULL){perror("malloc");exit(-1);}phead->data = x;phead->next = NULL;phead->prev = NULL;return phead;
}

3.2創建哨兵位----創建頭結點?

后續所有節點可以增加在哨兵位的前后就對應前插、尾插。

最開始的哨兵位前后指針都應該指向自己。

LTNode* LTInit()
{LTNode* phead = BuyNode(-1);//首先有一個節點phead->next = phead;phead->prev = phead;return phead;
}

3.3增加節點,尾部插入數據?

兩種情況一樣:

?


void LTPushBack(LTNode* phead, LTDataTYpe x)
{assert(phead);LTNode* tail = phead->prev;LTNode* newnode = BuyNode(x);newnode->prev = tail;tail->next = newnode;newnode->next = phead;phead->prev = newnode;}

3.4尾刪除?


void LTPopBack(LTNode* phead)
{assert(phead);assert(phead->next != phead);LTNode* tail = phead->prev;LTNode* tailprev = tail->prev;free(tail);tail->next = phead;phead->prev = tailprev;
}

3.5查找函數----遍歷+對比,返回節點地址?

LTNode* LTFind(LTNode* phead, LTDataTYpe x)
{assert(phead);LTNode* cur = phead->next;while (cur!= phead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}

3.6頭刪函數

void LTPodFront(LTNode* phead)
{assert(phead);assert(phead->next != phead);LTNode* after = phead->next;LTNode* tail = after->next;phead->next = tail;tail->prev = phead;free(after);
}

3.7頭插函數?

?

void LTPushFront(LTNode* phead, LTDataTYpe x)
{assert(phead);LTNode* d1 = phead->next;LTNode* newnode = BuyNode(x);phead->next = newnode;newnode->next = d1;d1->prev = newnode;newnode->prev = phead;}

?

3.8 計算數組的長度

?這里對于大家可能有一個誤區,我們的頭結點也就是哨兵位,數據領域沒有保存值,就會有伙伴像在數據域保存鏈表的大小,增加就+1,減少就-1,但是這種情況只針對數據域是整型的情況,如果數據領域是浮點數或者字符型,加1可能就導致數據不準確,

方法:遍歷+計數

int LTSize(LTNode* phead)
{assert(phead);//不能是空指針int size = 0;LTNode* cur = phead->next;//定義遍歷指針while (cur != phead){size++;cur = cur->next;}return size;
}

3.9在任意位置pos前插入?

如果pos=head就是尾插

如果pos = head->next就是頭插

void LTInsert(LTNode* pos, LTDataTYpe x)
{//首先要查找的節點不能為空assert(pos);LTNode* newnode = BuyNode(x);LTNode* prv = pos->prev;prv->next = newnode;newnode->prev = prv;newnode->next = pos;pos->prev = newnode;}

3.10在任意位置刪除

刪除一定注意保護頭結點---使用斷言

void LTErase(LTNode* pos)
{assert(pos);LTNode* posprev = pos->prev;LTNode* posnext = pos->next;free(pos);posprev->next = posnext;posnext->prev = posprev;
}

也是可以復用實現頭刪尾刪

3.11鏈表的銷毀?

鏈表不是連續的空間就不會像那種順序表找到頭一下子釋放而是注意釋放

?

void LTDestory(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){LTNode* next = cur->next;free(cur);cur = next;}free(phead);//可以外部置空,不設置返回值和二級指針。}

?4、結語及整個源碼含測試用例

雙向鏈表是一個快捷使用的數據結構,非常實用,不過對于初學建議畫圖來理解增刪查改。很大程度上增刪查改避免了二級指針的傳參,就是因為使用了哨兵位的好處。以上就是本期的所有內容,知識含量蠻多,大家可以配合解釋和原碼運行理解。創作不易,大家如果覺得還可以的話,歡迎大家三連,有問題的地方歡迎大家指正,一起交流學習,一起成長,我是Nicn,正在c++方向前行的奮斗者,數據結構內容持續更新中,感謝大家的關注與喜歡。

源碼:

test.c

#include"List.h"
void test()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPodFront(plist);LTPushFront(plist, 1);LTPrint(plist);printf("\n");//LTInsert(plist,1);//LTPrint(plist);
}
int main()
{test();return 0;
}

?List.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int LTDataTYpe;
typedef struct ListNode
{struct ListNode* next;struct ListNode* prev;LTDataTYpe data;
}LTNode;//創建新節點函數
LTNode* BuyNode(LTDataTYpe x);
//初始化創建哨兵位
LTNode* LTInit();
//尾插一下
void LTPushBack(LTNode* phead, LTDataTYpe x);
//打印鏈表
void LTPrint(LTNode* phead);
//尾刪
void LTPopBack(LTNode* phead);
//計算鏈表的大小或者記錄鏈表的大小
int LTSize(LTNode* phead);
//頭刪函數
void LTPodFront(LTNode* phead);
//頭插一下
void LTPushFront(LTNode* phead, LTDataTYpe x);
//查找函數
LTNode* LTFind(LTNode* phead, LTDataTYpe x);
//在尋找到的任意pos位置之前插入
void LTInsert(LTNode* pos, LTDataTYpe x);//刪除任意位置,pos
void LTErase(LTNode* pos);
//鏈表的銷毀
//鏈表不是連續的空間就不會像那種順序表找到頭一下子釋放而是注意釋放
void LTDestory(LTNode* phead);

List.c

LTNode* BuyNode(LTDataTYpe x)
{LTNode* phead = (LTNode*)malloc(sizeof(LTNode));if (phead == NULL){perror("malloc");exit(-1);}phead->data = x;phead->next = NULL;phead->prev = NULL;return phead;
}LTNode* LTInit()
{LTNode* phead = BuyNode(-1);//首先有一個節點phead->next = phead;phead->prev = phead;return phead;
}void LTPushBack(LTNode* phead, LTDataTYpe x)
{assert(phead);LTNode* tail = phead->prev;LTNode* newnode = BuyNode(x);newnode->prev = tail;tail->next = newnode;newnode->next = phead;phead->prev = newnode;}
void LTPushFront(LTNode* phead, LTDataTYpe x)
{assert(phead);LTNode* d1 = phead->next;LTNode* newnode = BuyNode(x);phead->next = newnode;newnode->next = d1;d1->prev = newnode;newnode->prev = phead;}void LTPrint(LTNode* phead)
{assert(phead);LTNode* cur= phead->next;while (cur != phead){//printf("phead");printf("%d<=>", cur->data);cur = cur->next;}}void LTPopBack(LTNode* phead)
{assert(phead);assert(phead->next != phead);LTNode* tail = phead->prev;LTNode* tailprev = tail->prev;free(tail);tail->next = phead;phead->prev = tailprev;
}int LTSize(LTNode* phead)
{assert(phead);//不能是空指針int size = 0;LTNode* cur = phead->next;//定義遍歷指針while (cur != phead){size++;cur = cur->next;}return size;
}LTNode* LTFind(LTNode* phead, LTDataTYpe x)
{assert(phead);LTNode* cur = phead->next;while (cur!= phead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}void LTInsert(LTNode* pos, LTDataTYpe x)
{//首先要查找的節點不能為空assert(pos);LTNode* newnode = BuyNode(x);LTNode* prv = pos->prev;prv->next = newnode;newnode->prev = prv;newnode->next = pos;pos->prev = newnode;}void LTErase(LTNode* pos)
{assert(pos);LTNode* posprev = pos->prev;LTNode* posnext = pos->next;free(pos);posprev->next = posnext;posnext->prev = posprev;
}void LTPodFront(LTNode* phead)
{assert(phead);assert(phead->next != phead);LTNode* after = phead->next;LTNode* tail = after->next;phead->next = tail;tail->prev = phead;free(after);
}void LTDestory(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){LTNode* next = cur->next;free(cur);cur = next;}free(phead);//可以外部置空,不設置返回值和二級指針。}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/719413.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/719413.shtml
英文地址,請注明出處:http://en.pswp.cn/news/719413.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

AcWing 562.壁畫

咱先看一眼算法標簽&#xff0c;發現是思維題、枚舉、前綴和 Buttt其實我們根據上訴的樣例解釋部分就會發現&#xff0c;其實這就是一個長度為?n/2?&#xff08;向上取整哦&#xff09;的連續子數組的最大和。 這題我也用暴力法試過啦&#xff0c;很明顯會TLE 如果你對dp題…

Mac M系列芯片如何重新安裝系統

使用可引導安裝器重新安裝&#xff08;可用于安裝非最新的 Mac OS&#xff0c;系統降級&#xff0c;需要清除所有數據&#xff0c;過程確保連接上網絡&#xff0c;雖然這種方式不會下載 Mac OS&#xff0c;但是需要下載固件等信息&#xff09; 插入制作好的可引導安裝器&#x…

【使用imgaug庫調整圖像大小并修改對應的XML標簽框】

使用imgaug庫可以方便地進行圖像增強操作&#xff0c;包括調整圖像大小。以下是使用imgaug庫調整圖像大小并修改對應的XML標簽框的示例腳本&#xff1a; 注意修改輸入文件夾路徑、輸出文件夾路徑和目標尺寸為自己內容。 input_folder "path/to/your/input_folder" …

kalibr標定ZED2i雙目加imu

一、錄制bag 本人使用的zed2i相機。 rosbag record -O 32 /zed2i/zed_node/imu/data /zed2i/zed_node/imdata_raw /zed2i/zed_node/left/image_rect_color /zed2i/zed_node/right/image_rect_color /zed2i/zed_node/left_raw/image_raw_color /zed2i/zed_node/right_raw/ima…

Matlab|【免費】基于合作博弈的綜合能源系統利益分配優化調度

目錄 主要內容 部分代碼 結果一覽 下載鏈接 主要內容 該程序實現的模型為綜合能源系統利益分配優化調度&#xff0c;采用合作博弈方法&#xff0c;模型針對IES系統的P2G、電解槽、甲烷反應器、儲氫罐、CHP和燃氣鍋爐等設備進行建模&#xff0c;實現基于合作博弈的…

std::shared_from_this注意事項:exception bad_weak_ptr

1.不可以在構造函數中調用shared_from_this() 因為它的實現是&#xff1a; _LIBCPP_INLINE_VISIBILITYshared_ptr<_Tp> shared_from_this(){return shared_ptr<_Tp>(__weak_this_);}也就是它依賴的__weak_this_此時還未創建完成。 2.一定要public繼承 class MyTy…

大數據開發(Java面試真題-卷二)

大數據開發&#xff08;Java面試真題&#xff09; 1、請簡要說明Java中equeals()和hashCode()的作用及區別&#xff1f;2、Java中的四種訪問修飾符及它們之間的區別&#xff1f;3、請解釋Java中的異常處理機制&#xff0c;包括checked exception和unchecked exception?4、Java…

Linux 學習筆記(10)

十、 進程管理 進程就是運行中的程序&#xff0c;一個運行著的程序&#xff0c;可能有多個進程。 比如 LinuxSir.Org 所用的 WWW 服務器是 apache 服務器&#xff0c;當管理員啟動服務后&#xff0c;可能會有好多人來訪問&#xff0c;也就是說許多用戶來同時請 求 htt…

QT debug編譯失敗:xxx/bin/ld.exe: cannot find -lxxd1

原因&#xff1a;由于編譯時&#xff0c;使用debug模式下&#xff0c;動態庫沒有對應的lxxd1中的xx庫 解決方案1&#xff1a;改為release編譯&#xff1b; 解決方案2&#xff1a;在引用的三方pri文件中&#xff0c;去掉多余的d #修改前 if(!debug_and_release|build_pass):CON…

沃德的背包

題目描述 沃德進入源碼世界的路上有很多寶石&#xff0c;可是沃德的背包只能背總重量不超過m的寶石&#xff0c;路上一共有n個寶石&#xff0c;每個寶石的重量為wi&#xff0c;請你幫沃德選擇盡量多的寶石裝進背包&#xff0c;請注意寶石的總重量不超過m。 輸入描述 第一行輸…

Django官網項目 二

官網地址&#xff1a;Writing your first Django app, part 2 | Django documentation | Django 創建模組&#xff1a; 注冊model &#xff08;bug&#xff1a;沒有加后面的逗號&#xff09; 在manage.py 的目錄下&#xff1a; python manage.py makemigrations polls pyth…

redis09 集群(cluster)

思維草圖 為什么要使用集群 單臺redis內存容量的限制單臺redis并發寫量太大有性能瓶頸 redis集群認識 redis集群是對redis的水平擴容&#xff0c;即啟動N個redis節點&#xff0c;將整個數據分布存儲在這個N個節點中&#xff0c;每個節點存儲總數據的1/N。 如下圖&#xff1…

C++ 根據公式計算橢圓任意點到中心的距離

#include <iostream> using namespace std;double fact(int x) //定義階乘函數。注意是double類型 {double y x; //注意是double類型for (int i x-1; i > 0; i--)y * i;return y; };double My_sin(int x) //定義sin函數。注意是double類型 {double y 0; //注意是do…

【視頻圖像取證篇】Amped FIVE專業法醫圖像和視頻增強軟件之模糊圖像去隔行功能

【視頻圖像取證篇】Amped FIVE專業法醫圖像和視頻增強軟件之模糊圖像去隔行功能 法醫圖像和視頻增強軟件&#xff0c;專業又強大&#xff01;&#xff01;&#xff01;超過 140 種過濾器和工具&#xff0c;用于分析、恢復和增強數字圖像和視頻。Amped FIVE能夠穩定抖動的視頻&…

Linux:ansible-playbook配置文件(劇本)(進階)

Linux&#xff1a;ansible-playbook配置文件&#xff08;劇本&#xff09;_ansible-playbook -i參數-CSDN博客https://blog.csdn.net/w14768855/article/details/132579492?ops_request_misc%257B%2522request%255Fid%2522%253A%2522170930036016800215061982%2522%252C%2522s…

LaTeX排版論文的常見問題匯總(持續更新中)

文章目錄 LaTeX排版論文的常見問題匯總&#xff08;持續更新中&#xff09;1.如何上傳期刊或會議提供的LaTeX模板&#xff1f;2.模板中各文件的說明3.LaTeX中如何設置字體大小&#xff1f;3.1如何設置表格中的字體大小&#xff1f;3.2如何設置表格、圖片標題的字體大小&#xf…

A/D轉換

硬件電路模型 模數轉換代碼 main.c #include <REGX52.H> #include "LCD1602.h" #include "Delay.h" #include "XPT2046.h"unsigned int ADValue; int main(){LCD_Init();LCD_ShowString(1,1,"ADJ NTC RG");while(1){ADValue …

什么是Vue的服務端渲染(SSR)?它有什么作用?

Vue的服務端渲染&#xff08;SSR&#xff09;是指將Vue組件在服務器端進行渲染&#xff0c;然后將已經渲染好的頁面返回給瀏覽器&#xff0c;相比于傳統的客戶端渲染&#xff0c;SSR可以更好地優化SEO和加速首屏加載速度。在傳統的客戶端渲染中&#xff0c;瀏覽器需要加載所有的…

【MySQL系列】在 MacOS 上安裝 MySQL

在 MacOS 上有兩種方式安裝 MySQL 服務器&#xff1a;通過 brew 安裝和通過安裝包安裝。 文章目錄 1、通過 brew 安裝 MySQL1.1、安裝 MySQL1.2、啟動 MySQL 服務器1.3、配置 MySQL 服務器1.4、MySQL 服務器管理命令 2、通過安裝包安裝 MySQL2.1、下載安裝包2.2、安裝 MySQL2.3…

深入理解快速排序算法:從原理到實現

目錄 1. 引言 2. 快速排序算法原理 3. 快速排序的時間復雜度分析 4. 快速排序的應用場景 5. 快速排序的優缺點分析 5.1 優點&#xff1a; 5.2 缺點&#xff1a; 6. Java、JavaScript 和 Python 實現快速排序算法 6.1 Java 實現&#xff1a; 6.2 JavaScript 實現&#…