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 = 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 }

 

程序的運行結果如下圖:

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM