深度剖析:复制带随机指针的链表算法实现

news2025/3/26 19:05:10

在链表相关的算法中,复制一个带有随机指针的链表是一个经典且具有一定难度的问题。本文将深入分析一段用C语言实现的复制带随机指针链表的代码,通过模块化的方式详细解释每段代码的作用,帮助读者更好地理解这一复杂算法。
 

作者主页:共享家9527-CSDN博客

代码仓:Study in the first semester of college.c: 大一下学期学习,主要内容为个人学习过程记录

2025寒假C语言学习: 学习记录


链表节点定义
 


c
  
/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */
 


 
这段代码定义了链表节点的结构。每个节点包含三个成员:一个整数值 val ,一个指向下一个节点的指针 next ,以及一个指向链表中任意节点(或NULL)的随机指针 random 。这个定义是后续链表操作的基础。
 


复制链表主体函数
 


c
  
struct Node* copyRandomList(struct Node* head) {
    // 若为空链表,直接返回NULL
    if(!head) return NULL;
 


 
函数 copyRandomList 接收链表的头指针 head 作为参数,返回复制后的链表头指针。首先进行边界条件检查,如果原链表为空( head 为NULL),则直接返回NULL,因为没有节点需要复制。
 


第一步:在原链表每个节点后添加复制节点
 


c
  
// 在与原链表的每个节点后添加复制一个节点
struct Node* node = head;
while(node){
    struct Node* newNode = malloc(sizeof(struct Node));
    newNode->val = node->val;
    newNode->next = node->next;
    newNode->random = NULL;
    node->next = newNode;
    node = node->next->next;
}
 


 
这部分代码的作用是在原链表的每个节点后面插入一个复制节点。具体步骤如下:
 
1. 初始化一个指针 node 指向原链表的头节点。
 
2. 使用 while 循环遍历原链表。
 
3. 对于每个节点,分配内存创建一个新节点 newNode 。
 
4. 将原节点的值 val 复制到新节点。
 
5. 新节点的 next 指针指向原节点的下一个节点。
 
6. 新节点的 random 指针初始化为NULL。
 
7. 将原节点的 next 指针指向新节点,从而将新节点插入到原节点之后。
 
8. 更新 node 指针,跳过新插入的节点,指向下一个原节点。
 


第二步:为复制节点的random指针赋值
 


c
  
// 为所有复制的节点的random赋值
node = head;
while(node){
    // 若原节点的random不为空,赋值
    if(node->random){
        node->next->random = node->random->next;
    }
    node = node->next->next;
}
 


 
在这一步中,再次遍历链表,为所有复制节点的 random 指针赋值。因为复制节点紧跟在原节点之后,所以 node->next 就是复制节点。如果原节点的 random 指针不为NULL,那么原节点 random 指向节点的下一个节点就是复制节点 random 应该指向的节点(即 node->random->next )。
 


第三步:分离新链表和原链表
 


c
  
// 分离新节点和旧节点
struct Node* newHead = head->next;
struct Node* pre = head;
struct Node* cur = head->next;
while(pre->next->next){
    pre->next = cur->next;
    cur->next = cur->next->next;
    pre = pre->next;
    cur = pre->next;
}
pre->next = NULL;
return newHead;
 


 
最后一步是将新链表从交错的链表结构中分离出来。具体操作如下:
 
1. 初始化 newHead 为新链表的头节点,即原链表头节点的下一个节点。
 
2. 使用 pre 指向原链表节点, cur 指向新链表节点。
 
3. 通过 while 循环,不断调整 pre 和 cur 的 next 指针,将原链表和新链表分离。
 
4. 当原链表只剩下最后一个节点时,将 pre 的 next 指针设为NULL,完成原链表的修复。
 
5. 最后返回新链表的头指针 newHead 。


 
通过以上三个步骤,成功实现了对带随机指针链表的复制。这种方法巧妙地利用了原链表的结构,在不使用额外复杂数据结构(如哈希表)的情况下完成了复制操作,时间复杂度为O(n),空间复杂度为O(1)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2320686.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java 大视界 -- Java 大数据在智慧文旅旅游目的地营销与品牌传播中的应用(150)

💖亲爱的朋友们,热烈欢迎来到 青云交的博客!能与诸位在此相逢,我倍感荣幸。在这飞速更迭的时代,我们都渴望一方心灵净土,而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识,也…

SQLMesh SCD-2 时间维度实战:餐饮菜单价格演化追踪

场景背景:动态菜单价格管理 考虑某连锁餐厅的菜单管理系统,需要记录食品价格的历史变更轨迹。业务需求包括: 记录每次价格调整的时间点支持历史价格查询(如"2020年1月2日汉堡多少钱")维护当前有效价格清单…

uniapp自身bug | uniapp+vue3打包后 index.html无法直接运行

前提: 已经修改了基础路径 打开打包文件,双击运行index.html报错,无法访问页面 uniappvue2项目是可以正常运行的 vue3修改publicPath: ./后,也是可以正常访问打包文件中的index.html 点进控制台提供的链接:https:/…

数据分析面试--京东

1.考察日期函数的应用 select Order_date, count(distinct user_id) as uv from (select user_id, Order_date, row_number() over(partition by user_id order by Order_date) as new_tagfrom ord where date_diff(current_date(), Order_date)<30 ) t where new_tag1 gro…

Centos7搭建Zabbix4.x监控HCL模拟网络设备:zabbix-server搭建及监控基础04

兰生幽谷&#xff0c;不为莫服而不芳&#xff1b; 君子行义&#xff0c;不为莫知而止休。 4.OID查看工具Getif安装及使用 找度娘下载Getif&#xff0c;该软件比较老&#xff0c;可以用来查看OID编码&#xff0c;我的宿主机是Win11,无法安装。所以只有到虚拟机win12去安装&am…

蓝桥杯2023年第十四届省赛真题-异或和之差

题目来自DOTCPP&#xff1a; 思路&#xff1a; 什么是异或和&#xff1f; ①题目要求我们选择两个不相交的子段&#xff0c;我们可以枚举一个分界线i&#xff0c;子段1在 i 的左边&#xff0c; 子段2在 i 的右边&#xff0c;分别找到子段1和子段2的最大值、最小值。 ②怎么确…

Linux系统管理实战:文件权限配置、用户组协作与日志处理全解析

1、创建/www目录&#xff0c;在/www目录下新建name和https目录&#xff0c;在name和https目录下分别创建一个index.html文件&#xff0c;name下面的index.html文件中包含当前主机的主机名&#xff0c;https目录下的index.html文件中包含当前主机的ip地址。 &#xff08;1&…

[自动化] 【八爪鱼】使用八爪鱼实现CSDN文章自动阅读脚本

在CSDN上&#xff0c;文章的阅读量往往是衡量内容影响力的一个重要指标。为了测试自动化手段能否提高阅读数&#xff0c;我尝试使用网页自动化工具来模拟人工阅读某个ID的文章。 1. 网页自动化的常见方案 谈到网页自动化&#xff0c;Selenium 是一个最常见的选择。它可以通过…

N列股票收盘价为起点的马科维茨(Markowitz)均值—方差理论

1. 数据准备与收益率计算 输入数据&#xff1a; 假设你有一个矩阵&#xff0c;每一列代表一只股票的历史收盘价序列。每一行对应一个时间点的收盘价。 计算收益率&#xff1a; 马科维茨理论要求使用资产的收益率而非价格。常用的收益率计算方法有对数收益率或简单收益率。 2.…

mac brew 安装的php@7.4 打开redis扩展

1. 找到php7.4的pecl目录 一般在这个位置 cd /usr/local/Cellar/php7.4/7.4.33_8/pecl/20190902 ls 一下 有个 redis.so 于是 直接去php.ini编辑了 php.ini的路径 vim /usr/local/etc/php/7.4/php.ini 把938行添加进去 然后重启一下 php7.4 brew services restart ph…

OSPF多区域通信

作业要求: 1、多区域0SPF area 0、area10、are20 2、AR5、AR6作为stub区&#xff0c;使用环回接口与Pc1进行通信 第一步&#xff1a;为各端口配置IP地址 AR1: <Huawei>sys [Huawei]int g0/0/0 [Huawei-GigabitEthernet0/0/0]ip add 5.5.5.1 24 [Huawei-GigabitEther…

三、重学C++—C语言内存管理

上一章节&#xff1a; 二、重学C—C语言核心-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/146191640?spm1001.2014.3001.5502 本章节代码&#xff1a; cPart2 CuiQingCheng/cppstudy - 码云 - 开源中国https://gitee.com/cuiqingcheng/cppstudy/tree/…

算法题(105):小猫爬山

审题&#xff1a; 本题需要我们找出将n个小猫放在有限重的缆车上运下山所需的最小缆车数 时间复杂度分析&#xff1a;本题的数据量小于等于18&#xff0c;所以我们在做好剪枝的前提下可以使用深度优先搜索解题 思路&#xff1a; 方法一&#xff1a;dfs 搜索策略&#xff1a;将小…

线程的pthread_create、pthread_join、pthread_exit、pthread_detach函数

线程的创建&#xff08;pthread_create&#xff09; pthread_t tid;//本质是unsigned long类型&#xff0c;打印时得到的是该线程的虚拟地址int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine)(void*), void *arg ); pthread_t *thre…

测试专项4:AI算法测试在测试行业中,该如何定位自己自述

这岗位到底干啥的&#xff1f; 打个比方&#xff1a; 你就像AI模型的“质检员产品经理风险顾问”三合一。 质检员&#xff1a; 别人造了个AI模型&#xff08;比如人脸识别系统&#xff09;&#xff0c;你不能光看它实验室成绩好&#xff0c;得把它丢到现实里折腾&#xff1a;…

【C语言系列】数据在内存中存储

数据在内存中存储 一、整数在内存中的存储二、大小端字节序和字节序判断2.1什么是大小端&#xff1f;2.2练习2.2.1练习12.2.2练习22.2.3练习32.2.4练习42.2.5练习52.2.6练习6 三、浮点数在内存中的存储3.1练习3.2浮点数的存储3.2.1 浮点数存的过程3.2.2 浮点数取的过程 3.3题目…

【中文翻译】第12章-The Algorithmic Foundations of Differential Privacy

由于GitHub项目仅翻译到前5章&#xff0c;我们从第6章开始通过大语言模型翻译&#xff0c;并导出markdown格式。 大模型难免存在错漏&#xff0c;请读者指正。 教材原文地址&#xff1a;https://www.cis.upenn.edu/~aaroth/Papers/privacybook.pdf 12 其他模型 到目前为止&…

图解模糊推理过程(超详细步骤)

我们前面已经讨论了三角形、梯形、高斯型、S型、Z型、Π型6种隶属函数&#xff0c;下一步进入模糊推理阶段。 有关六种隶属函数的特点在“Pi型隶属函数&#xff08;Π-shaped Membership Function&#xff09;的详细介绍及python示例”都有详细讲解&#xff1a;https://lzm07.b…

datawhale组队学习-大语言模型-task5:主流模型架构及新型架构

目录 5.3 主流架构 5.3.1 编码器-解码器架构 5.3.2 因果解码器架构 5.3.3 前缀解码器架构 5.4 长上下文模型 5.4.1 扩展位置编码 5.4.2 调整上下文窗口 5.4.3 长文本数据 5.5 新型模型架构 5.5.1 参数化状态空间模型 5.5.2 状态空间模型变种 5.3 主流架构 在预训…

RAG 架构地基工程-Retrieval 模块的系统设计分享

目录 一、知识注入的关键前奏——RAG 系统中的检索综述 &#xff08;一&#xff09;模块定位&#xff1a;连接语言模型与知识世界的桥梁 &#xff08;二&#xff09;核心任务&#xff1a;四大关键问题的协调解法 &#xff08;三&#xff09;系统特征&#xff1a;性能、精度…