1. 程式人生 > >看一遍就理解,圖解單鏈表反轉

看一遍就理解,圖解單鏈表反轉

前言

反轉連結串列是程式設計師必備的基本素養,經常在面試、筆試的過程中出現。一直覺得反轉連結串列實現程式碼不是很好理解,決定搬leetcode那道經典反轉連結串列題出來,用十多張圖去解析它,希望加深大家對連結串列反轉的理解,謝謝閱讀。

leetcode的反轉連結串列原題&答案

題目描述: 反轉一個單鏈表。

輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL

分析:

假設存在連結串列 1 → 2 → 3 → Ø,我們想要把它改成 Ø ← 1 ← 2 ← 3。

在遍歷列表時,將當前節點的 next 指標改為指向前一個元素。由於節點沒有引用其上一個節點,因此必須事先儲存其前一個元素。在更改引用之前,還需要另一個指標來儲存下一個節點。不要忘記在最後返回新的頭引用!

程式碼實現:

public ListNode reverseList(ListNode head) {  
    ListNode prev = null;   
    ListNode curr = head;   
    while (curr != null) {  
        ListNode nextTemp = curr.next;
        curr.next = prev;
        prev = curr;
        curr = nextTemp;
    }
    return prev;
}

圖解連結串列反轉程式碼的實現

接下來,我們圖解以上程式碼實現,先對以上實現程式碼加上行號,如下:

public ListNode reverseList(ListNode head) {  //1
    ListNode prev = null;   // 2
    ListNode curr = head;   // 3
    while (curr != null) {   //4
        ListNode nextTemp = curr.next; //5
        curr.next = prev;  // 6 
        prev = curr;  //7
        curr = nextTemp; //8
    } 
    return prev;  //9
}

第一行程式碼圖解

public ListNode reverseList(ListNode head) {  //1

我們順著題目描述意思,假設連結串列就有1、2、3個元素吧,後面還跟著一個null,又因為輸入是ListNode head,所以這個即將要反轉的連結串列如下:

第二行程式碼圖解

ListNode prev = null;   // 2

將null賦值給prev,即prev指向null,可得圖如下:

第三行程式碼圖解

ListNode curr = head;

將連結串列head賦值給curr,即curr指向head連結串列,可得圖如下:

迴圈部分程式碼圖解

 while (curr != null) {   //4
        ListNode nextTemp = curr.next; //5
        curr.next = prev;  // 6 
        prev = curr;  //7
        curr = nextTemp; //8
    }

迴圈部分是連結串列反轉的核心部分,我們先走一遍迴圈,圖解分析一波。

因為curr指向了head,head不為null,所以進入迴圈。先來看第5行:

ListNode nextTemp = curr.next; //5

把curr.next 賦值給nextTemp變數,即nextTemp 指向curr的下一節點(即節點2),可得圖如下:

再執行到第6行:

curr.next = prev;  // 6 

把prev賦值給curr.next,因為prev初始化化指向null,即curr(節點1)指向了null,連結串列圖解成這樣了:

然後我們看執行到第7行

 prev = curr;  //7

把curr賦值給prev,prev指向curr,圖解如下:

接著,我們執行到第8行:

curr = nextTemp; //8

把nextTemp賦值給curr,即curr指向nextTemp,圖解如下:

至此,第一遍迴圈執行結束啦,回到迴圈條件,curr依舊不為null,我們繼續圖解完它。

5-8行程式碼又執行一遍,依次可得圖:

        ListNode nextTemp = curr.next; //5
        curr.next = prev;  // 6 
        prev = curr;  //7
        curr = nextTemp; //8

執行完ListNode nextTemp = curr.next;後:

執行完curr.next = prev;後:

執行完prev = curr;後:

執行完curr = nextTemp;後:

來到這裡,發現curr還是不為null,再回到while迴圈,再執行一遍:

        ListNode nextTemp = curr.next; //5
        curr.next = prev;  // 6 
        prev = curr;  //7
        curr = nextTemp; //8

依次可得圖:

來到這裡,我們發現curr已經為null了,可以跳出迴圈了。這時候prev指向的就是連結串列的反轉呀,所以第9行執行完,反轉連結串列功能實現:

 return prev;  //9

參考與感謝

  • LeetCode 官網

個人公眾號

  • 如果你是個愛學習的好孩子,可以關注我公眾號,一起學習討論。
  • 如果你覺得本文有哪些不正確的地方,可以評論,也可以關注我公眾號,私聊我,大家一起學習進步哈。