網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
C語(yǔ)言?超詳細(xì)介紹與實(shí)現(xiàn)線性表中的無(wú)頭單向非循環(huán)鏈表_C 語(yǔ)言
作者:李逢溪 ? 更新時(shí)間: 2022-06-01 編程語(yǔ)言一、本章重點(diǎn)
- 無(wú)頭單向非循環(huán)鏈表介紹
- 無(wú)頭單向非循環(huán)鏈表常用接口實(shí)現(xiàn)
- 在線oj訓(xùn)練
二、鏈表介紹
概念:鏈表是一種物理存儲(chǔ)結(jié)構(gòu)上非連續(xù)、非順序的存儲(chǔ)結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過(guò)鏈表 中的指針鏈接次序?qū)崿F(xiàn)的。
簡(jiǎn)單的說(shuō):鏈表就是一些結(jié)構(gòu)體相互關(guān)聯(lián)起來(lái),而關(guān)聯(lián)的手段就是指針,通過(guò)存儲(chǔ)下一個(gè)結(jié)構(gòu)體的地址,就能挨個(gè)訪問(wèn)存在結(jié)構(gòu)體里的數(shù)據(jù)。
相比于順序表來(lái)說(shuō)。鏈表能夠解決順序表的一些缺點(diǎn)。
- 從內(nèi)存角度來(lái)說(shuō):無(wú)論是靜態(tài)順序表還是動(dòng)態(tài)順序表都會(huì)有一定的內(nèi)存浪費(fèi),鏈表則是用一個(gè)節(jié)點(diǎn)申請(qǐng)一個(gè)節(jié)點(diǎn),無(wú)內(nèi)存浪費(fèi)。
- 從效率角度上來(lái)說(shuō):順序表不管是頭插還是中間插入與刪除都要移動(dòng)數(shù)據(jù),時(shí)間復(fù)雜度是O(N)。而鏈表則只要改變指針指向即可達(dá)到插入和刪除的效果。
實(shí)際中要實(shí)現(xiàn)的鏈表的結(jié)構(gòu)非常多樣,以下情況組合起來(lái)就有8種鏈表結(jié)構(gòu):
1. 單向、雙向
2. 帶頭、不帶頭
3. 循環(huán)、非循環(huán)
帶頭:
存在一個(gè)哨兵位的節(jié)點(diǎn),該節(jié)點(diǎn)不存儲(chǔ)任何有效數(shù)據(jù),屬于無(wú)效節(jié)點(diǎn),但通過(guò)這個(gè)無(wú)效節(jié)點(diǎn)當(dāng)頭節(jié)點(diǎn)讓我們?cè)谀承┓矫媸褂脮?huì)有一些優(yōu)勢(shì)。
比如,你頭插新節(jié)點(diǎn)時(shí),不需要傳二級(jí)指針,因?yàn)槲覀兊念^節(jié)點(diǎn)始終指向這個(gè)無(wú)效節(jié)點(diǎn)。
帶頭單向非循環(huán)鏈表
雙向:
指的是節(jié)點(diǎn)中不再只有一個(gè)指針,而是有兩個(gè)指針,一個(gè)指向前一個(gè)節(jié)點(diǎn),另一個(gè)指向后一個(gè)節(jié)點(diǎn)。
無(wú)頭雙向非循環(huán)鏈表
循環(huán):
尾指針不再指向NULL,而是指向頭節(jié)點(diǎn)。?
無(wú)頭單向循環(huán)鏈表
三、無(wú)頭單向非循環(huán)鏈表常用接口實(shí)現(xiàn)
3.1動(dòng)態(tài)申請(qǐng)一個(gè)節(jié)點(diǎn)
SLTNode* BuySListNode(SLDataType x) { SLTNode* newnode = malloc(sizeof(SLTNode)); if (newnode == NULL) { printf("malloc fail\n"); exit(-1); } newnode->data = x; newnode->next = NULL; return newnode; }
3.2單鏈表打印
void SListPrint(SLTNode* phead) { SLTNode* cur = phead; while (cur) { printf("%d->", cur->data); cur = cur->next; } printf("NULL\n"); }
3.3單鏈表尾插
void SListPushBack(SLTNode** pphead, SLDataType x) { if (*pphead==NULL) { *pphead = BuySListNode(x); return; } else { SLTNode* tail; tail = *pphead; while (tail->next) { tail = tail->next; } tail->next = BuySListNode(x); return; } }
3.4單鏈表的頭插
void SListPushFront(SLTNode** pphead, SLDataType x) { SLTNode* newnode = BuySListNode(x); newnode->next = *pphead; *pphead = newnode; }
3.5單鏈表的尾刪
void SListPopBack(SLTNode** pphead) { if (*pphead == NULL) { return; } else if((*pphead)->next==NULL) { *pphead = NULL; } else { SLTNode* prev = NULL; SLTNode* tail = *pphead; while (tail->next) { prev = tail; tail = tail->next; } free(tail); prev->next = NULL; } }
3.6單鏈表頭刪
void SListPopFront(SLTNode** pphead) { if (*pphead == NULL) { return; } else { SLTNode* temp = *pphead; (*pphead) = (*pphead)->next; free(temp); } }
3.7單鏈表查找
SLTNode* SListSearch(SLTNode* phead, SLDataType x) { while (phead) { if (phead->data == x) { return phead; } phead = phead->next; } return NULL; }
3.8單鏈表在pos位置之前插入x
void SListInsert(SLTNode** pphead, SLTNode* pos, SLDataType x) { SLTNode* newnode = BuySListNode(x); if (*pphead == NULL) { return; } else if(*pphead==pos) { newnode->next = pos; *pphead = newnode; } else { SLTNode* cur = *pphead; while (cur->next != pos) { cur = cur->next; } newnode->next = pos; cur->next = newnode; } }
3.9單鏈表刪除pos位置的節(jié)點(diǎn)
void SListErase(SLTNode** phead, SLTNode* pos) { if (*phead == NULL) { return; } else if (*phead == pos) { *phead == NULL; } else { SLTNode* cur = *phead; while (cur->next != pos) { cur = cur->next; } cur->next = pos->next; free(pos); } }
四、在線oj訓(xùn)練
4.1移除鏈表元素(力扣)
給你一個(gè)鏈表的頭節(jié)點(diǎn)?head
?和一個(gè)整數(shù)?val
?,請(qǐng)你刪除鏈表中所有滿足?Node.val == val
?的節(jié)點(diǎn),并返回?新的頭節(jié)點(diǎn)?。
輸入:head = [1,2,6,3,4,5,6], val = 6
輸出:[1,2,3,4,5]
輸入:head = [7,7,7,7], val = 7
輸出:[]
?思路:
前后指針(跟班指針),初始轉(zhuǎn)態(tài)prev指向NULL,cur指向head,如果出現(xiàn)cur->val==val.
就進(jìn)行刪除,刪除步驟為prev->next==cur->next;cur=cur->next。迭代過(guò)程為:prev=cur,cur==cur->next。
特殊情況,如果要?jiǎng)h除的val為頭節(jié)點(diǎn),則刪除步驟為head=cur->next;free(cur);cur=head。
代碼參考:
typedef struct ListNode ListNode; struct ListNode* removeElements(struct ListNode* head, int val) { ListNode* cur=head; ListNode* prev=NULL; while(cur) { if(cur->val==val) { if(cur==head) { head=cur->next; free(cur); cur=head; } else { prev->next=cur->next; cur=cur->next; } } else { prev=cur; cur=cur->next; } } return head; }
4.2反轉(zhuǎn)單鏈表(力扣)
給你單鏈表的頭節(jié)點(diǎn)?head
?,請(qǐng)你反轉(zhuǎn)鏈表,并返回反轉(zhuǎn)后的鏈表。
輸入:head = [1,2,3,4,5]
輸出:[5,4,3,2,1]
輸入:head = []
輸出:[]
這里提供一個(gè)頭插思路:newhead=NULL,將head中的數(shù)據(jù)從左到右依次頭插至newhead鏈表中。
typedef struct ListNode ListNode; struct ListNode* reverseList(struct ListNode* head) { ListNode* newhead=NULL; ListNode* cur=head; if(cur==NULL) { return cur; } ListNode* next=cur->next; while(cur) { cur->next=newhead; newhead=cur; cur=next; if(next) next=next->next; } return newhead; }
注意:結(jié)束條件是cur==NULL;此時(shí)如果next往后走,next=next->next;會(huì)出現(xiàn)NULL解引用的問(wèn)題。
其次要考慮cur==NULL的問(wèn)題,不然ListNode* next=cur->next也是對(duì)空指針解引用。
其實(shí)可以化簡(jiǎn)為:
struct ListNode* reverseList(struct ListNode* head) { struct ListNode* cur = head; struct ListNode* newhead = NULL; while(cur) { struct ListNode* next = cur->next; cur->next = newhead; newhead = cur; cur = next; } return newhead; }
原文鏈接:https://blog.csdn.net/m0_62171658/article/details/123300104
相關(guān)推薦
- 2022-10-05 redis?哨兵集群搭建的實(shí)現(xiàn)_Redis
- 2022-06-13 基于Docker與Jenkins實(shí)現(xiàn)自動(dòng)化部署的原理解析_docker
- 2022-10-23 Go語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之選擇排序示例詳解_Golang
- 2023-03-28 python?list與numpy數(shù)組效率對(duì)比_python
- 2022-07-12 用戶(hù)手抖,連續(xù)點(diǎn)了兩次??jī)?yōu)雅解決表單重復(fù)提交
- 2022-02-28 gyp info it worked if it ends with ok npm ERR 解決辦法
- 2021-12-15 liunx安裝Jenkins超詳細(xì)全過(guò)程_Linux
- 2024-03-05 git的使用
- 最近更新
-
- 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概述快速入門(mén)
- 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)程分支