1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include "DoubleLinkedList.h"
4
+
5
+
6
+ struct listnode {
7
+ void * data ;
8
+ Listptr next ;
9
+ Listptr prev ;
10
+ };
11
+
12
+ //Initialize list (and return the pointers of the head and the tail of it)
13
+ void DLL_Create (Listptr * head , Listptr * tail ) {
14
+ * head = * tail = NULL ;
15
+ }
16
+
17
+
18
+ //returns size of the list
19
+ int DLL_Size (Listptr head , Listptr tail ) {
20
+ int count = 0 ;
21
+ while ((head != tail ) && (head -> prev != tail )) { /*Careful! The tail and the head can meet up either in the middle element (if the number of nodes is odd), so we should count it afterwards, or never meet up because when the one increases the other decreases*/
22
+ count += 2 ;
23
+ head = head -> next ;
24
+ tail = tail -> prev ;
25
+ }
26
+ if ((head == tail ) && (head != NULL )) { /*We have not counted this single element*/
27
+ count ++ ;
28
+ }
29
+ return count ;
30
+ }
31
+
32
+
33
+ //Check if list is empty and return 0 if not, otherwise return 1
34
+ bool DLL_IsEmpty (Listptr list ) {
35
+ return list == NULL ;
36
+ }
37
+
38
+
39
+ //returns the item of the first node of the list
40
+ void * DLL_GetFirst (Listptr head ) {
41
+ if (DLL_IsEmpty (head )) {
42
+ printf ("List is empty. The is no element inside the list.\n" );
43
+ return 0 ;
44
+ }
45
+ return head -> data ;
46
+ }
47
+
48
+
49
+ //returns the item of the last node of the list
50
+ void * DLL_GetLast (Listptr tail ) {
51
+ if (DLL_IsEmpty (tail )) {
52
+ printf ("List is empty. The is no element inside the list.\n" );
53
+ return 0 ;
54
+ }
55
+ return tail -> data ;
56
+ }
57
+
58
+
59
+ //returns a pointer to the first node of the list which contains the item "i"
60
+ Listptr DLL_GetNode (Listptr head , void * i , CompareFunc compare ) {
61
+ while (head != NULL ) { /*Cross the list from the beginning*/
62
+ if (compare (head -> data , i ) == 0 )
63
+ return head ; /*Found the first element with data i :) , return it*/
64
+ head = head -> next ;
65
+ }
66
+ return NULL ; /*Did not found it :(*/
67
+ }
68
+
69
+
70
+ //returns the data of the given node
71
+ void * DLL_GetData (Listptr node ) {
72
+ return node -> data ;
73
+ }
74
+
75
+
76
+
77
+ //returns the item of the previous node from the given node
78
+ void * DLL_GetPrev (Listptr node ) {
79
+ if (node -> prev == NULL ) {
80
+ printf ("No previous element of the given node.\n" );
81
+ return 0 ;
82
+ }
83
+ return (node -> prev )-> data ;
84
+ }
85
+
86
+
87
+ //returns the item of the next node from the given node
88
+ void * DLL_GetNext (Listptr node ) {
89
+ if (node -> next == NULL ) {
90
+ printf ("No next element of the given node.\n" );
91
+ return 0 ;
92
+ }
93
+ return (node -> next )-> data ;
94
+ }
95
+
96
+
97
+ //add a node with data i before the given node
98
+ void DLL_AddBefore (Listptr * node , void * i , Listptr * head ) {
99
+ if (* node == NULL ) { /*The given node is not appropriate*/
100
+ fprintf (stderr , "Fail to add the node" );
101
+ return ;
102
+ }
103
+ Listptr new_node = malloc (sizeof (struct listnode ));
104
+ if (new_node == NULL ) { /*The given node is not appropriate*/
105
+ fprintf (stderr , "Error while allocating memory\n" );
106
+ return ;
107
+ }
108
+ new_node -> data = i ;
109
+ new_node -> next = * node ;
110
+ new_node -> prev = (* node )-> prev ;
111
+ if ((* node )-> prev != NULL ) { /*Only if node is not the head of the list, we will deal with the previous node's next pointer*/
112
+ (((* node )-> prev )-> next ) = new_node ; /*Linking the new node with its previous node*/
113
+ }
114
+ (* node )-> prev = new_node ; /*Linking the current node with the new node*/
115
+ if (* node == * head ) { /*Adding before current head. The head must still point to the first element of the list so it changes*/
116
+ * head = new_node ;
117
+ }
118
+ }
119
+
120
+
121
+ //add a node with data i after the given node
122
+ void DLL_AddAfter (Listptr * node , void * i , Listptr * tail ) {
123
+ if (* node == NULL ) { /*The given node is not appropriate*/
124
+ fprintf (stderr , "Fail to add the node. The given node does not exists.\n" );
125
+ return ;
126
+ }
127
+ Listptr new_node = malloc (sizeof (struct listnode ));
128
+ if (new_node == NULL ) { /*The given node is not appropriate*/
129
+ fprintf (stderr , "Error while allocating memory\n" );
130
+ return ;
131
+ }
132
+ new_node -> data = i ;
133
+ new_node -> prev = * node ; /*Link the new node with the current node*/
134
+ new_node -> next = (* node )-> next ;
135
+ if ((* node )-> next != NULL ) { /*Only if node is not the tail of the list, we will deal with the previous node's next pointer*/
136
+ (((* node )-> next )-> prev = new_node );
137
+ }
138
+ (* node )-> next = new_node ;
139
+ if (* node == * tail ) { /*If an element is added before the current tail, the tail of the list should change*/
140
+ * tail = new_node ;
141
+ }
142
+ }
143
+
144
+
145
+ //add a node with data-item "i" at the beginning of the list
146
+ void DLL_AddFirst (Listptr * head , Listptr * tail , void * i ) {
147
+ Listptr templist = * head ; /*Save the head of the list*/
148
+ * head = malloc (sizeof (struct listnode ));
149
+ if (* head == NULL ) { /*The given node is not appropriate*/
150
+ fprintf (stderr , "Error while allocating memory\n" );
151
+ return ;
152
+ }
153
+ (* head )-> data = i ;
154
+ (* head )-> prev = NULL ;
155
+ (* head )-> next = templist ; /*Link the new head with the other nodes of the list*/
156
+ if (templist != NULL ) {
157
+ templist -> prev = * head ;
158
+ }
159
+ else {
160
+ * tail = * head ;
161
+ }
162
+ }
163
+
164
+
165
+ //add a node with data-item "i" at the end of the list
166
+ void DLL_AddLast (Listptr * tail , Listptr * head , void * i ) {
167
+ Listptr templist = * tail ;
168
+ * tail = malloc (sizeof (struct listnode ));
169
+ if (* tail == NULL ) {
170
+ fprintf (stderr , "Error while allocating memory\n" );
171
+ return ;
172
+ }
173
+ (* tail )-> data = i ;
174
+ (* tail )-> next = NULL ;
175
+ (* tail )-> prev = templist ; /*Link the new tail with all the other elements of the list*/
176
+ if (templist != NULL ) {
177
+ templist -> next = * tail ;
178
+ }
179
+ else {
180
+ * head = * tail ;
181
+ }
182
+ }
183
+
184
+ //delete given node from the double linked list
185
+ static inline void DLL_delete_node (Listptr node , DestroyFunc destroy ) {
186
+ if (node -> prev ) {
187
+ node -> prev -> next = node -> next ; /* update the previous node's next pointer */
188
+ }
189
+ if (node -> next ) {
190
+ node -> next -> prev = node -> prev ; /* update the next node's previous pointer */
191
+ }
192
+ if (destroy ) {
193
+ destroy (node -> data );
194
+ }
195
+ free (node ); /* free the memory allocated for the node */
196
+ }
197
+
198
+
199
+ //removes all the nodes with data "i" from the list
200
+ void DLL_Remove (Listptr * head , Listptr * tail , void * i , CompareFunc compare , DestroyFunc destroy ) {
201
+ Listptr tempnode ;
202
+ bool onlyonenode = true;
203
+ while ((* head != * tail ) && (* head != NULL ) && ((* head )-> prev != * tail )) {
204
+ onlyonenode = false;
205
+ if ((* head )-> data == i ) {
206
+ if ((* head )-> prev == NULL ) {
207
+ tempnode = * head ;
208
+ * head = (* head )-> next ;
209
+ tempnode -> next -> prev = NULL ; /*update the next node's previous pointer*/
210
+ if (destroy )
211
+ destroy (tempnode -> data );
212
+ free (tempnode ); /*free the memory allocated for the node*/
213
+ }
214
+ else {
215
+ tempnode = * head ;
216
+ head = & ((* head )-> next );
217
+ DLL_delete_node (tempnode , destroy );
218
+ }
219
+ }
220
+ else {
221
+ head = & ((* head )-> next );
222
+ }
223
+ if ((* tail )-> data == i ) {
224
+ if ((* tail )-> next == NULL ) {
225
+ tempnode = * tail ;
226
+ * tail = (* tail )-> prev ;
227
+ tempnode -> prev -> next = NULL ; /*update the previous node's next pointer*/
228
+ if (destroy )
229
+ destroy (tempnode -> data );
230
+ free (tempnode ); /*free the memory allocated for the node*/
231
+ }
232
+ else {
233
+ tempnode = * tail ;
234
+ tail = & ((* tail )-> prev );
235
+ DLL_delete_node (tempnode , destroy );
236
+ }
237
+ }
238
+ else {
239
+ tail = & ((* tail )-> prev );
240
+ }
241
+ }
242
+ if (* head == * tail ) {
243
+ if ((* head )-> data == i ) {
244
+ if (onlyonenode ) {
245
+ if (destroy )
246
+ destroy ((* head )-> data );
247
+ free (* head );
248
+ * head = * tail = NULL ;
249
+ }
250
+ else {
251
+ tempnode = * head ;
252
+ head = & ((* head )-> next );
253
+ DLL_delete_node (tempnode , destroy );
254
+ }
255
+ }
256
+ }
257
+ }
258
+
259
+
260
+ //print the items of the list from the first one to the last one
261
+ void DLL_print (Listptr head , PrintFunc print ) {
262
+ if (DLL_IsEmpty (head )) {
263
+ printf ("List is empty\n" );
264
+ return ;
265
+ }
266
+ printf ("[" );
267
+ while (head != NULL ) {
268
+ print (head -> data );
269
+ head = head -> next ;
270
+ if (head != NULL )
271
+ printf (", " );
272
+ }
273
+ printf ("]\n" );
274
+ }
275
+
276
+
277
+ //free the double linked list
278
+ void DLL_freelist (Listptr head , Listptr tail , DestroyFunc destroy ) {
279
+ while ((head != tail ) && (head -> prev != tail )) {
280
+ Listptr temp = head ;
281
+ head = head -> next ;
282
+ if (destroy )
283
+ destroy (temp -> data );
284
+ free (temp );
285
+ temp = tail ;
286
+ tail = tail -> prev ;
287
+ if (destroy )
288
+ destroy (temp -> data );
289
+ free (temp );
290
+ }
291
+ }
0 commit comments