DList双向链表
2016-05-25 16:35
423 查看
// // DList.h // Algorithms&Data_structures // // Created by TTc on 15-2-2. // Copyright (c) 2015年 TTc. All rights reserved. // #ifndef __Algorithms_Data_structures__DList__ #define __Algorithms_Data_structures__DList__ #include <stdlib.h> /* define a structure for doubly_linked list */ typedef struct DlistElmt_{ void *data; struct DlistElmt_ *prev; struct DlistElmt_ *next; }DlistElmt; typedef struct Dlist_{ int size; int(*match)(void *key1,void *key2); void(*destroy)(void *data); DlistElmt *head; DlistElmt *tail; }Dlist; /* public Interfaces*/ void dlist_init(Dlist *dlist,void(*destroy)(void *data)); void dlist_destroy(Dlist *dlist); int dlist_ins_next(Dlist *dlist,DlistElmt *element,const void *data); int dlist_ins_prev(Dlist *dlist,DlistElmt *element,const void *data); int dlist_remove(Dlist *dlist,DlistElmt *element, void **data); #define dlist_size(dlist) ((dlist)->size) #define dlist_head(dlist) ((dlist) ->head) #define dlist_tail(dlist) ((dlist) ->tail) #define dlist_is_head(dlist) ((element) ->prev == NULL? 1:0) #define dlist_is_tail(dlist) ((element) ->next == NULL? 1:0) #define dlist_data(dlist) ((dlist) ->data) #define dlist_next(dlist) ((dlist) ->next) #define dlist_prev(dlist) ((dlist) ->prev) #endif /* defined(__Algorithms_Data_structures__DList__) */
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
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
// // DList.c // Algorithms&Data_structures // // Created by TTc on 15-2-2. // Copyright (c) 2015年 TTc. All rights reserved. // #include "dlist.h" #include <stdlib.h> #include <string.h> void dlist_init(Dlist *dlist,void(*destroy)(void *data)){ dlist->size = 0; dlist->head = NULL; dlist->tail = NULL; dlist->destroy = destroy; } void dlist_destroy(Dlist *dlist){ void *data; /*remove each element*/ while (dlist_size(dlist) > 0) { if((dlist_remove(dlist, dlist_tail(dlist), (void**) &data) == 0) && dlist->destroy != NULL){ dlist->destroy(data); } } //清空dlist 结构体 memset(dlist, 0, sizeof(Dlist)); } /*1: 将新元素插入到双链表中 由参数element所指向的元素 之后 2: 同单链表最大的区别在于:除了要管理next 指针外,还必须管理prev指针,以保证链表的 反向链接关系 正确 */ /* 插入成功返回0 ,反之返回 -1 */ /* O(1)*/ int dlist_ins_next(Dlist *dlist,DlistElmt *element,const void *data){ DlistElmt *new_element; //do not allow a NULL unless the list is empty if(element == NULL && dlist_size(dlist) != 0){ return -1; } if((new_element = (DlistElmt*)malloc(sizeof(DlistElmt))) == NULL){ return -1; } //fill the data to the element new_element->data = (void*)data; //如果当前链表为 空表,再插入新元素 的情况 if(dlist_size(dlist) == 0){ new_element->prev = NULL; //链表的头元素 的 前驱指针 指向NULL new_element->next = NULL; //链表的头元素 的 后驱指针 指向NULL(当前情况 链表中只要这一个元素) dlist->head = new_element; dlist->tail = new_element;//链表的尾指针也指向 当前元素 } else { //如果当前链表为 非空表,再插入新元素 的情况 if(element->next == NULL){ dlist->tail = new_element; } else{ //否则 将当前目标元素的 后一位置的元素 的 前驱指针 指向 要插入的元素 element->next->prev = new_element; } new_element->next = element->next; //要插入的元素的 next指针 指向 当前目标元素 后一位置 元素 new_element->prev = element;//要插入元素的 前驱函数 指向 当前目标元素 //如果 当前目标元素的 是当前链表的 尾元素,则 将 链表的尾元素 置为 新插入的元素(把链表的尾指针 tail 指向 要插入的元素) //当前目标元素 的后驱指针 指向 要初入的元素 element->next = new_element; } dlist->size ++; return 0; } /*1: 将新元素插入到双链表中 由参数element所指向的元素 之前 2: 同单链表最大的区别在于:除了要管理next 指针外,还必须管理prev指针,以保证链表的 反向链接关系 正确 3: 若element = NULL, 则双向链表应该为空,否则退出并返-1; 若element != NULL,则需要在element->prev位置插入元素,插入的新元素的数据域为第三个参数data.另外还需要考虑当element为head结点时的情况。 */ /* 插入成功返回0 ,反之返回 -1 */ /* O(1)*/ int dlist_ins_prev(Dlist *dlist,DlistElmt *element,const void *data){ DlistElmt *new_element; //Do not allow a NULL unless the list is empty if(element == NULL && dlist_size(dlist) != 0){ return -1; } if((new_element = (DlistElmt*)malloc(sizeof(DlistElmt))) == NULL){ return -1; } new_element->data = (void*)data; //如果当前链表为 空表,再插入新元素 的情况 if(dlist_size(dlist) == 0){ dlist->head = new_element; dlist->tail = new_element;//链表的尾指针也指向 当前元素 new_element->prev = NULL; //链表的头元素 的 前驱指针 指向NULL new_element->next = NULL;//链表的头元素 的 后驱指针 指向NULL(当前情况 链表中只要这一个元素) } else { new_element->next = element; new_element->prev = element->prev; if(element->prev == NULL){ dlist->head = new_element; } else{ element->prev->next = new_element; } element->prev = new_element; } dlist->size++; return 0; } /* 1: remove操作将指定得元素从 双链表中删除;同单链表最大的区别在于:除了要管理next 指针外,还必须管理prev指针,以保证链表的 反向链接关系 正确 2: 对于双链表还有一个不同于 单链表 的地方在于 :该接口 移除当前指定的元素,而不是移除指定元素之后的那个元素,因为每个元素都有一个指向其前驱的指针 3: element代表 目标节点, 删除操作针对 element节点 */ /* 删除成功返回0 ,反之返回 -1 */ /* O(1)*/ int dlist_remove(Dlist *dlist,DlistElmt *element, void **data){ /* Don't allow a NULL element or removal from an empty dlist */ if(element == NULL || dlist_size(dlist) == 0){ return -1; } *data = element->data; /* handle removal from the head of the dlist */ // 若为 删除节点为 链表的 头节点 if(element == dlist->head){ //将链表头节点的 指针 指向 目标元素的 next指针(目标元素的下一个位置 元素) dlist->head = element->next; //若链表的head指针 指向NULL 则 tail 也必须指向NULL,删除元素后,可能为空表 if(dlist->head == NULL){ dlist->tail = NULL; } else{ //若 head 指针 不为NULL ,则将必须将 目标元素的 前驱指针的 prev指向NULL(其实这个时候 element->next 就是 链表的 第一个元素 ,这个时候 第一元素的 前驱指针必须置为 NULL) element->next->prev = NULL; } } else { /* handle removal from other than the head of the dlist */ //将 当前要删除的元素的 前一个位置的元素 的 next指针 指向 当前元素的 next指针(也就是当前位置元素 的后一个位置的 元素) element->prev->next = element->next; // if(element->next == NULL){ dlist->tail = element->prev; }else{ //将 当前位置要删除元素的 后一个位置的元素 的前驱指针prev 指向 当前元素的前驱指针(也就是当前元素的 前一个位置的元素) element->next->prev = element->prev; } } free(element); dlist->size --; return 0; }
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
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
// // test_dlist_main.c // // // Created by TTc on 16/5/25. // // #include<stdio.h> #include<stdlib.h> #include<string.h> #include "dlist.h" typedef struct Cuboid_ { int length; int width; int height; }Cuboid; Cuboid *cube_instance(const int length, const int width, const int height) { Cuboid *cb_ptr; cb_ptr = (Cuboid *)malloc(sizeof(Cuboid)); if( cb_ptr == NULL ) return NULL; cb_ptr->length = length; cb_ptr->width = width; cb_ptr->height = height; return cb_ptr; } /*destroy */ void destroy(void *data) { free(data); return; } /* main */ int main(int argc, char **argv) { int i; Dlist dlist_exp; DlistElmt *p = NULL; Cuboid *cb1_ptr, *cb2_ptr, *cb3_ptr, *cb4_ptr, *cb5_ptr; Cuboid *cb_ptr; //cb1_ptr ~ cb5_ptr are the data of the 5 elements. cb1_ptr = cube_instance(1,2,3); cb2_ptr = cube_instance(6,10,8); cb3_ptr = cube_instance(5,20,30); cb4_ptr = cube_instance(17,100,25); cb5_ptr = cube_instance(3,6,9); //init the double linked list. dlist_init(&dlist_exp, destroy); //insert the 5 elements into the dlist dlist_ins_next(&dlist_exp, NULL, (void *)cb1_ptr ); //insert data:cb1 p = dlist_head(&dlist_exp); //get the address of the first element dlist_ins_next(&dlist_exp, p , (void *)cb2_ptr ); //insert data:cb2 cb1- cb2 p = dlist_next(p); //pointer to the element containing the data cb2. dlist_ins_prev(&dlist_exp, p, (void *)cb3_ptr ); //insert data:cb3 cb1- cb3- cb2 dlist_ins_prev(&dlist_exp, p, (void *)cb4_ptr ); //insert data:cb4 cb1- cb3- cb4- cb2 p = dlist_prev(p); //pointer to the element conatining the data cb4. dlist_ins_prev(&dlist_exp, p, (void *)cb5_ptr ); //insert data:cb5 cb1- cb3- cb5- cb4- cb2 //now the sequence is: head->cb1->cb3->cb5->cb4->cb2 printf("traverse and print:\n"); p = dlist_head(&dlist_exp); //get the head element; for( i = 0; i < dlist_size(&dlist_exp); i++ ) { cb_ptr = (Cuboid *)dlist_data(p); //get the element's data, every data is a Cuboid's pointer. printf("i = %d: ",i); printf("length = %d, width = %d, height = %d\n", cb_ptr->length, cb_ptr->width, cb_ptr->height); p = dlist_next(p); //pointer to next element; } //we'll remove the third element:that's containing the data of cb5(3,6,9) p = dlist_head(&dlist_exp); p = dlist_next(p); p = dlist_next(p); dlist_remove(&dlist_exp, p, (void **)&cb_ptr); printf("the data of the third element: length = %d, width = %d, height = %d\n", cb_ptr->length, cb_ptr->width, cb_ptr->height); destroy(cb_ptr); //free the memory //now we'll show you the remained elements,the sequence is :(head)cb1->cb3->cb4->cb2(tail) printf("after remove the third elements:\n"); p = dlist_head(&dlist_exp); for(i = 0; i < dlist_size(&dlist_exp); i++ ) { cb_ptr = (Cuboid *)dlist_data(p); printf("i = %d: ",i); printf("length = %d, width = %d, height = %d\n", cb_ptr->length, cb_ptr->width, cb_ptr->height); p = dlist_next(p); } //destroy the double linked list dlist_destroy(&dlist_exp); printf("after destroy the list,its size = %d\n", dlist_size(&dlist_exp)); return 0; }
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
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
相关文章推荐
- 使用windows 窗体应用程序编写简单的阅读器
- 推荐 iOS 网站:
- string.Format格式化
- [RxJS] Filtering operators: take, first, skip
- hibernate的方言
- intellij idea 注册服务器
- FTP命令全集
- Android 自定义View 让内容跟随手指滚动
- springMVC (七) mvc:interceptors
- Python中几个以“__”开头的方法介绍总结
- C#实现FTP基本功能源代码
- Android的拍照功能
- linux--定时任务--crontab
- Failure [INSTALL_FAILED_SHARED_USER_INCOMPATIBLE]
- sqlserver中drop、truncate和delete语句的用法
- 3164 质因数分解
- MYSQL系列-Mysql存储引擎选择
- 轮播图 jquery
- php的错误级别
- GStreamer基础教程08——pipeline的快捷访问