c语言怎样复制链表,C语言之复杂链表的复制(图示详解)

c4468b3f4df77e96b0a416fa2a870fba.png

什么是复杂链表?

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

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

1 typedef int DataType; //数据域的类型2

3 //复杂链表的数据结构

4

5 typedef structComplexNode6

7 {8

9 DataType _data ; //数据

10

11 struct ComplexNode * _next; //指向下个节点的指针

12

13 struct ComplexNode * _random; //指向随机节点(可以是链表中的任意节点 or 空)

14

15 }ComplexNode;

73b49a2c198cfcaa3583e90cd0ed21f4.png

上图就是一个复杂链表的例子,那么我们应该如何实现复杂链表的复制呢?

1、首先我们应该根据已有的复杂链表创建一条新的复杂链表,但是这个新的复杂链表的所有的结点的random指针都指向空,这样是很好实现的,相当于我们创建了一条简单的单链表(newlist),我们要复制的链表不妨称之为oldlist。

ce981f0e8fe888e948851dd949ce3961.png

2、接下来我们应该把新创建的这条复杂链表(newlist)与已有的复杂链表(oldlist)合并成如下的形式:

e2c1e9df15a797b75daabb32948fb58b.png

在这种情况下我们已经把两条复杂链表合并成了一条链表(称之为linklist),通过对这条链表(linklist)的观察,我们可以发现合并的链表(linklist)中属于newlist的结点pnew的上一个结点pold(属于oldlist的结点)的random指针所指向的结点的next指针就应该是pnew结点的randow指针所指向的结点。

这样我们让pold和pnew指针一直往后走最后就可以实现对所有属于新创建的复杂链表(newlist)的random指针指向相应的结点的操作。构成的复杂链表如下图

0516128f27647cec78614d306a9cfb6a.png

在完成以上的步骤之后我们所要做的工作就很简单了,我们只要把这一条链表linklist分开成我们的newlist链表和oldlist链表就可以了。

82f5ed188f33e2a6ae45e88040634d2d.png

19b729fb4b6f375f3670ac6a2da8d034.png

这样我们就完美的完成了复杂链表的复制工作下面就是具体实现的代码:

头文件complexnode.h:

1 #ifndef __COMPLEX__NODE__H__2

3 #define __COMPLEX__NODE__H__

4

5

6

7 //包含头文件

8

9 #include

10

11 #include

12

13 #include

14

15

16

17

18

19 typedef int DataType; //数据域的类型20

21

22

23 //复杂链表的数据结构

24

25 typedef structComplexNode26

27 {28

29 DataType _data ; //数据

30

31 struct ComplexNode * _next; //指向下个节点的指针

32

33 struct ComplexNode * _random; //指向随机节点(可以是链表中的任意节点 or 空)

34

35 }ComplexNode;36

37

38

39 //创建一个复杂链表的结点

40

41 ComplexNode *BuyComplexNode(DataType x);42

43

44

45 //打印复杂的单链表

46

47 void Display(const ComplexNode *cplist);48

49

50

51 //复杂链表的复制

52

53 ComplexNode * CopyComplexNode(ComplexNode *cplist);54

55

56

57 #endif//__COMPLEX__NODE__H__

具体功能实现complexnode.c

1 #include "complexnode.h"

2

3

4

5 //创建一个复杂链表的结点

6

7 ComplexNode *BuyComplexNode(DataType x)8

9 {10

11 ComplexNode *cnode = (ComplexNode *)malloc(sizeof(ComplexNode));12

13 if(cnode == NULL)//创建失败

14

15 {16

17 perror("BuyComplexNode()::malloc");18

19 returnNULL;20

21 }22

23 //创建成功

24

25 cnode->_data =x;26

27 cnode->_next =NULL;28

29 cnode->_random =NULL;30

31 returncnode;32

33 }34

35

36

37 //打印复杂的单链表

38

39 void Display(const ComplexNode *cplist)40

41 {42

43 ComplexNode *pnode =cplist;44

45 while(pnode)46

47 {48

49 printf("%d::%d -->",pnode->_data,pnode->_random->_data);50

51 pnode = pnode->_next;52

53 }54

55 printf("over\n");56

57

58

59 }60

61

62

63 //复杂链表的复制

64

65 ComplexNode * CopyComplexNode(ComplexNode *cplist)66

