Skip to content

Commit aeb0f2d

Browse files
committed
uploaded double linked list data structure
1 parent 044cdfb commit aeb0f2d

File tree

5 files changed

+493
-3
lines changed

5 files changed

+493
-3
lines changed
Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
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+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*File: DoubleLinkedList.h*/
2+
#ifndef DOUBLE_LINKED_LIST_H
3+
#define DOUBLE_LINKED_LIST_H
4+
5+
typedef struct listnode *Listptr;
6+
7+
#include <stdbool.h>
8+
9+
typedef struct {
10+
Listptr head;
11+
Listptr tail;
12+
} DLlist;
13+
14+
// Compare functions for the different data type
15+
typedef int (*CompareFunc)(void *, void *);
16+
17+
//Functions to destroy values inserted in the hash table
18+
typedef void (*DestroyFunc)(void *);
19+
20+
// Functions to visit nodes printing their data
21+
typedef void (*PrintFunc)(void *);
22+
23+
//Initialize list (and return the pointers of the head and the tail of it)
24+
void DLL_Create(Listptr *head, Listptr *tail);
25+
26+
//returns size of the list
27+
int DLL_Size(Listptr head, Listptr tail);
28+
29+
//Check if list is empty and return 0 if not, otherwise return 1
30+
bool DLL_IsEmpty(Listptr list);
31+
32+
//returns the item of the first node of the list
33+
void *DLL_GetFirst(Listptr head);
34+
35+
//returns the item of the last node of the list
36+
void *DLL_GetLast(Listptr tail);
37+
38+
//returns a pointer to the first node of the list which contains the item "i"
39+
Listptr DLL_GetNode(Listptr head, void *i, CompareFunc compare);
40+
41+
//returns the data of the given node
42+
void *DLL_GetData(Listptr node);
43+
44+
//returns the item of the previous node from the given node
45+
void *DLL_GetPrev(Listptr node);
46+
47+
//returns the item of the next node from the given node
48+
void *DLL_GetNext(Listptr node);
49+
50+
//add a node with data i before the given node
51+
void DLL_AddBefore(Listptr *node, void *i, Listptr *head);
52+
53+
//add a node with data i after the given node
54+
void DLL_AddAfter(Listptr *node, void *i, Listptr *tail);
55+
56+
//add a node with data-item "i" at the beginning of the list
57+
void DLL_AddFirst(Listptr *head, Listptr *tail, void *i);
58+
59+
//add a node with data-item "i" at the end of the list
60+
void DLL_AddLast(Listptr *tail, Listptr *head, void *i);
61+
62+
//removes all the nodes with data "i" from the list
63+
void DLL_Remove(Listptr *head, Listptr *tail, void *i, CompareFunc compare, DestroyFunc destroy);
64+
65+
//print the items of the list from the first one to the last one
66+
void DLL_print(Listptr head, PrintFunc print);
67+
68+
//free the double linked list
69+
void DLL_freelist(Listptr head, Listptr tail, DestroyFunc destroy);
70+
71+
#endif

0 commit comments

Comments
 (0)