forked from fw876/helloworld
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlist.c
370 lines (313 loc) · 11.1 KB
/
list.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
#include "list.h"
/// 文件:list_impl.c
/// 功能:实现链表的基本操作
/// 作者:bluewind
/// 完成时间:2011.5.29
/// 修改时间:2011.5.31, 2011.7.2
/// 修改备注:在头节点处添加一个空节点,可以优化添加、删除节点代码
/// 再次修改,链表增加节点数据data_size,限制数据大小,修改了
/// 添加复制数据代码,修正重复添加节点后释放节点的Bug,添加了前
/// 插、排序和遍历功能,7.3 添加tail尾指针,改进后插法性能,并改名
/// --------------------------------------------------------------
void swap_data(Node n1, Node n2);
/// --------------------------------------------------------------
// 函数名:list_init
// 功能: 链表初始化
// 参数: 无
// 返回值:已初始化链表指针
// 备注: 链表本身动态分配,由list_destroy函数管理释放
/// --------------------------------------------------------------
List list_init(unsigned int data_size)
{
List list = (List) malloc(sizeof(struct clist));
if(list != NULL) //内存分配成功
{
list->head = (Node) malloc(sizeof(node)); //为头节点分配内存
if(list->head) //内存分配成功
{
list->head->data = NULL; //初始化头节点
list->head->next = NULL;
list->data_size = data_size;
list->tail = list->head;
list->size = 0;
list->add_back = list_add_back; //初始化成员函数
list->add_front = list_add_front;
list->delete_node = list_delete_node;
list->delete_at = list_delete_at;
list->modify_at = list_modify_at;
list->have_same = list_have_same;
list->have_same_cmp = list_have_same_cmp;
list->foreach = list_foreach;
list->clear = list_clear;
list->sort = list_sort;
list->destroy = list_destroy;
}
}
return list;
}
/// --------------------------------------------------------------
// 函数名:list_add_back
// 功能: 添加链表结点 (后插法)
// 参数: l--链表指针,data--链表数据指针,可为任意类型
// 返回值:int型,为1表示添加成功,为0表示添加失败
// 备注: 如果链表本身为空或是分配节点内存失败,将返回0
/// --------------------------------------------------------------
int list_add_back(List l, void *data)
{
Node new_node = (Node) malloc(sizeof(node));
if(l != NULL && new_node != NULL) //链表本身不为空,且内存申请成功
{
new_node->data = malloc(l->data_size);
memcpy(new_node->data, data, l->data_size);
new_node->next = NULL;
l->tail->next = new_node; //添加节点
l->tail = new_node; //记录尾节点位置
l->size ++; //链表元素总数加1
return 1;
}
return 0;
}
/// --------------------------------------------------------------
// 函数名:list_add_front
// 功能: 添加链表结点 (前插法)
// 参数: l--链表指针,data--链表数据指针,可为任意类型
// 返回值:int型,为1表示添加成功,为0表示添加失败
// 备注: 如果链表本身为空或是分配节点内存失败,将返回0
/// --------------------------------------------------------------
int list_add_front(List l, void *data)
{
Node new_node = (Node) malloc(sizeof(node));
if(l != NULL && new_node != NULL)
{
new_node->data = malloc(l->data_size);
memcpy(new_node->data, data, l->data_size);
new_node->next = l->head->next;
l->head->next = new_node;
if(!l->size) //记录尾指针位置
l->tail = new_node;
l->size ++;
return 1;
}
return 0;
}
/// --------------------------------------------------------------
// 函数名:list_delete_node
// 功能:删除链表结点
// 参数:l--链表指针,data--链表数据指针,可为任意类型
// *pfunc为指向一个数据类型比较的函数指针
// 返回值:int型,为1表示删除成功,为0表示没有找到匹配数据
// 备注:*pfunc函数接口参数ndata为节点数据,data为比较数据,返回为真表示匹配数据
/// --------------------------------------------------------------
int list_delete_node(List l, void *data, int (*pfunc)(void *ndata, void *data))
{
if(l != NULL)
{
Node prev = l->head; //前一个节点
Node curr = l->head->next; //当前节点
while(curr != NULL)
{
if(pfunc(curr->data, data)) //如果找到匹配数据
{
if(curr == l->tail) //如果是删除尾节点
l->tail = prev;
prev->next = prev->next->next; //修改前节点next指针指向下下个节点
free(curr->data); //释放节点数据
free(curr); //释放节点
l->size--; //链表元素总数减1
return 1; //返回真值
}
prev = prev->next; //没有找到匹配时移动前节点和当前节点
curr = curr->next;
}
}
return 0; //没有找到匹配数据
}
/// --------------------------------------------------------------
// 函数名:list_delete_at
// 功能: 修改链表节点元素值
// 参数: l--链表指针,index--索引值, 范围(0 -- size-1)
// 返回值:int型,为1表示删除成功,为0表示删除失败
// 备注: 如果链表本身为空或是index为非法值,将返回0
/// --------------------------------------------------------------
int list_delete_at(List l, unsigned int index)
{
unsigned int cindex = 0;
if(l != NULL && index >= 0 && index < l->size)
{
Node prev = l->head; //前一个节点
Node curr = l->head->next; //当前节点
while(cindex != index)
{
prev = prev->next;
curr = curr->next;
cindex ++;
}
if(index == (l->size) - 1)
l->tail = prev;
prev->next = prev->next->next;
free(curr->data);
free(curr);
l->size --;
return 1;
}
return 0;
}
/// --------------------------------------------------------------
// 函数名:list_modify_at
// 功能: 修改链表节点元素值
// 参数: l--链表指针,index--索引值, 范围(0 -- size-1)
// data--链表数据指针
// 返回值:int型,为1表示修改成功,为0表示修改失败
// 备注: 如果链表本身为空或是index为非法值,将返回0
/// --------------------------------------------------------------
int list_modify_at(List l, unsigned int index, void *new_data)
{
unsigned int cindex = 0;
if(l != NULL && index >= 0 && index < l->size ) //非空链表,并且index值合法
{
Node curr = l->head->next;
while(cindex != index)
{
curr = curr->next;
cindex ++;
}
memcpy(curr->data, new_data, l->data_size);
return 1;
}
return 0;
}
/// --------------------------------------------------------------
// 函数名:list_sort
// 功能: 链表排序
// 参数: l--链表指针,*pfunc为指向一个数据类型比较的函数指针
// 返回值:无
// 备注: 使用简单选择排序法,相比冒泡法每次交换,效率高一点
/// --------------------------------------------------------------
void list_sort(List l, compare pfunc)
{
if(l != NULL)
{
Node min, icurr, jcurr;
icurr = l->head->next;
while(icurr)
{
min = icurr; //记录最小值
jcurr = icurr->next; //内循环指向下一个节点
while(jcurr)
{
if(pfunc(min->data, jcurr->data)) //如果找到n+1到最后一个元素最小值
min = jcurr; //记录下最小值的位置
jcurr = jcurr->next;
}
if(min != icurr) //当最小值位置和n+1元素位置不相同时
{
swap_data(min, icurr); //才进行交换,减少交换次数
}
icurr = icurr->next;
}
}
}
void swap_data(Node n1, Node n2)
{
void *temp;
temp = n2->data;
n2->data = n1->data;
n1->data = temp;
}
int list_have_same(List l, void *data, int (*pfunc)(void *ndata, void *data))
{
if(l != NULL)
{
Node curr;
for(curr = l->head->next; curr != NULL; curr = curr->next)
{
if(pfunc(curr->data, data))
{
return 1;
}
}
}
return 0;
}
int list_have_same_cmp(List l, void *data)
{
if(l != NULL)
{
Node curr;
for(curr = l->head->next; curr != NULL; curr = curr->next)
{
if(memcmp(curr->data, data, l->data_size))
{
return 1;
}
}
}
return 0;
}
/// --------------------------------------------------------------
// 函数名:list_foreach
// 功能: 遍历链表元素
// 参数: l--链表指针,doit为指向一个处理数据的函数指针
// 返回值:无
// 备注: doit申明为void (*dofunc)(void *ndata)原型
/// --------------------------------------------------------------
void list_foreach(List l, dofunc doit)
{
if(l != NULL)
{
Node curr;
for(curr = l->head->next; curr != NULL; curr = curr->next)
{
doit(curr->data);
}
}
}
/// --------------------------------------------------------------
// 函数名:list_clear
// 功能: 清空链表元素
// 参数: l--链表指针
// 返回值:无
// 备注: 没有使用先Destroy再Init链表的办法,直接实现
/// --------------------------------------------------------------
void list_clear(List l)
{
if(l != NULL)
{
Node temp;
Node curr = l->head->next;
while(curr != NULL)
{
temp = curr->next;
free(curr->data); //释放节点和数据
free(curr);
curr = temp;
}
l->size = 0; //重置链表数据
l->head->next = NULL;
l->tail = l->head;
}
}
/// --------------------------------------------------------------
// 函数名:list_destroy
// 功能: 释放链表
// 参数: l--链表指针
// 返回值:空链表指针
/// --------------------------------------------------------------
List list_destroy(List l)
{
if(l != NULL)
{
Node temp;
while(l->head)
{
temp = l->head->next;
if(l->head->data != NULL) //如果是头节点就不释放数据空间
free(l->head->data); //先释放节点数据(但是节点数据里也有指针?)
free(l->head); //再释放节点
l->head = temp;
}
free(l); //释放链表本身占用空间
l = NULL;
}
return l;
}