C语言之复杂链表的复制方法(图示详解)

发布时间 - 2026-01-11 02:09:53    点击率:

什么是复杂链表?

复杂链表指的是一个链表有若干个结点,每个结点有一个数据域用于存放数据,还有两个指针域,其中一个指向下一个节点,还有一个随机指向当前复杂链表中的任意一个节点或者是一个空结点。今天我们要实现的就是对这样一个复杂链表复制产生一个新的复杂链表。

复杂链表的数据结构如下:

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;

}

程序的运行结果如下图:

以上这篇C语言之复杂链表的复制方法(图示详解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。


# 复杂链表的复制  # C语言之复杂链表的复制详解  # C语言数据结构之复杂链表的拷贝  # C语言复杂链表的复制实例详解  # 链表  # 数据结构  # 两条  # 我们应该  # 这条  # 给大家  # 下个  # 创建一个  # 如下图  # 就可以  # 称之为  # 是一个  # 这是  # 头文件  # 这一  # 很好  # 成了  # 要把  # 我们可以  # 希望能 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 详解Nginx + Tomcat 反向代理 如何在高效的在一台服务器部署多个站点  网站制作价目表怎么做,珍爱网婚介费用多少?  Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】  如何撰写建站申请书?关键要点有哪些?  Laravel如何设置定时任务(Cron Job)_Laravel调度器与任务计划配置  Linux系统命令中screen命令详解  Laravel如何使用.env文件管理环境变量?(最佳实践)  HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】  安克发布新款氮化镓充电宝:体积缩小 30%,支持 200W 输出  移动端脚本框架Hammer.js  Laravel如何实现API版本控制_Laravel版本化API设计方案  微信小程序 wx.uploadFile无法上传解决办法  高配服务器限时抢购:企业级配置与回收服务一站式优惠方案  音乐网站服务器如何优化API响应速度?  香港服务器如何优化才能显著提升网站加载速度?  深圳防火门网站制作公司,深圳中天明防火门怎么编码?  如何安全更换建站之星模板并保留数据?  Python进程池调度策略_任务分发说明【指导】  Java类加载基本过程详细介绍  Laravel如何部署到服务器_线上部署Laravel项目的完整流程与步骤  javascript中数组(Array)对象和字符串(String)对象的常用方法总结  用v-html解决Vue.js渲染中html标签不被解析的问题  奇安信“盘古石”团队突破 iOS 26.1 提权  php嵌入式断网后怎么恢复_php检测网络重连并恢复硬件控制【操作】  如何快速搭建个人网站并优化SEO?  Laravel如何处理异常和错误?(Handler示例)  Android仿QQ列表左滑删除操作  如何快速重置建站主机并恢复默认配置?  Laravel如何获取当前用户信息_Laravel Auth门面获取用户ID  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  如何在阿里云香港服务器快速搭建网站?  HTML5空格在Angular项目里怎么处理_Angular中空格的渲染问题【详解】  Laravel怎么实现模型属性的自动加密  Laravel API路由如何设计_Laravel构建RESTful API的路由最佳实践  Laravel怎么写单元测试_PHPUnit在Laravel项目中的基础测试入门  Bootstrap整体框架之CSS12栅格系统  怎么用AI帮你为初创公司进行市场定位分析?  Laravel如何与Pusher实现实时通信?(WebSocket示例)  Laravel怎么生成URL_Laravel路由命名与URL生成函数详解  Chrome浏览器标签页分组怎么用_谷歌浏览器整理标签页技巧【效率】  详解Oracle修改字段类型方法总结  如何基于PHP生成高效IDC网络公司建站源码?  Laravel如何与Docker(Sail)协同开发?(环境搭建教程)  Win11怎么开启自动HDR画质_Windows11显示设置HDR选项  laravel怎么用DB facade执行原生SQL查询_laravel DB facade原生SQL执行方法  HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】  iOS验证手机号的正则表达式  1688铺货到淘宝怎么操作 1688一键铺货到自己店铺详细步骤  Laravel怎么在Controller之外的地方验证数据  新三国志曹操传主线渭水交兵攻略