//
// 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