鍊錶翻轉 面試經驗

2021-08-28 05:23:32 字數 2155 閱讀 6254

鍊錶的翻轉是程式設計師面試中出現頻度最高的問題之一,常見的解決方法分為遞迴和迭代兩種。

我們知道迭代是從前往後依次處理,直到迴圈到鏈尾;而遞迴恰恰相反,首先一直迭代到鏈尾也就是遞迴基判斷的準則,然後再逐層返回處理到開頭。

總結來說,鍊錶翻轉操作的順序對於迭代來說是從鏈頭往鏈尾,而對於遞迴是從鏈尾往鏈頭。下面我會用詳細的**來剖析其中實現的細節。 

1、非遞迴(迭代)方式 

迭代的方式是從鏈頭開始處理,如下圖給定乙個存放5個數的鍊錶。

首先對於鍊錶設定兩個指標:

然後依次將舊鍊錶上每一項新增在新鍊錶的後面,然後新鍊錶的頭指標newh移向新的煉表頭,如下圖所示。此處需要注意,不可以上來立即將上圖中p->next直接指向newh,這樣存放2的位址就會被丟棄,後續鍊錶儲存的資料也隨之無法訪問。而是應該設定乙個臨時指標tmp,先暫時指向p->next指向的位址空間,儲存原鍊錶後續資料。然後再讓p->next指向newh,最後p=tmp就可以取回原鍊錶的資料了,所有迴圈訪問也可以繼續展開下去。

指標繼續向後移動,直到p指標指向null停止迭代。

最後一步:

2、非遞迴實現的程式

node* reverselist(node* h)

return newh;

}

3、遞迴方式 

我們再來看看遞迴實現鍊錶翻轉的實現,前面非遞迴方式是從前面數1開始往後依次處理,而遞迴方式則恰恰相反,它先迴圈找到最後面指向的數5,然後從5開始處理依次翻轉整個鍊錶。 

首先指標h迭代到底如下圖所示,並且設定乙個新的指標作為翻轉後的鍊錶的頭。由於整個鍊錶翻轉之後的頭就是最後乙個數,所以整個過程newh指標一直指向存放5的位址空間。

然後h指標逐層返回的時候依次做下圖的處理,將h指向的位址賦值給h->next->next指標,並且一定要記得讓h->next =null,也就是斷開現在指標的鏈結,否則新的鍊錶形成了環,下一層h->next->next賦值的時候會覆蓋後續的值。

繼續返回操作:

上圖第一次如果沒有將存放4空間的next指標賦值指向null,第二次h->next->next=h,就會將存放5的位址空間覆蓋為3,這樣鍊錶一切都大亂了。接著逐層返回下去,直到對存放1的位址空間處理。

返回到頭:

4、迭代實現的程式

node* in_reverselist(node* h)

5、整體實現的程式:

#includeusing namespace std;

struct node

};/***非遞迴方式***/

node* reverselist(node* h)

return newh;

}/***遞迴方式***/

node* in_reverselist(node* h)

int main()

面試題 鍊錶的 部分 翻轉

2016年08月09日 21 43 37 問題 給出乙個單鏈表 不帶頭節點 和乙個數k,請翻轉此單鏈表?例如 1 2 3 4 5 k 0 翻轉過後 1 2 3 4 5 1 2 3 4 5 k 2 翻轉過後 2 1 4 3 5 1 2 3 4 5 k 10 翻轉過後 5 4 3 2 1 在討論鍊錶的 ...

鍊錶的翻轉

如何快速的實現鍊錶的翻轉,比如鍊錶a資料為 str1,str2,str3,str4,str5,str6 翻轉後則變為 str6,str5,str4,str3,str2,str1 針對上述問題我能想到的一種辦法就是以壓棧的方式來實現,其實現思路相對較為簡單,通過定義乙個鍊錶資料結構的資料棧,遍歷鍊錶,...

分析鍊錶翻轉

鍊錶翻轉分兩部分,鍊錶整表翻轉和鍊錶部分翻轉。下面討論非遞迴的做法,遞迴的做法以後有空再說。先說鍊錶整表翻轉,核心四句話 next p.next p.next pre pre p p next 顧名思義,pre是p前面的節點,next是p後面的節點。舉個例子,下圖是乙個鍊錶節點翻轉前的狀態 上面的 ...