67 {68

69

70

71 ComplexNode * pold =NULL;72

73 ComplexNode * pnew =NULL;74

75 ComplexNode * newlist = NULL;//指向新的复杂链表的头结点的指针

76

77 pold =cplist;78

79 //创建一条新的复杂链表

80

81 while(pold !=NULL)82

83 {84

85 ComplexNode * new_node = BuyComplexNode(pold->_data);86

87 if(newlist == NULL)//当新的复杂链表中没有结点时

88

89 {90

91 newlist =new_node;92

93 }94

95 else//当新的复杂链表有结点时

96

97 {98

99 ComplexNode * node =newlist;100

101 while(node->_next != NULL)//找到最后一个结点

102

103 {104

105 node = node->_next;106

107 }108

109 node->_next = new_node;//插入新的结点

110

111 }112

113 pold = pold->_next;114

115

116

117 }//创建新的复杂链表结束118

119

120

121 //合并两条复杂链表

122

123 pold =cplist;124

125 pnew =newlist;126

127 while(pold)128

129 {130

131 ComplexNode * curold =NULL;132

133 ComplexNode * curnew =NULL;134

135 curold = pold->_next;136

137 curnew = pnew->_next;138

139 if(pold->_next ==NULL)140

141 {142

143 pold->_next =pnew;144

145 pold =curold;146

147 pnew =curnew;148

149 break;150

151 }152

153 pold->_next =pnew;154

155 pnew->_next =curold;156

157 pold =curold;158

159 pnew =curnew;160

161 }//合并两条复杂链表结束162

163

164

165 //让新创建的那条复杂链表上的所有结点的random指针指向相应的结点

166

167 pold =cplist;168

169 pnew =newlist;170

171 while(pnew)172

173 {174

175 pnew->_random = pold->_random->_next;176

177 pold = pnew->_next;178

179 if(pold == NULL)//这是pnew的_next指针已经指向空

180

181 {182

183 break;184

185 }186

187 pnew = pold->_next;188

189 }//结束190

191

192

193 //分离合并后的复杂链表

194

195 pold =cplist;196

197 pnew =newlist;198

199 while(pold)200

201 {202

203 ComplexNode * curold =NULL;204

205 ComplexNode * curnew =NULL;206

207 if(pnew->_next == NULL)//已经分离完成

208

209 {210

211 pold->_next =NULL;212

213 pnew->_next =NULL;214

215 break;216

217

218

219 }220

221 curold = pold->_next->_next;222

223 curnew = pnew->_next->_next;224

225

226

227 pold->_next =curold;228

229 pnew->_next =curnew;230

231 pold =curold;232

233 pnew =curnew;234

235 }//分离合并的复杂链表结束

236

237

238

239 returnnewlist;240

241 }

测试代码test.c:

1 #include "complexnode.h"

2

3 //

4

5 //复杂链表的复制。?个链表的每个节点,有?个指向next指针指向下?个节6

7 //点,还有?个random指针指向这个链表中的?个随机节点或者NULL,现在要8

9 //求实现复制这个链表,返回复制后的新链表。10

11 //ps: 复杂链表的结构

12

13

14

15

16

17

18

19 voidtest()20

21 {22

23 ComplexNode *cplist;24

25 ComplexNode *copylist;26

27 ComplexNode *node1;28

29 ComplexNode *node2;30

31 ComplexNode *node3;32

33 ComplexNode *node4;34

35 cplist = BuyComplexNode(1);36

37 node1 = BuyComplexNode(2);38

39 node2 = BuyComplexNode(3);40

41 node3 = BuyComplexNode(4);42

43 node4 = BuyComplexNode(5);44

45 cplist->_next =node1;46

47 node1->_next =node2;48

49 node2->_next =node3;50

51 node3->_next =node4;52

53 cplist->_random =node3;54

55 node1->_random =node4;56

57 node2->_random =cplist;58

59 node3->_random =node1;60

61 node4->_random =node2;62

63 Display(cplist);64

65 copylist =CopyComplexNode(cplist);66

67 Display(copylist);68

69

70

71 }72

73 intmain()74

75 {76

77 test();78

79 return 0;80

81 }

程序的运行结果如下图:

3f565395b1613e152b5ca38b1bc7dbae.png

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com

特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值