1. 程式人生 > >[劍指offer學習心得]之:從尾到頭列印連結串列

[劍指offer學習心得]之:從尾到頭列印連結串列

題目:輸入個連結串列的頭結點,從尾到頭反過來打印出每個結點的值。

測試用例

  1. 功能測試(輸入的連結串列有多個結點,輸入的連結串列只有一個結點)
  2. 特殊輸入測試(輸入的連結串列頭結點為 null)

思路

我們知道連結串列是從頭到尾輸出的,既然要解決這個問題可能很自然地會想到把連結串列中指標都反過來,改變指向的方向就好了嘛,不過這個會導致連結串列的結構的改變,你確定面試官會讓你這麼做嘛?

一般來說列印也就是一個只讀操作,連結串列結構的改變通常是不允許的。所以要想其他的方法。

方法一:棧

第一個想到的就是棧。因為這個題目的意思,就是第一個遍歷的結點是最後一個輸出,而最後一個遍歷的結點是第一個輸出,這不就是先進後出的道理嘛。我們可以每經過一個結點,就把這個結點放到一個棧中,遍歷完整個連結串列後,再從棧頂開始逐個輸出結點的值,此時輸出的結點順序已經反轉過來了。

方法二:遞迴

我們都知道遞迴本質上是一個棧結構,前面又用到了棧來實現這個函式。於是當然很自然地想到用遞迴的思想來實現。要實現反過來輸出連結串列,我們每訪問到一個結點時,先遞迴輸出它後面的結點,再輸出結點本身,醬紫的話輸出結果就可以反過來了。

不過這裡有一點需要注意的:當連結串列非常長,就會導致函式呼叫的層級很深,就可能導致函式呼叫棧溢位,顯式用棧基於迴圈實現的程式碼魯棒性要好一些。

程式碼實現

import java.util.Stack;

public class PrintReversingly {

    public static void main(String[] args){
        ListNode root=new
ListNode(); root.value=1; root.next=new ListNode(); root.next.value=2; root.next.next=new ListNode(); root.next.next.value=3; root.next.next.next=new ListNode(); root.next.next.next.value=4; root.next.next.next.next=new ListNode(); root.next.next.next.next.value=5
; printReversingly_Iteratively(root); System.out.println(); printReversingly_Recursively(root); } private static class ListNode{ int value; ListNode next; } /** * 棧實現 * @param root 連結串列的頭結點 */ private static void printReversingly_Iteratively(ListNode root){ Stack<ListNode> stack=new Stack<ListNode>(); while(root!=null){//遍歷連結串列,push進棧中 stack.push(root); root=root.next; } ListNode temp; while(!stack.isEmpty()){ temp=stack.pop(); System.out.print(temp.value+" "); } } /** * 遞迴實現 * @param root 連結串列的頭結點 */ private static void printReversingly_Recursively(ListNode root){ if(root!=null){ printReversingly_Recursively(root.next); System.out.print(root.value+" "); } } }