1. 程式人生 > >java用遞迴和非遞迴實現連結串列逆序

java用遞迴和非遞迴實現連結串列逆序

傳統的逆序連結串列方法是使用三個指標來記錄節點的狀態,防止連結串列斷裂。


Node節點

public class Node {
    private int data;
    private Node next;

    public Node(int data){
        this.data = data;
        next = null;
    }

    public int getData() {
        return this.data;
    }

    public void setData(int data) {
        this.data = data;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }
}

逆序方法

public static Node reverseLinkList(Node head){
        Node p1=head,p2 = head.getNext();
        Node p3=null;
        while (p2!=null){
            p3 = p2.getNext();
            p2.setNext(p1);
            p1 = p2;
            p2 = p3;
        }
        return p1;
    }

主方法裡面逆序

Node newHead = reverseLinkList(head);
        head.setNext(null);
        p = newHead;
        while (p != null) {
            System.out.print(p.getData() + " ");
            p = p.getNext();
        }

我在想遞迴是先處理好後面的問題,然後把結果返回。如果我從最後開始逆序整個連結串列,我獲得當前節點的後一個節點的時候,當前節點的後面已經完成逆序。只要將後一個節點指向當前節點。


這裡使用了靜態變數newHead是因為要記錄舊的尾節點來作為新的頭節點。不然整個函式獲得的只是舊的頭結點(新的尾節點)。如果將newHead作為形參傳入方法,而不設定成靜態變數,是不行的。因為java裡面物件的引用形參相當於拷貝了一份實參。直接改變形參指向一個新的物件是不會改變實參的。而改變形參引用的內容卻可以改變實參所引用物件的內容,如下面的setNext方法。

private static Node newHead;

    public static Node getNextNode(Node node) {
        if (node.getNext() != null) {
            //獲得後一個節點,此時該節點後面節點已經全部逆序完
            Node nextNode = getNextNode(node.getNext());
            nextNode.setNext(node);
            return node;
        }
        //最後一個節點
        else {
            newHead = node;
            return node;
        }
    }

主方法裡面呼叫,可以發現遞迴來實現逆序也是可以的

 Node tail = getNextNode(head);
        //尾節點(原頭節點)指向null
        tail.setNext(null);
        p = newHead;
        while (p != null) {
            System.out.print(p.getData() + " ");
            p = p.getNext();
        }