網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
C++零基礎(chǔ)精通數(shù)據(jù)結(jié)構(gòu)之帶頭雙向循環(huán)鏈表_C 語(yǔ)言
作者:雪芙花 ? 更新時(shí)間: 2022-06-02 編程語(yǔ)言與單鏈表的區(qū)別
單向/雙向
單向:只有一個(gè)next指針,只指向下一位元素
雙向:有兩個(gè)指針,指向上一位和下一位元素,尋找前一節(jié)點(diǎn)和后一節(jié)點(diǎn)很便利
帶頭/不帶頭
帶頭:在本來(lái)的頭結(jié)點(diǎn)之前還有一個(gè)哨兵衛(wèi)節(jié)點(diǎn)作為頭節(jié)點(diǎn),它的址域指針指向頭節(jié)點(diǎn),值域不做使用
不帶頭:沒(méi)有哨兵衛(wèi)頭節(jié)點(diǎn),在尾刪尾插等問(wèn)題中要考慮頭結(jié)點(diǎn)的情況(局限)
循環(huán)/非循環(huán)
循環(huán):頭結(jié)點(diǎn)會(huì)與尾節(jié)點(diǎn)相連
非循環(huán):頭結(jié)點(diǎn)不與尾節(jié)點(diǎn)相連
代碼的實(shí)現(xiàn)
接口
// 創(chuàng)建鏈表(鏈表初始化) ListNode* ListCreate(); //創(chuàng)建節(jié)點(diǎn) ListNode* BuyListNode(ListNode* pHead); // 雙向鏈表銷毀 void ListDestory(ListNode* pHead); // 雙向鏈表打印 void ListPrint(ListNode* pHead); // 雙向鏈表尾插 void ListPushBack(ListNode* pHead, LTDataType x); // 雙向鏈表尾刪 void ListPopBack(ListNode* pHead); // 雙向鏈表頭插 void ListPushFront(ListNode* pHead, LTDataType x); // 雙向鏈表頭刪 void ListPopFront(ListNode* pHead); // 雙向鏈表查找 ListNode* ListFind(ListNode* pHead, LTDataType x); // 雙向鏈表在pos的前面進(jìn)行插入 void ListInsert(ListNode* pos, LTDataType x); // 雙向鏈表刪除pos位置的節(jié)點(diǎn) void ListErase(ListNode* pos);
節(jié)點(diǎn)的構(gòu)造
typedef int LTDataType; typedef struct ListNode { LTDataType data; struct ListNode* next; struct ListNode* prev; }ListNode;
初始化鏈表
// 創(chuàng)建鏈表(初始化) ListNode* ListCreate() { //開辟哨兵衛(wèi)頭結(jié)點(diǎn) ListNode* plist = (ListNode*)malloc(sizeof(ListNode)); if (plist == NULL)//失敗打印錯(cuò)誤信息并結(jié)束進(jìn)程 { perror("ListCreat fail:"); exit(-1); } plist->next = plist; plist->prev = plist; return plist; }
開辟節(jié)點(diǎn)
//創(chuàng)建節(jié)點(diǎn) ListNode* BuyListNode(LTDataType x) { //創(chuàng)建節(jié)點(diǎn) ListNode* newnode = (ListNode*)malloc(sizeof(ListNode)); if (newnode == NULL)//失敗打印錯(cuò)誤信息并結(jié)束進(jìn)程 { perror("creatnode fail:"); exit(-1); } newnode->data = x; //初始化結(jié)點(diǎn) newnode->next = NULL; newnode->prev = NULL; return newnode; }
銷毀鏈表
注:動(dòng)態(tài)開辟的鏈表空間,在不使用后需要將之釋放,避免造成內(nèi)存泄漏
// 雙向鏈表銷毀 void ListDestory(ListNode* pHead) { //斷言傳入指針不為NULL assert(pHead); ListNode* cur = pHead; pHead->prev->next = NULL; while (cur!=NULL) { ListNode* next = cur->next; free(cur); cur = next; } return; }
打印鏈表
// 雙向鏈表打印 void ListPrint(ListNode* pHead) { //斷言傳入指針不為NULL assert(pHead); //創(chuàng)建尋址指針 ListNode* cur = pHead->next; //循環(huán)遍歷鏈表 while (cur != pHead) { //打印數(shù)據(jù) printf("%d->", cur->data); //找到下一個(gè)節(jié)點(diǎn) cur = cur->next; }printf("NULL\n"); return; }
尾插鏈表
// 雙向鏈表尾插 void ListPushBack(ListNode* pHead, LTDataType x) { //斷言傳入指針不為NULL assert(pHead); //創(chuàng)建節(jié)點(diǎn) ListNode* newnode = BuyListNode(x); //找到尾節(jié)點(diǎn) ListNode* tail=pHead->prev; tail->next = newnode; newnode->prev = tail; pHead->prev = newnode; newnode->next = pHead; }
尾刪鏈表
尾刪前記錄前一節(jié)點(diǎn)的地址
// 雙向鏈表尾刪 void ListPopBack(ListNode* pHead) { //斷言傳入指針不為NULL assert(pHead); //只剩哨兵衛(wèi)頭結(jié)點(diǎn)的情況 if (pHead->prev == pHead) return; //記錄尾節(jié)點(diǎn)及其前一節(jié)點(diǎn) ListNode* tail = pHead->prev; ListNode* tailprev = tail->prev; //釋放尾節(jié)點(diǎn) free(tail); //構(gòu)建尾節(jié)點(diǎn)前一節(jié)點(diǎn)與哨兵衛(wèi)頭結(jié)點(diǎn)的關(guān)系 tailprev->next = pHead; pHead->prev = tailprev; return; }
頭插鏈表
頭插前記錄哨兵衛(wèi)頭節(jié)點(diǎn)的下一節(jié)點(diǎn)
// 雙向鏈表頭插 void ListPushFront(ListNode* pHead, LTDataType x) { //斷言傳入指針不為NULL assert(pHead); //創(chuàng)建節(jié)點(diǎn) ListNode* newnode = BuyListNode(x); //記錄哨兵衛(wèi)頭結(jié)點(diǎn)的下一節(jié)點(diǎn) ListNode* next = pHead->next; //構(gòu)建各節(jié)點(diǎn)之間的關(guān)系 pHead->next = newnode; newnode->prev = pHead; newnode->next = next; next->prev = newnode; return; }
頭刪鏈表
// 雙向鏈表頭刪 void ListPopFront(ListNode* pHead) { //斷言傳入指針不為NULL assert(pHead); //只剩哨兵衛(wèi)頭結(jié)點(diǎn)的情況 if (pHead->next == pHead) return; //記錄哨兵衛(wèi)頭結(jié)點(diǎn)下一節(jié)點(diǎn)及其的下一節(jié)點(diǎn) ListNode* next = pHead->next; ListNode* nextNext = next->next; //釋放節(jié)點(diǎn) free(next); pHead->next = nextNext; nextNext->prev = pHead; return; }
查找鏈表
// 雙向鏈表查找 ListNode* ListFind(ListNode* pHead, LTDataType x) { //斷言傳入指針不為NULL assert(pHead); //創(chuàng)建尋址指針 ListNode* cur = pHead->next; while (cur != pHead) { //比較數(shù)據(jù) if (cur->data == x) return cur; //找到下一個(gè)節(jié)點(diǎn) cur = cur->next; } //沒(méi)找到則返回NULL return NULL; }
鏈表pos位置的刪除
void ListErase(ListNode* pos) { assert(pos); ListNode* prev = pos->prev; ListNode* next = pos->next; free(pos); prev->next = next; next->prev = prev; return; }
總結(jié)
我們?cè)趯?shí)帶頭雙向循環(huán)鏈表:結(jié)構(gòu)最復(fù)雜,一般用在單獨(dú)存儲(chǔ)數(shù)據(jù)。實(shí)際中使用的鏈表數(shù)據(jù)結(jié)構(gòu),都是帶頭雙向循環(huán)鏈表。另外這個(gè)結(jié)構(gòu)雖然結(jié)構(gòu)復(fù)雜,但是使用代碼實(shí)現(xiàn)以后會(huì)發(fā)現(xiàn)結(jié)構(gòu)會(huì)帶來(lái)很多優(yōu)勢(shì),實(shí)現(xiàn)反而簡(jiǎn)單現(xiàn)的時(shí)候可以看出其實(shí)帶頭雙向循環(huán)鏈表實(shí)現(xiàn)起來(lái)并不難,而且在雙向循環(huán)特點(diǎn)的加持下,在一些方面顯得格外方便。
但是因?yàn)閹ь^雙向循環(huán)鏈表結(jié)構(gòu)的復(fù)雜性,我們通常還是會(huì)使用邏輯結(jié)構(gòu)相對(duì)簡(jiǎn)單的單鏈表,并且在oj題上考的最多的也是單鏈表。
但我們?nèi)砸炀氄莆諑ь^雙向循環(huán)鏈表的結(jié)構(gòu)和實(shí)現(xiàn)方式,因?yàn)檫@是一種特別且方便的結(jié)構(gòu),且用處十分強(qiáng)大。
原文鏈接:https://blog.csdn.net/yin_ming_hui/article/details/123607952
相關(guān)推薦
- 2022-05-29 C#獲取攝像頭拍照顯示圖像的方法_C#教程
- 2022-04-26 EF?Core通過(guò)顯式編譯提高查詢性能_實(shí)用技巧
- 2021-12-14 如何利用C語(yǔ)言輸出3D立體感心形圖詳解_C 語(yǔ)言
- 2022-09-03 golang架構(gòu)設(shè)計(jì)開閉原則手寫實(shí)現(xiàn)_Golang
- 2022-04-01 containerd常用命令
- 2022-04-20 Python?設(shè)計(jì)模式中命令模式_python
- 2022-09-10 Python實(shí)現(xiàn)自定義異常堆棧信息的示例代碼_python
- 2022-02-24 Android基礎(chǔ)之隱藏標(biāo)題欄/設(shè)置為全屏/橫豎屏切換_Android
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支