1. 程式人生 > >翻轉連結串列(遞迴)

翻轉連結串列(遞迴)

1. 給出一個連結串列,翻轉連結串列,返回翻轉後連結串列的頭結點

2. 因為涉及到翻轉連結串列所以應該從連結串列的末尾開始改變指標的指向,而遞迴這種方法就很好地詮釋了這一點,因為遞迴碰到遞迴出口之後那麼是層層返回的,而且它是從末尾開始返回的,對於這道題目來說是從連結串列的末尾的節點開始返回的,所以這個時候使用遞迴來求解就非常合適了,在碰到遞迴出口之後進行層層返回修改每一個節點的next指標的指向即可翻轉整個連結串列,最後返回的應該是連結串列中的最後一個節點

遞迴出口應該是當前的節點的next為空的時候那麼我們就返回這個節點,每一層都是返回的是這個節點所以最後我們得到的遞迴函式的返回值為這個節點

當碰到遞迴出口返回的時候: reverseLinkedList(head.next);的head為倒數第二個元素,所以我們應該將下一個元素的next指向前一個元素,也就是指向倒數第二個元素,每一次都是將下一個元素的next指向前一個元素,並且把前一個元素的next賦值為空才不會形成有環連結串列,因為即使前一個元素的next會在上一層的時候會被修改掉,但是在最後一層的的時候為第一個元素這個時候原來的next是指向下一個元素,next沒有上一個元素可以指向了,所以不會被修改了,這個時候不賦值為空那麼就會形成有環連結串列導致在輸出的時候出現死迴圈,在eclipse輸出的時看不到結果而且會出現閃退的情況

head.next = null;

等到全部遞迴返回之後那麼得到的就是一張翻轉的連結串列,而返回的指標就是翻轉後連結串列的頭指標(原來連結串列的尾節點)

         

 

3. 具體的程式碼如下:

public class Main{
    private static class ListNode{
        private ListNode next;
        private Object value;
        public ListNode(Object value) {
            super();
            this.value = value;
        }
    }
    public static void main(String[] args){
        int arr[] = {1, 6, 6, 7, 3, 3, 5, 3, 8, 9, 10, 10};
        ListNode head = new ListNode(arr[0]);
        ListNode p = head;
        for(int i = 1; i < arr.length; i++){
            p.next = new ListNode(arr[i]);
            p = p.next;
        }
        p = head;
        while(p != null){
            System.out.print(p.value+ " ");
            p = p.next;
        }
        System.out.print("\n");
        p = reverseLinkedList(head);
        while(p != null){
            System.out.print(p.value+ " ");
            p = p.next;
        }
    }
    
    public static ListNode reverseLinkedList(ListNode head){
        //通過層層改變節點的指向來進行翻轉連結串列
        if(head.next == null){
            return head;
        }
        ListNode prev = reverseLinkedList(head.next);
        //當前的head是上一個元素
        //下一個元素的next指向前一個元素
        head.next.next = head;
        head.next = null;
        //返回的是連結串列的尾節點
        return prev;
    }
}