【剑指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;

        }
    }
}
相关文章
相关标签/搜索