C語言實現(xiàn)單鏈表反轉(zhuǎn)
一、理解指針
看懂鏈表的結(jié)構(gòu)并不是很難,但是一旦把它和指針混在一起,就很容易讓人摸不著頭腦。所以,要想寫對鏈表代碼,首先就要理解好指針。
有些語言有“指針”的概念,比如 C 語言;有些語言沒有指針,取而代之的是“引用”,比如 Java、Python。不管是“指針”還是“引用”,實際上,它們的意思都是一樣的,都是存儲所指對象的內(nèi)存地址。
將某個變量賦值給指針,實際上就是將這個變量的地址賦值給指針,或者反過來說,指針中存儲了這個變量的內(nèi)存地址,指向了這個變量,通過指針就能找到這個變量。
p->next=q。這行代碼是說,p 結(jié)點中的 next 指針存儲了 q 結(jié)點的內(nèi)存地址。p->next=p->next->next。這行代碼表示,p 結(jié)點的 next 指針存儲了 p 結(jié)點的下下一個結(jié)點的內(nèi)存地址。
C語言標(biāo)準(zhǔn)規(guī)定,對于一個符號的定義,編譯器總是從它的名字開始讀取,然后按照優(yōu)先級順序依次解析。對,從名字開始,不是從開頭也不是從末尾,這是理解復(fù)雜指針的關(guān)鍵!
對于初學(xué)者,有幾種運算符的優(yōu)先級非常容易混淆,它們的優(yōu)先級從高到低依次是:
定義中被括號( )括起來的那部分。后綴操作符:括號( )表示這是一個函數(shù),方括號[ ]表示這是一個數(shù)組。前綴操作符:星號*表示“指向xxx的指針”。
在本章中我們最多只用到二級指針因此將對二級指針做下說明。比如int **p,是什么意思?
首先看 *p 。 “*”表示P是一個指針。但是是指向什么的指針呢?
在看前面的int* ,int是一個整型類型后面加一個“*”表示整型類型的指針。
*p就是指向整型類型指針的指針。p保存的是整型類型指針的地址。
二、警惕指針丟失和內(nèi)存泄漏
不知道你有沒有這樣的感覺,寫鏈表代碼的時候,指針指來指去,一會兒就不知道指到哪里了。所以,我們在寫的時候,一定注意不要弄丟了指針。指針往往都是怎么弄丟的呢?我拿單鏈表的插入操作為例來給你分析一下。
指針往往都是怎么弄丟的呢?我拿單鏈表的插入操作為例來給你分析一下。
如圖所示,我們希望在結(jié)點 a 和相鄰的結(jié)點 b 之間插入結(jié)點 x,假設(shè)當(dāng)前指針 p 指向結(jié)點 a。如果我們將代碼實現(xiàn)變成下面這個樣子,就會發(fā)生指針丟失和內(nèi)存泄露。
p->next = x; // 將p的next指針指向x結(jié)點; x->next = p->next; // 將x的結(jié)點的next指針指向b結(jié)點;
初學(xué)者經(jīng)常會在這兒犯錯。p->next 指針在完成第一步操作之后,已經(jīng)不再指向結(jié)點 b 了,而是指向結(jié)點 x。第 2 行代碼相當(dāng)于將 x 賦值給 x->next,自己指向自己。因此,整個鏈表也就斷成了兩半,從結(jié)點 b 往后的所有結(jié)點都無法訪問到了。
對于有些語言來說,比如 C 語言,內(nèi)存管理是由程序員負(fù)責(zé)的,如果沒有手動釋放結(jié)點對應(yīng)的內(nèi)存空間,就會產(chǎn)生內(nèi)存泄露。所以,我們插入結(jié)點時,一定要注意操作的順序,要先將結(jié)點 x 的 next 指針指向結(jié)點 b,再把結(jié)點 a 的 next 指針指向結(jié)點 x,這樣才不會丟失指針,導(dǎo)致內(nèi)存泄漏。所以,對于剛剛的插入代碼,我們只需要把第 1 行和第 2 行代碼的順序顛倒一下就可以了。同理,刪除鏈表結(jié)點時,也一定要記得手動釋放內(nèi)存空間,否則,也會出現(xiàn)內(nèi)存泄漏的問題。當(dāng)然,對于像 Java 這種虛擬機(jī)自動管理內(nèi)存的編程語言來說,就不需要考慮這么多了。
三、單鏈表反轉(zhuǎn)的C語言實現(xiàn)
使用p指向第一個結(jié)點,cur指向當(dāng)前結(jié)點,每次把cur->next結(jié)點摘掉放在p節(jié)點前面。然后更新p結(jié)點指向頭結(jié)點。具體實現(xiàn)代碼如下所示
void revers_list(list1 **l) { if(!(*l)||!l) { exit(-1); } list1 *start=*l; list1 *start_next=NULL; while (start->next) { // 獲取當(dāng)前節(jié)點的后繼節(jié)點 start_next = start->next; // 將后繼節(jié)點摘鏈 72 start->next = start_next->next; // 將后繼節(jié)點提到最前面 start_next->next = *l; // 更新頭節(jié)點 *l = start_next; } }
到此這篇關(guān)于C語言實現(xiàn)單鏈表反轉(zhuǎn)的文章就介紹到這了,更多相關(guān)C語言 單鏈表反轉(zhuǎn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于Qt開發(fā)獲取CTP量化交易接口測試數(shù)據(jù)工具
這篇文章主要為大家詳細(xì)介紹了如何使用Qt軟件開發(fā)K線股P相關(guān)軟件,先開發(fā)一個通過CTP量化交易的sdk獲取相關(guān)推送數(shù)據(jù)的工具,需要的可以參考下2024-04-04C語言中進(jìn)行大小寫字母轉(zhuǎn)化的示例代碼
C語言標(biāo)準(zhǔn)庫中提供了用于大小寫轉(zhuǎn)換的函數(shù),使得這一操作變得簡單而高效,本文將詳細(xì)介紹如何在C語言中進(jìn)行大小寫字母的轉(zhuǎn)換,包括相關(guān)的函數(shù)和示例代碼,需要的朋友可以參考下2024-03-03關(guān)于C語言strlen與sizeof區(qū)別詳情
對于 strlen 和 sizeof,相信不少程序員會混淆其功能。雖然從表面上看它們都可以求字符串的長度,但二者卻存在著許多不同之處及本質(zhì)區(qū)別,今天得這篇文章我們就來學(xué)習(xí)C語言strlen與sizeof區(qū)別的相關(guān)資料,需要的朋友可以參考一下2021-10-10C++中new與delete、malloc與free應(yīng)用分析
這篇文章主要介紹了C++中new與delete、malloc與free應(yīng)用分析,很重要的概念,需要的朋友可以參考下2014-08-08C++ 數(shù)據(jù)結(jié)構(gòu)完全二叉樹的判斷
這篇文章主要介紹了C++ 數(shù)據(jù)結(jié)構(gòu)完全二叉樹的判斷的相關(guān)資料,需要的朋友可以參考下2017-06-06