首页 > 代码库 > C语言之复杂链表的复制(图示详解)
C语言之复杂链表的复制(图示详解)
什么是复杂链表?
复杂链表指的是一个链表有若干个结点,每个结点有一个数据域用于存放数据,还有两个指针域,其中一个指向下一个节点,还有一个随机指向当前复杂链表中的任意一个节点或者是一个空结点。今天我们要实现的就是对这样一个复杂链表复制产生一个新的复杂链表。
复杂链表的数据结构如下:
1 typedef int DataType; //数据域的类型 2 3 //复杂链表的数据结构 4 5 typedef struct ComplexNode 6 7 { 8 9 DataType _data ; // 数据 10 11 struct ComplexNode * _next; // 指向下个节点的指针 12 13 struct ComplexNode * _random; // 指向随机节点(可以是链表中的任意节点 or 空) 14 15 }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:
1 #ifndef __COMPLEX__NODE__H__ 2 3 #define __COMPLEX__NODE__H__ 4 5 6 7 //包含头文件 8 9 #include <stdio.h> 10 11 #include<stdlib.h> 12 13 #include <assert.h> 14 15 16 17 18 19 typedef int DataType; //数据域的类型 20 21 22 23 //复杂链表的数据结构 24 25 typedef struct ComplexNode 26 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 return NULL; 20 21 } 22 23 //创建成功 24 25 cnode->_data =http://www.mamicode.com/ x; 26 27 cnode->_next = NULL; 28 29 cnode->_random = NULL; 30 31 return cnode; 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 return newlist; 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 void test() 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 int main() 74 75 { 76 77 test(); 78 79 return 0; 80 81 }
程序的运行结果如下图:
C语言之复杂链表的复制(图示详解)