前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >【数据结构与算法 经典例题】随机链表的复制(图文详解)

【数据结构与算法 经典例题】随机链表的复制(图文详解)

作者头像
用户11396077
发布2024-12-06 19:00:36
发布2024-12-06 19:00:36
11300
代码可运行
举报
文章被收录于专栏:C/C++指南
运行总次数:0
代码可运行

一、问题描述

习题摘自 138. 随机链表的复制 - 力扣(LeetCode)

二、解题思路

要完成一个带随机指针的链表的复制,有一个巧妙的办法: 分三步走

  1. 完成节点数据拷贝——在原链表的每个节点后面增加一个拷贝节点,拷贝节点的值等于原节点的值
  2. 完成节点的随机指针拷贝——原节点的随机指针指向哪里,拷贝节点就指向对应节点的下一个节点(这一部分是这条思路能实现的关键)
  3. 完成节点的next指针拷贝——将拷贝节点从原链表中取下,按顺序改变next指针指向,组成新的链表,并恢复原链表的next指针

三、代码实现

代码的实现逻辑: 需要用到三个循环

假设初始链表如下

1. 原链表中节点的数据拷贝

第一个循环:

  • 创建pcur指针指向链表第一个节点,遍历链表
  • 在每个节点后面创建一个相同结构的拷贝节点,拷贝原节点数据
  • 修改链表next指针指向如下:
  • 原链表节点->该节点拷贝节点->原链表下一个节点->该节点拷贝节点……原链表最后一个节点->该节点拷贝节点->NULL

经过第一轮循环后,原链表每个节点之后被插入了一个新节点

这一部分的实现代码如下

代码语言:javascript
代码运行次数:0
复制
/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */
typedef struct Node Node;
struct Node* copyRandomList(struct Node* head) 
{
    Node* pcur=head;
    while(pcur)
    {
        Node*copy=(Node*)malloc(sizeof(Node));//创建拷贝节点
        copy->val=pcur->val;//拷贝数据

        copy->next=pcur->next;//插入到pcur后面
        pcur->next=copy;

        pcur=copy->next;//移动pcur指针
    }
}
2.原链表中节点的随机指针拷贝

注意:

随机指针不是单纯的拷贝,而是将拷贝节点的随机指针指向与原链表中关系对应的拷贝节点

第二个循环:

  • pcur指针重新指向第一个节点,重新遍历链表
  • 进入循环
  • 拷贝指针指向pcur的下一个节点
  • 如果pcur指针指向节点的随机指针指向NULL,拷贝节点的随机指针则相同
  • 否则拷贝节点每次指向pcur指针指向节点的下一个节点
  • 修改拷贝节点的随机指针,令其指向pcur指针指向节点的随机指针指向的节点的下一个节点
  • 然后pcur指针指向拷贝节点的下一个节点,拷贝指针指向pcur指针的下一个节点

这一部分实现代码如下

代码语言:javascript
代码运行次数:0
复制
pcur=head;//指针重置
    while(pcur)//链表随机指针拷贝
    {
        Node*copy=pcur->next;
        if(pcur->random==NULL)
            copy->random=NULL;//对指向NULL的情况额外处理
        else
        {
            copy->random=pcur->random->next;//随机指针拷贝的关键
        }
        pcur=copy->next;
    }
3.原链表中节点的next指针拷贝,拷贝节点成为单独的新链表

第三个循环:

  • pcur指针重新指向链表第一个节点
  • 创建新链表的头指针和尾指针初始都指向空
  • 进入循环——拷贝指针指向pcur的下一个节点
  • next指针指向拷贝指针的下一个节点
  • 接下来将拷贝节点尾插到新链表,并恢复原链表
  • 如果新链表为空,则新链表首尾指针都指向拷贝节点
  • 否则,新链表尾指针的next指向拷贝节点,然后尾指针指向拷贝节点
  • 再将pcur指针指向节点的next指向next指针对应的节点
  • 循环直到pcur走向NULL

这一部分的实现代码如下

别忘记拷贝完成之后,返回新链表的地址

代码语言:javascript
代码运行次数:0
复制
pcur=head;
    Node*newhead=NULL,*newtail=NULL;
    while(pcur)
    {
        Node*copy=pcur->next;//指向要拷贝的节点
        Node*next=copy->next;//指向原链表原本的下一个节点

        if(newhead==NULL)//将拷贝节点尾插到新链表上
        {
            newhead=newtail=copy;
        }
        else
        {
            newtail->next=copy;
            newtail=copy;
        }

        pcur->next=next;//恢复原链表
        pcur=next;
    }
    return newhead;
完整代码
代码语言:javascript
代码运行次数:0
复制
/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */
typedef struct Node Node;
struct Node* copyRandomList(struct Node* head) 
{
    Node* pcur=head;
    while(pcur)//链表数据拷贝
    {
        Node*copy=(Node*)malloc(sizeof(Node));//创建拷贝节点
        copy->val=pcur->val;//拷贝数据

        copy->next=pcur->next;//插入到pcur后面
        pcur->next=copy;

        pcur=copy->next;//移动pcur指针
    }


    pcur=head;//指针重置
    while(pcur)//链表随机指针拷贝
    {
        Node*copy=pcur->next;
        if(pcur->random==NULL)
            copy->random=NULL;//对指向NULL的情况额外处理
        else
        {
            copy->random=pcur->random->next;//随机指针拷贝的关键
        }
        pcur=copy->next;
    }

    pcur=head;
    Node*newhead=NULL,*newtail=NULL;
    while(pcur)
    {
        Node*copy=pcur->next;//指向要拷贝的节点
        Node*next=copy->next;//指向原链表原本的下一个节点

        if(newhead==NULL)//将拷贝节点尾插到新链表上
        {
            newhead=newtail=copy;
        }
        else
        {
            newtail->next=copy;
            newtail=copy;
        }

        pcur->next=next;//恢复原链表
        pcur=next;
    }
    return newhead;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、问题描述
  • 二、解题思路
  • 三、代码实现
    • 1. 原链表中节点的数据拷贝
    • 2.原链表中节点的随机指针拷贝
    • 3.原链表中节点的next指针拷贝,拷贝节点成为单独的新链表
    • 完整代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档