面试题之--复杂链表的复制

26 篇文章 0 订阅

复杂链表的复制:
复杂链表除了有一个next指针还有一个random指针
我们可以画一个图来表示
这里写图片描述
复杂链表的声明:

struct  ComplexNode
{
    ComplexNode(const int&data)
    :_next(NULL)
    , _random(NULL)
    , _data(data)
    {}
    ComplexNode* _next;
    ComplexNode* _random;//随机指针
    int _data;//数据域
};

如果直接拷贝,random指针无法确定,可能会造成“野指针”的问题;
因此我们可以先拷贝 节点,然后再拷贝random指针,最后解链;
1:第一步:拷贝节点,并与原节点连起来:通过next指针将原节点和新节点链接起来

//将新节点插入到以前节点的后面
    ComplexNode*cur = _head;
    while (cur)
    {
        ComplexNode*tmp = new ComplexNode(cur->_data);
        ComplexNode*next = cur->_next;//用于保存头结点的下一个节点

        cur->_next = tmp;
        tmp->_next = next;
        cur = next;
    }

这里写图片描述
2:第二步:置random指针

//链上radom指针
    cur = _head;
    while (cur)
    {
        ComplexNode*next = cur->_next;
        if (cur->_random == NULL)
        {
            next->_random = NULL;
        }
        else
        {
            next->_random = cur->_random->_next;//拷贝随机指针
        }
        cur = next->_next;//下一个要复制的节点
    }

这里写图片描述
3:第三步解链,将原链表与新链表分离
//第三步拆链

    ComplexNode*newhead = NULL;//新节点的头
    ComplexNode*tail = NULL;//指向复制的节点
    ComplexNode*pphead = _head;//指向原来的头
    if (pphead != NULL)
    {
        newhead = pphead->_next;
        tail = newhead;//保存新节点的头
        pphead->_next = tail->_next;//将新节点分离开来
        pphead = tail->_next;
    }
    while (pphead)
    {
        tail->_next = pphead->_next;//把复制的链接到新链表
        tail = tail->_next;//分离新节点
        pphead = tail->_next;
    }
    return newhead;

这里写图片描述
4;完整代码:

#include<iostream>
using namespace std;
struct  ComplexNode
{
    ComplexNode(const int&data)
    :_next(NULL)
    , _random(NULL)
    , _data(data)
    {}
    ComplexNode* _next;
    ComplexNode* _random;//随机指针
    int _data;//数据域
};
ComplexNode* Copylist(ComplexNode*_head)
{
    //将新节点插入到以前节点的后面
    ComplexNode*cur = _head;
    while (cur)
    {
        ComplexNode*tmp = new ComplexNode(cur->_data);
        ComplexNode*next = cur->_next;//用于保存头结点的下一个节点

        cur->_next = tmp;
        tmp->_next = next;
        cur = next;
    }
    //链上radom指针
    cur = _head;
    while (cur)
    {
        ComplexNode*next = cur->_next;
        if (cur->_random == NULL)
        {
            next->_random = NULL;
        }
        else
        {
            next->_random = cur->_random->_next;//拷贝随机指针
        }
        cur = next->_next;//下一个要复制的节点
    }
    //第三步拆链
    ComplexNode*newhead = NULL;//新节点的头
    ComplexNode*tail = NULL;//指向复制的节点
    ComplexNode*pphead = _head;//指向原来的头
    if (pphead != NULL)
    {
        newhead = pphead->_next;
        tail = newhead;//保存新节点的头
        pphead->_next = tail->_next;//将新节点分离开来
        pphead = tail->_next;
    }
    while (pphead)
    {
        tail->_next = pphead->_next;//把复制的链接到新链表
        tail = tail->_next;//分离新节点
        pphead = tail->_next;
    }
    return newhead;
}
ComplexNode* Creatlist()//创建复杂链表
{
    ComplexNode*node1 = new ComplexNode(1);//创建节点
    ComplexNode*node2 = new ComplexNode(2);
    ComplexNode*node3 = new ComplexNode(3);
    ComplexNode*node4 = new ComplexNode(4);


    node1->_next = node2;//节点连起来
    node2->_next = node3;
    node3->_next = node4;
    node4->_next = NULL;

    node1->_random = node2;//置random
    node2->_random = node4;
    node4->_random = node3;
    node3->_random = node3;
    return node1;
}
void Printlist(ComplexNode* head)
{
    ComplexNode*cur = head;
    while (cur)
    {
        cout << "(" << cur->_data << "," << cur->_random->_data<< ")" << "->";
        cur = cur->_next;
    }
    cout << endl;
}
int main()
{
    cout << "Printlist(Head)" << endl;
    ComplexNode*Head = Creatlist();
    Printlist(Head);
    cout << "Printlist(newHead)" << endl;
    ComplexNode*newHead = Copylist(Head);
    Printlist(newHead);
    system("pause");
    return 0;
}

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值