C语言之复杂链表的复制详解
什么是复杂链表?
复杂链表指的是一个链表有若干个结点,每个结点有一个数据域用于存放数据,还有两个指针域,其中一个指向下一个节点,还有一个随机指向当前复杂链表中的任意一个节点或者是一个空结点。今天我们要实现的就是对这样一个复杂链表复制产生一个新的复杂链表。
复杂链表的数据结构如下:
typedef int DataType; //数据域的类型 //复杂链表的数据结构 typedef struct ComplexNode { DataType _data ; // 数据 struct ComplexNode * _next; // 指向下个节点的指针 struct ComplexNode * _random; // 指向随机节点(可以是链表中的任意节点 or 空) }ComplexNode;
上图就是一个复杂链表的例子,那么我们应该如何实现复杂链表的复制呢?
1、首先我们应该根据已有的复杂链表创建一条新的复杂链表,但是这个新的复杂链表的所有的结点的random指针都指向空,这样是很好实现的,相当于我们创建了一条简单的单链表(newlist),我们要复制的链表不妨称之为oldlist。
2、接下来我们应该把新创建的这条复杂链表(newlist)与已有的复杂链表(oldlist)合并成如下的形式:
在这种情况下我们已经把两条复杂链表合并成了一条链表(称之为linklist),通过对这条链表(linklist)的观察,我们可以发现合并的链表(linklist)中属于newlist的结点pnew的上一个结点pold(属于oldlist的结点)的random指针所指向的结点的next指针就应该是pnew结点的randow指针所指向的结点。
这样我们让pold和pnew指针一直往后走最后就可以实现对所有属于新创建的复杂链表(newlist)的random指针指向相应的结点的操作。构成的复杂链表如下图
在完成以上的步骤之后我们所要做的工作就很简单了,我们只要把这一条链表linklist分开成我们的newlist链表和oldlist链表就可以了。
这样我们就完美的完成了复杂链表的复制工作下面就是具体实现的代码:
头文件complexnode.h:
#ifndef __COMPLEX__NODE__H__ #define __COMPLEX__NODE__H__ //包含头文件 #include <stdio.h> #include<stdlib.h> #include <assert.h> typedef int DataType; //数据域的类型 //复杂链表的数据结构 typedef struct ComplexNode { DataType _data ; // 数据 struct ComplexNode * _next; // 指向下个节点的指针 struct ComplexNode * _random; // 指向随机节点(可以是链表中的任意节点 or 空) }ComplexNode; //创建一个复杂链表的结点 ComplexNode * BuyComplexNode(DataType x); //打印复杂的单链表 void Display(const ComplexNode * cplist); //复杂链表的复制 ComplexNode * CopyComplexNode(ComplexNode * cplist); #endif//__COMPLEX__NODE__H__
具体功能实现complexnode.c
#include "complexnode.h" //创建一个复杂链表的结点 ComplexNode * BuyComplexNode(DataType x) { ComplexNode *cnode = (ComplexNode *)malloc(sizeof(ComplexNode)); if(cnode == NULL)//创建失败 { perror("BuyComplexNode()::malloc"); return NULL; } //创建成功 cnode->_data = x; cnode->_next = NULL; cnode->_random = NULL; return cnode; } //打印复杂的单链表 void Display(const ComplexNode * cplist) { ComplexNode *pnode = cplist; while (pnode) { printf("%d::%d -->",pnode->_data,pnode->_random->_data); pnode = pnode->_next; } printf("over\n"); } //复杂链表的复制 ComplexNode * CopyComplexNode(ComplexNode * cplist) { ComplexNode * pold = NULL; ComplexNode * pnew = NULL; ComplexNode * newlist = NULL;//指向新的复杂链表的头结点的指针 pold = cplist; //创建一条新的复杂链表 while(pold != NULL) { ComplexNode * new_node = BuyComplexNode(pold->_data); if(newlist == NULL)//当新的复杂链表中没有结点时 { newlist = new_node; } else//当新的复杂链表有结点时 { ComplexNode * node = newlist; while(node->_next != NULL)//找到最后一个结点 { node = node->_next; } node->_next = new_node;//插入新的结点 } pold = pold->_next; }//创建新的复杂链表结束 //合并两条复杂链表 pold = cplist; pnew = newlist; while (pold) { ComplexNode * curold = NULL; ComplexNode * curnew = NULL; curold = pold->_next; curnew = pnew->_next; if(pold->_next == NULL) { pold->_next = pnew; pold = curold; pnew = curnew; break; } pold->_next = pnew; pnew->_next = curold; pold = curold; pnew = curnew; }//合并两条复杂链表结束 //让新创建的那条复杂链表上的所有结点的random指针指向相应的结点 pold = cplist; pnew = newlist; while (pnew) { pnew->_random = pold->_random->_next; pold = pnew->_next; if(pold == NULL)//这是pnew的_next指针已经指向空 { break; } pnew = pold->_next; }//结束 //分离合并后的复杂链表 pold = cplist; pnew = newlist; while (pold) { ComplexNode * curold = NULL; ComplexNode * curnew = NULL; if(pnew->_next == NULL)//已经分离完成 { pold->_next = NULL; pnew->_next = NULL; break; } curold = pold->_next->_next; curnew = pnew->_next->_next; pold->_next = curold; pnew->_next = curnew; pold = curold; pnew = curnew; }//分离合并的复杂链表结束 return newlist; } 测试代码test.c: #include "complexnode.h" // //复杂链表的复制。?个链表的每个节点,有?个指向next指针指向下?个节 //点,还有?个random指针指向这个链表中的?个随机节点或者NULL,现在要 //求实现复制这个链表,返回复制后的新链表。 //ps: 复杂链表的结构 void test() { ComplexNode * cplist; ComplexNode * copylist; ComplexNode * node1; ComplexNode * node2; ComplexNode * node3; ComplexNode * node4; cplist = BuyComplexNode(1); node1 = BuyComplexNode(2); node2 = BuyComplexNode(3); node3 = BuyComplexNode(4); node4 = BuyComplexNode(5); cplist->_next = node1; node1->_next = node2; node2->_next = node3; node3->_next = node4; cplist->_random = node3; node1->_random = node4; node2->_random = cplist; node3->_random = node1; node4->_random = node2; Display(cplist); copylist = CopyComplexNode(cplist); Display(copylist); } int main() { test(); return 0; }
程序的运行结果如下图:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
- 开源组件NanUI一周年-使用HTML/CSS/JS来构建.Net Winform应用程序界面
- 邱寒:新零售笔记(四)基于区块链大数据的人工智能
- 腾讯云GAME-TECH沙龙干货回顾:网龙《英魂之刃口袋版》开发经验分享
- ASP.NET MVC基于标注特性的Model验证:一个Model,多种验证规则
- 【深度学习系列】用PaddlePaddle和Tensorflow实现经典CNN网络AlexNet
- 黄荣奎:如何快速、便捷开发小程序
- 熊普江: BGP网络架构助力开发者快速构建、优化业务
- 唐良:云端架构给电商行业带来创新力
- 邹方明:看腾讯云如何架构海量存储系统
- 王之捷:AI智能云端架构大幅提升智能语音识别能力
- 精彩大放送 | 腾讯云:容器架构向无服务架构的演进
- Python 数据分析学习笔记
- 如何用Fiddler抓取https
- 人工智能与大数据结合,帮助降低自杀率
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 使用代码修改SAP CRM附件的属性
- SAP CRM附件创建的internal模式是什么含义
- 搭建maven私服上传并使用Jar包
- Docker 容器跨主机多网段通信解决方案
- Docker 容器实现数据持久化
- mongodb----复制
- CentOS磁盘挂载
- Mono for Android 实现高效的导航
- MyBatis版本升级导致OffsetDateTime入参解析异常问题复盘
- elasticSearch学习(二)
- 146. LRU缓存机制 Krains 2020-08-05 12:50:28 链表
- 337. 打家劫舍 III Krains 2020-08-05 10:18:45 动态规划
- 58道Vue常见面试题集锦,涵盖入门到精通,自测 Vue 掌握程度
- 记一次Linux计划任务cron无结果的排查过程
- 一文学会使用 CSS 中的 min(), max(), clamp() 以及它们的使用场景用例