复杂链表的复制

Posted guoyuying

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了复杂链表的复制相关的知识,希望对你有一定的参考价值。

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

结点结构体如下:

/*
struct RandomListNode 
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) 
    
;
*/

这是一道剑指offer上的题目。下面看一下解析吧。

在做这道题之前,自己的想法是先把链表中的next域全部复制,这时候原复杂链表的random域的所有指向都会存在于刚才复制的链表中,之后再遍历原复杂链表,将新链表random域与原链表random域相互对应即可。

但是过程中问题就出现了,虽然我可以在将原链表的所有next域全部复制,也保证了即将要复制的random域的指向存在于该链表中,但是random域是随机指的,也就是说并不知道当前的random域指向的结点在前面还是后面,如此一来,如果还要继续下去,恐怕还要嵌套一层循环。

为此,又在网上找了大神的博客参考下,真的是受益匪浅。

想想我们平时复制粘贴一段文字的时候是怎么做的?是照着那段文字一个一个的再敲一次吗?并不是,很显然,我们是直接在该段文字上复制,然后将复制后的文字粘贴到我们想要的地方。

上面的笨办法显然就是一个一个的再敲一个链表出来,并没有做真正的复制

那怎么做?对,就是直接在原链表上复制一份链表,最后将我们想要的备份链表从原链表中抽离出来。

具体分三个步骤:

1.再原链表的每个结点后面插入一个与当前结点数据域相同的结点

2.复制random域的对应关系

3.抽离链表

完整代码如下

    RandomListNode* Clone(RandomListNode* pHead)
    
        if(!pHead)
            return NULL;
        
        RandomListNode *head = NULL;
        RandomListNode *p, *pf = NULL;
        RandomListNode *q;
// 先复制结点
        for(p = pHead; p; p = p->next->next)
            q = new RandomListNode(p->label);
            q->next = p->next;
            p->next = q;
        
// 复制random域对应关系
        for(p = pHead; p; p = p->next->next)
            if(!p->random)
                p->next->random = p->random;
            else
                p->next->random = p->random->next;
            
        
//抽离链表
        head = pHead->next;
        for(p = pHead, q = head; q; q = q->next)
            p->next = p->next->next;
            if(q->next)
               p = p->next;
               q->next = q->next->next; 
            
        
        return head;
    

下面附一下参考链接,上面有图,更容易理解。

https://blog.csdn.net/H_Strong/article/details/83042934

end。

以上是关于复杂链表的复制的主要内容,如果未能解决你的问题,请参考以下文章

C语言之复杂链表的复制(图示详解)

复杂链表的复制

复杂链表的复制

35. 复杂链表的复制

数据结构复杂链表的复制

剑指OFFER 复杂链表的复制