反轉乙個單鏈表。
示例:
輸入:1->2->3->4->5->null
輸出:5->4->3->2->1->null
1鍊錶的翻轉是程式設計師面試**現頻度最高的問題之一,常見的解決方法分為遞迴和迭代兩種。最近在複習的時候,發現網上的資料都只告訴了怎麼做,但是根本沒有好好介紹兩種方法的實現過程與原理。所以我覺得有必要好好的整理一篇博文,來幫忙大家一步步理解其中的實現細節。class
solution
6 listnode h =reverselist(head.next);
7 head.next.next =head;
8 head.next = null;9
return
h;10
}11 }
我們知道迭代是從前往後依次處理,直到迴圈到鏈尾;而遞迴恰恰相反,首先一直迭代到鏈尾也就是遞迴基判斷的準則,然後再逐層返回處理到開頭。總結來說,鍊錶翻轉操作的順序對於迭代來說是從鏈頭往鏈尾,而對於遞迴是從鏈尾往鏈頭。下面我會用詳細的**來剖析其中實現的細節。
1、非遞迴(迭代)方式
迭代的方式是從鏈頭開始處理,如下圖給定乙個存放5個數的鍊錶。
首先對於鍊錶設定兩個指標:
然後依次將舊鍊錶上每一項新增在新鍊錶的後面,然後新鍊錶的頭指標newh移向新的煉表頭,如下圖所示。此處需要注意,不可以上來立即將上圖中p->next直接指向newh,這樣存放2的位址就會被丟棄,後續鍊錶儲存的資料也隨之無法訪問。而是應該設定乙個臨時指標tmp,先暫時指向p->next指向的位址空間,儲存原鍊錶後續資料。然後再讓p->next指向newh,最後p=tmp就可以取回原鍊錶的資料了,所有迴圈訪問也可以繼續展開下去。
指標繼續向後移動,直到p指標指向null停止迭代。
最後一步:
2、非遞迴實現的程式
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、迭代實現的程式
leetcode 206 鍊錶反轉
一 題目大意 反轉乙個單鏈表,實現遞迴和非遞迴兩種形式 二 鍊錶節點 public class listnode 三,分析 1,非遞迴解決方案 最容易想到的是使用三個指標,p1,p2,p3,遍歷鍊錶事項反轉。這裡需要注意的是,p1,p2,p3的初始化,不同初始化應該考慮煉表頭的不同處理。一般的初始是...
LeetCode 206 反轉鍊錶
反轉乙個單鏈表。高階 鍊錶可以迭代或遞迴地反轉。你能否兩個都實現一遍?設定三個指標分別指向連續的三個節點,每次完成節點的反向就把三個節點同時後移,直到所有節點反轉。definition for singly linked list.struct listnode class solution ret...
LeetCode 206 反轉鍊錶
206.反轉鍊錶 反轉乙個單鏈表。輸入 1 2 3 4 5 null 輸出 5 4 3 2 1 null非遞迴解法 1.class solution object defreverselist self,head type head listnode rtype listnode res none ...