第3次学习总结

1 .h
2 // 定义循环链结表元素类型为整数。
3 typedef int ElemType;
4
5 // 定义循环链结表节点
6 typedef struct node {
7 ElemType elem; // 节点数据,整数。
8 struct node* prev; // 节点的前链,递归定义。
9 struct node* next; // 节点的后链,递归定义。
10 } Node; // 节点型态
11
12 // 节点的链,是节点的指针。
13 typedef Node* Link;
14
15 // 循环双向链结表使用双节点指针,指向头节点和尾节点。
16 typedef struct {
17 Link head; // 头节点指针
18 Link tail; // 尾节点指针
19 } DList;
20
21 // 初始化循环双向链结表。
22 void initial(DList *);
23 // 取得循环双向链结表的元素个数。
24 int getSize(DList);
25
26 // 取出循环双向链结表的第 i 个元素, 返回该元素的值。
27 // 若 inx<0, 向左移动;若 inx>0, 向右移动。
28 // 若 |inx| 大于双向链结表的元素个数,则循环重复计数
29 ElemType getElem(DList, int);
30
31 // 搜寻循环双向链结表的元素。若成功,返回元素位置;否则,返回 -1。
32 int search(DList, ElemType);
33
34 // 将一个元素插入到循环双向链结表,返回该元素的位置。
35 int insert(DList *, ElemType);
36
37 // 从循环双向链结表删除一个元素。若成功,返回该元素原来的位置;
38 // 否则,返回 -1。
39 int delete(DList *, ElemType);
40
41 // 将循环双向链结表清空。
42 void clear(DList *);
43
44 // 檢查循环双向链结表是否為空表。若是空,返回 1;否则,返回 0。
45 int is_empty(DList);
46
47 // 打印循环双向链结表元素。
48 void printlst(DList);
49
50
51 .c
52 // 循环单链有序线性表基本操作介面
53 #include
54 #include
55 #include "sorted_list_circular_double_list.h"
56
57 // 初始化双向链结表 L。
58 void initial(DList *L) {
59 L->head = NULL; // 将双向链结表的头节点指针设为空值。
60 L->tail = NULL; // 将双向链结表的尾节点指针设为空值。
61 }
62
63 // 取得双向链结表 L 的元素个数。
64 int getSize(DList L) {
65 Link current = L.head; // 节点指针。
66 int size = 0; // 线性表个数初始值设为 0.
67
68 if (current==NULL) return size; // 如果线性表为空,则元素个数为 0.
69
70 do { // 加一个节点计数。
71 size++; // 个数加 1。
72 current = current->next; // 下一个节点。
73 } while (current!=L.head); // 如果不是尾节点,继续搜寻。
74 return size; // 线性表 L 的元素个数。
75 }
76
77 // 取出循环双向链结表的第 i 个元素, 返回该元素的值。
78 // 若 inx<0, 向左移动;若 inx>0, 向右移动。
79 // 若 |inx| 大于双向链结表的元素个数,则循环重复计数。
80 ElemType getElem(DList L, int inx) {
81 Link current = L.head; // 头节点指针。
82 int i; // 循环变量。
83
84 if (current==NULL) return -1; // 如果线性表为空,则无此元素。
85
86 // 循环线性表,如果 inx>size, 会重复 L 的头节点。
87 for (i=0; i 88 if (inx>0) current = current->next; // 往右移到下一个元素。
89 else current = current->prev; // 往左移到前一个元素。
90 return current->elem; // 返回节点的元素值。
91 }
92
93 // 搜寻循环双向链结表的元素。若成功,返回元素位置;否则,返回 -1。
94 int search(DList L, ElemType e) {
95 Link current = L.head; // 头节点指针。 int position=0; // 元素位置,设定初始值为 0。
96
97 if (current==NULL) return -1; // 如果循环双向链结表为空,则无此元素。
98
99 do { // 循环双向链结表不是空的,至少做一次。
100 if (current->elem==e) return position; // 搜寻成功,返回元素 e 的位置。
101 else if (current->elem102 position++; // 位置加 1。
103 current = current->next; // 移到下一个节点。
104 }
105 else return -1; // 节点的值已超过,搜寻失败。
106 } while (current!=L.head); // 若回到头节点,则停止循环。
107 return -1; // 已经超过循环双向链结表的最后一个节点,搜寻失败。
108 }
109
110 // 将一个元素插入到循环双向链结表,返回该元素的位置。
111 int insert(DList *L, ElemType e) {
112 Link current = L->head; // 指向头节点。
113 Link previous = L->tail; // 指向尾节点。
114 Link newNode; // 新节点的指针。
115 int size = getSize(*L); // 循环双向链结表的元素个数。
116 int position=0; // 目前节点位置。
117
118 if (current==NULL) { // Case 1:当循环双向链结表为空时。
119 newNode = (Link) malloc(sizeof(Node)); // 要求一个新节点的内存。
120 newNode->elem = e; // 复制节点的数据。
121 newNode->prev = newNode; // 循环双向链结表只有一个节点,prev 指向自己。
122 newNode->next = newNode; // 循环双向链结表只有一个节点,next 指向自己。
123 L->head = newNode; // 设定循环双向链结表只头节点。
124 L->tail = newNode; // 设定循环双向链结表只尾节点。
125 return position; // 头节点的位置为 0。
126 }
127
128 for (position=0; position129 if (current->elem>=e) break; // 找到第一个元素大于或等于 e 的节点。
130 previous = current; // 下一个 previous。
131 current = current->next; // 下一个 current。
132 }
133 // Cases 2, 3 & 4: 插入一个节点的 current 之前。
134 newNode = (Link) malloc(sizeof(Node)); // 要求一个新节点的内存。
135 newNode->elem = e; // 复制目前节点的数据。
136 newNode->prev = previous; // 设定新节点的的 prev 指针。
137 previous->next = newNode; // 将前一节点的 next 指针指向新节点。
138 newNode->next = current; // 设定新节点的 next 指针。
139 current->prev = newNode; // 将现节点的 prev 指针指向新节点。
140 if (position==0) L->head = newNode; // Case 2:更新头节点。
141 else if (position==size) L->tail = newNode; // Case 4: 更新尾节点。
142 return position; // 返回位置。
143 }
144
145 // 从循环双向链结表删除一个元素。若成功,返回该元素原来的位置;
146 // 否则,返回 -1。
147 int delete(DList *L, ElemType e) {
148 Link current = L->head; // 指向头节点。
149 Link previous = L->tail; // 指向尾节点。
150 int position = 0; // 目前节点位置。
151
152 if (current==NULL) return -1; // 若循环双向链结表为空,删除失败。
153
154 do { // 当循环双向链结表还有节点。
155 if (current->elem==e) { // 找到要删除的节点。
156 if (position==0) { // 删除的节点是头节点。
157 if (current->next==current) { // 循环双向链结表只有一个节点。
158 L->head = NULL; // 将头节点清空。
159 L->tail = NULL; // 将尾节点清空。
160 }
161 else {
162 previous->next = current->next; // 修改前一个节点的 next 指针。
163 current->next->prev = previous; // 修改下一个节点的 prev 指针。
164 L->head = current->next; // 更新头节点。
165 }
166 free(current); // 释放删除的节点。
167 return position; // 返回删除节点的原来位置。
168 }
169 else {
170 if (current->next==L->head) // 删除的是尾节点。
171 L->tail = previous; // 更新尾节点。
172 previous->next = current->next; // 修改前一个节点的 next 指针。
173 current->next->prev = previous; // 修改下一个节点的 prev 指针。
174 free(current); // 释放删除的节点。
175 return position; // 返回删除节点的原来位置。
176 }
177 }
178 else if (current->elem179 previous = current; // 将目前的节点设为前一个节点。
180 current = current->next; // 将下一个节点设为下一步骤的目前节点。
181 position++; // 位置加 1。
182 }
183 else return -1; // 目前节点数据已超过删除的值;删除失败。
184 } while (current!=L->head); // 若还没回到头节点,继续检查。
185
186 return -1; // current 回到头节点,删除失败。
187 }
188
189 // 将循环双向链结表清空。
190 void clear(DList *L) {
191 Link current = L->head; // 指向目前的节点。
192 Link previous; // 前一个节点。
193
194 while (current->next!=L->head) { // 不是尾节点。
195 previous = current; // 目前的节点。
196 current = current->next; // 下一个节点。
197 free(previous); // 释放目前的节点。
198 }
199 free(current); // 释放尾节点。
200 L->head = NULL; // 将循环双向链结表的头节点设为空。
201 L->tail = NULL; // 将循环双向链结表设尾节点设为空。
202 }
203
204 // 檢查循环双向链结表是否為空表。若是空,返回 1;否则,返回 0。
205 int is_empty(DList L) {
206 return L.head==NULL; // 若 L 的头节点为空,返回 1,否则,返回 0。
207 }
208
209 // 打印循环双向链结表元素。
210 void printlst(DList L) {
211 Link current = L.head; // 指向目前的节点。
212 int position = 0; // 目前节点的位置。
213
214 printf("线性表元素个数:%3d 元素\n", getSize(L));
215
216 if (current!=NULL) { // 循环双向链结表不是空的,开始打印。
217 while (current->next!=L.head) { // 还有节点要打印。
218 printf("%3d ", current->elem); // 打印节点数据。
219 if ((position+1)%20==0) printf("\n"); // 满 20 个元素,打印换行。
220 current = current->next; // 移到下一个节点。
221 position++; // 下一个位置。
222 }
223 printf("%3d \n", current->elem); // 打印尾节点数据和换行。
224 }
225 printf("\n"); // 打印一个换行。
226 }
227
228
229 main.c
230 #include
231 #include
232 #include
233 #include "sorted_list_circular_double_list.h"
234
235 // 合并 (merge) 两个循环线性表 L1 和 L2。
236 // 返回合并后的循环线性表。
237 DList merge_list(DList L1, DList L2) {
238 DList L; // 合并后的循环双向链结表。
239 int size1=getSize(L1), size2=getSize(L2); // 循环双向链结表 L1,和 L2 的大小。
240 ElemType e1, e2; // 循环双向链结表 L1 和 L2 的元素。
241 int i1=0, i2=0; // 循环双向链结表 L1 和 L2 的索引。
242
243 initial(&L); // 初始化 L。
244
245 // i1246 // i2247 while (i1248 e1 = getElem(L1, i1); // 取得 L1 的元素。
249 e2 = getElem(L2, i2); // 取得 L2 的元素。
250 // 将 L1 和 L2 较小的元素放到 L 中,并移到下一个元素的位置。
251 if (e1<=e2) {insert(&L, e1); i1++;} else {insert(&L, e2); i2++;}
252 }
253
254 // L1 还有元素,继续复制 L1 的元素。
255 while (i1256
257 // L2 还有元素,继续复制 L2 的元素。
258 while (i2259
260 return L; // 返回合并后的循环双向链结表。
261 }
262
263 // 合自 L1 中移除 (remove) 所有 L2 的元素。
264 // 返回移除后的循环双向链结表。
265 DList remove_list(DList L1, DList L2) {
266 DList L; // 移除后的循环双向链结表。
267 int size1=getSize(L1), size2=getSize(L2); // 循环双向链结表 L1,和 L2 的大小。
268 ElemType e1, e2; // 循环双向链结表 L1 和 L2 的元素。
269 int i1=0, i2=0; // 循环双向链结表 L1 和 L2 的索引。
270
271 initial(&L); // 初始化 L。
272 // i1273 // i2274 while (i1275 e1 = getElem(L1, i1); // 取得 L1 的元素。
276 e2 = getElem(L2, i2); // 取得 L2 的元素。
277 // 若 L1 和 L2 的元素相同,移除 L1 的元素,不储存。
278 if (e1==e2) i1++;
279 // 若 L1 的元素小于 L2 的元素,将 L1 的元素放到 L 中。
280 else if (e1281 // 若 L1 的元素大于 L2 的元素,检查下一个 L2 的元素。
282 else i2++;
283 }
284
285 // L2 已经没有元素;但是,L1 还有元素,继续将 L1 的元素放到 L 中。
286 while (i1287
288 return L; // 返回移除后的循环双向链结表。
289 }
290
291 int main(void) {
292 DList L, L1, L2; // 声明循环双向链结表。
293 int leng1, leng2; // 两个循环双向链结表的长度。 int i; // 循环变量。
294
295 initial(&L1); // 初始化 L1。
296 initial(&L2); // 初始化 L2。
297
298 srand(time(NULL)); // 随机数生成器的种子。
299
300 // 输入循环双向链结表 L1 的元素个数。
301 do {
302 printf("输入循环双向链结表 L1 的元素个数 (1 与 100 (含)之间):");
303 scanf("%d", &leng1);
304 } while (leng1<0 || leng1>100);
305
306 // 输入循环双向链结表 L2 的元素个数。
307 do {
308 printf("输入循环双向链结表 L2 的元素个数 (1 与 100 (含)之间):");
309 scanf("%d", &leng2);
310 } while (leng2<0 || leng2>100);
311 printf("-------------------------------------------\n");
312
313 // 随机产生 L1 的元素。
314 for (i=0; i315 printf("循环双向链结表 L1:\n");
316 printlst(L1); // 打印循环双向链结表 L1。
317
318 // 随机产生 L2 的元素。
319 for (i=0; i320 printf("循环双向链结表 L2:\n");
321 printlst(L2); // 打印循环双向链结表 L2。
322
323 L = merge_list(L1, L2); // 合并 L1 和 L2。
324 printf("合并 L1 和 L2 的循环双向链结表:\n");
325 printlst(L); // 打印合并的循环双向链结表。
326
327 L = remove_list(L1, L2); // 从 L1 移除 L2。
328 printf("从 L1 移除 L2 的循环双向链结表:\n");
329 printlst(L); // 打印移除的循环双向链结表。
330
331 return 0;
332 }

你可能感兴趣的:(第3次学习总结)