【劍指Offer】鏈表——複雜鏈表的克隆

package cn.dzp.flyroc.offer;


    //定義複雜鏈表
    class ComplexList{

        int val;
        ComplexList next = null;
        ComplexList random = null;

        ComplexList(int val){

            this.val = val;
        }
    }


public class RandomListNodeDemo {


    /*題目描述:輸入一個複雜鏈表()每一個節點中有節點值,以及兩個指針,
    * 一個指向下一個節點,另外一個特殊指針指向任意一個節點),
    * 返回結果爲複製後複雜鏈表的head。(注意:輸出結果中請不要返回參數中節點引用,
    * 不然判斷程序會直接返回空)*/

    /*思路:對每個節點都進行克隆,克隆後的節點的特殊指針指向原節點特殊指針的下一個節點,
    * 將一個長鏈表經過奇偶次序分爲原鏈表和克隆鏈表*/


    /*實現步驟:
    * 1、根據原始鏈表的每一個節點克隆出對應的克隆節點
    * 2、設置克隆出來節點的random,假設原始結點的隨機指向S,複製出來結點的random指向S後一個
    * 3、經過奇偶次序把長鏈表分爲兩個鏈表,奇數位置對應的節點鏈接起來就是原始鏈表,偶數位置鏈接起來的鏈表就是克隆鏈表*/


    //代碼實現

    //根據原始鏈表的每一個節點建立對應的克隆節點
    private void cloneNode(ComplexList head){

        ComplexList node = head;

        while (node != null){

            ComplexList cloneNode = new ComplexList(node.val);      //把原始鏈表中頭節點的值克隆
            cloneNode.next = node.next;         //把原始鏈表中的指針克隆
            cloneNode.random = null;        //特殊指針暫定

            node.next = cloneNode;      //克隆後頭結點的next爲克隆的第一個元素
            node = cloneNode.next;      //將指針跳轉到第三個元素(即爲克隆元素的後一個),繼續進行下一個節點克隆
        }
    }


    //設置克隆出來節點的random,爲原始鏈表random的後一個元素
    private void connectRandomNodes(ComplexList head) {

        ComplexList node = head;

        while (node != null){

            ComplexList clone = node.next;

            if (node.random != null){       //random設置爲原來random的後一個元素

                clone.random = node.random.next;
            }
            node = clone.next;      //繼續設置下一個節點
        }
    }


    //將長鏈表經過奇偶次序分爲兩個鏈表
    private ComplexList reRandomNode(ComplexList head){

        ComplexList node = head;
        ComplexList cloneHead = null;       //克隆鏈表
        ComplexList cloneNode = null;


        //設置第一個節點
        if (node != null){

            cloneHead = node.next;      //找到克隆鏈表的頭節點
            cloneNode = node.next;      //克隆鏈表的node,也就是克隆鏈表的頭節點

            node.next = cloneNode.next;         //node的下一個節點跳轉到第三個節點(奇數節點)
            node = node.next;       //設置爲本次奇數開始的節點
        }

        while (node != null){       //node是從第三個節點開始的

            cloneNode.next = node.next;     //clone的下一個節點跳轉到第四個節點(偶數節點)
            cloneNode = cloneNode.next;     //設置本次偶數開始的節點

            node.next = cloneNode.next;     //node的下一個節點跳轉到第五個節點(奇數節點)
            node = node.next;       //設置本次奇數開始的節點
        }
        return cloneHead;
    }


    //引用方法
    public ComplexList Clone(ComplexList head){

        cloneNode(head);
        connectRandomNodes(head);
        return reRandomNode(head);

    }


    //測試方法
    public static void main(String[] args){

        ComplexList head = new ComplexList(10);
        ComplexList node2 = new ComplexList(11);
        ComplexList node3 = new ComplexList(12);
        ComplexList node4 = new ComplexList(13);
        ComplexList node5 = new ComplexList(14);
        ComplexList node6 = new ComplexList(15);
        ComplexList node7 = new ComplexList(16);
        ComplexList node8 = new ComplexList(17);

        head.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        node5.next = node6;
        node6.next = node7;
        node7.next = node8;

        head.random = node3;
        node2.random = node5;
        node4.random = node2;


        RandomListNodeDemo randomList = new RandomListNodeDemo();
        ComplexList copyList = randomList.Clone(head);

        while (copyList != null){

            System.out.print(copyList.val + ",");
            copyList = copyList.next;

        }
    }
}
相關文章
相關標籤/搜索