最近研究演算法,遇到的一道很有意思的問題——怎麼把乙個鍊錶反轉?
很容易想到乙個方法:遍歷鍊錶,陣列作棧儲存路徑,元素逐個出棧得到的就是反轉後的鍊錶!查詢資料發現,有更好的方式實現。
仔細研究後,終於明白了其中的奧妙。小僧掌握了兩種方法,以下分別進行說明。
首先給出鍊錶結構:
public class linkednode
}
linkednode node1 = new linkednode(1);
linkednode node2 = new linkednode(2);
linkednode node3 = new linkednode(3);
linkednode node4 = new linkednode(4);
node1.next = node2;
node2.next = node3;
node3.next = node4;
先給出**實現:
/**
* 鍊錶翻轉,迴圈 + 雙指標(pre、next)實現
* @param cur
* @return
*/public linkednode reverse(linkednode cur)
return pre;
}
迴圈體之前,煉表示意圖:
之後進入while
迴圈,注釋標註的四個步驟會產生如下變化(圖中編號與注釋編號一一對應):
第一次迴圈後,鍊錶變成這樣:
之後的遍歷,鍊錶的變化示意:
可見,while
迴圈執行完,pre
指向的節點,已經是最新的頭節點了!
遞迴的實現方式,似乎更容易理解。
/**
* 鍊錶反轉,遞迴實現
* @param node
* @return
*/public linkednode reverse2(linkednode node)
linkednode newhead = reverse2(node.next);
node.next.next = node; 換成 newhead.next 不行,因為node在遞迴中在追溯上乙個節點,仔細體會下
node.next = null;
return newhead;
}
首先會通過遞迴呼叫找到尾節點,之後做了兩件事:
尾節點反指 (node.next.next = node;
)
當前節點指向null節點 (node.next = null;
)
rentun newhead
後,回溯到節點2(此時node就是節點2),再次重複之前的兩件事——節點反指和當前節點指向null節點。
再次回溯,得到最終的結果。
老規矩,完整**見git:暗夜君王的demo練習——鍊錶反轉
done !
鍊錶 反轉鍊錶
問題 兩兩交換鍊錶中的節點 問題 k 個一組翻轉鍊錶 問題鏈結 利用棧先進後出的特性,遍歷鍊錶,將每個結點加入棧中,最後進行出棧操作,先出棧的結點指向臨近的後出棧的結點。definition for singly linked list.struct listnode class solution ...
反轉鍊錶與分組反轉鍊錶
經典的反轉鍊錶,先上 public class listnode public class printlist system.out.println public class reverse public listnode reverse listnode root listnode pre nul...
鍊錶 鍊錶反轉I
package com.hnust.reversal public class listnode public listnode int value,listnode next override public string tostring 我們可以通過把鍊錶中鏈結節點的指標反轉過來,從而改變鍊錶的...