【数据结构】研究链表深度拷贝问题

💯💯💯

本篇总结链表如何深度拷贝,考虑链表拷贝后地址不能相同,采用一种独特的方式来拷贝原链表的相对位置,图文分析,更好理解。


在这里插入图片描述 请添加图片描述

⏰.链表深度拷贝

在这里插入图片描述
深度拷贝指的是将该链表上每个结点都拷贝过来,链接形式是与原链表一模一样。
但要注意的是,拷贝的链表的链接形式虽然跟原链表一样,但它们的地址都是不同的,拷贝的链表中的指针都不应该指向原链表中的结点。
在这里插入图片描述
而解答本题的思路就是:
1.在每个结点的后面生成自己的拷贝结点
2.处理每个拷贝结点的random
3.将所有拷贝结点拿下来,尾插形成新的链表
4.恢复原链表链接关系

🕑生成拷贝结点

在这里插入图片描述

 //1.在每个结点的后面生成拷贝结点
      struct Node* cur = head;//利用cur进行遍历,不使用head遍历
      while (cur)
      {
          struct Node* next = cur->next;//记录后面结点的位置
          struct Node* copy = (struct Node*)malloc(sizeof(struct Node));//开辟一个结点出来
          copy->val = cur->val;//将原结点的数据拷贝过去
          //cur  copy  next现在就是要求这个样子,cur第一个结点,copy要插在cur和next在中间
          cur->next = copy;
          copy->next = next;
          //插入结点
          cur = next;//迭代操作
       }

在这里插入图片描述

🕒处理random

在这里插入图片描述

  //2.处理每个拷贝结点的random
      cur = head;//将cur重新指回头结点
      while (cur)
      {
          struct Node* copy = cur->next;//记录每个拷贝结点的位置
          if (cur->random == NULL)//如果原结点的random为NULL
          {
              copy->random = NULL;//则拷贝结点的random也为NULL
          }
          else
          {
              copy->random = cur->random->next;//否则拷贝结点的random就等于原结点random的next。
          }
          cur = cur->next->next;//cur每次要走两步,因为这样才可以每次都走到原结点上去,然后原结点的next就是拷贝结点
      }

🕓解下拷贝结点

在这里插入图片描述

 //3.解下拷贝结点,恢复原来结点链接
      cur = head;//使cur重新指向头结点
      struct Node* copyhead = NULL, * tail = NULL;//因为拷贝结点需要尾插成一条链表,需要头结点和找尾操作
      while (cur)
      {
          //解下拷贝结点就是把结点拿下来尾插.尾插需要头指针尾指针
          struct Node* copy = cur->next;//记录每个拷贝结点
          struct Node* next = copy->next;//记录每个原来结点
          if (copyhead == NULL)//一开始新链表头结点是空所以需要将第一个拷贝结点赋值过去
          {
              copyhead = tail = copy;
          }
          else
          {
              tail->next = copy;//接下来才是真正的尾插,将拷贝结点尾插到tail结点的next上去
              tail = tail->next;//tail结点每次都需要更新,以便找尾
          }
          //恢复链接关系
          cur->next = next;//next记录的是每个copy结点的下一个那就是原结点,原结点与cur链接恢复原来链接关系
          //迭代
          cur = next;
      }

在这里插入图片描述

⏰.完整代码

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */
  struct Node* copyRandomList(struct Node* head)
{
      //1.在每个结点的后面生成拷贝结点
      struct Node* cur = head;
      while (cur)
      {
          struct Node* next = cur->next;
          struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
          copy->val = cur->val;
          //cur  copy  next
          cur->next = copy;
          copy->next = next;
          //插入结点
          // 迭代
          cur = next;
       }
       //2.处理每个拷贝结点的random
      cur = head;
      while (cur)
      {
          struct Node* copy = cur->next;
          if (cur->random == NULL)
          {
              copy->random = NULL;
          }
          else
          {
              copy->random = cur->random->next;
          }
          cur = cur->next->next;
      }
      //3.解下拷贝结点,恢复原来结点链接
      cur = head;
      struct Node* copyhead = NULL, * tail = NULL;
      while (cur)
      {
          //解下拷贝结点就是把结点拿下来尾插.尾插需要头指针尾指针
          struct Node* copy = cur->next;
          struct Node* next = copy->next;
          if (copyhead == NULL)
          {
              copyhead = tail = copy;
          }
          else
          {
              tail->next = copy;
              tail = tail->next;
          }
          //恢复链接关系
          cur->next = next;

          //迭代
          cur = next;
      }
      return copyhead;
}
  • 18
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小陶来咯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值