Skip to content

Commit f141ae4

Browse files
SahilK-027Panquesito7github-actions[bot]CascadingCascadetjgurwara99
authored
feat: add Circular Doubly Linked List implementation (#1038)
* Create circular_doubly_linked_list.c * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update circular_doubly_linked_list.c Added brief description of library files * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update circular_doubly_linked_list.c Done the all suggested changes. * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update circular_doubly_linked_list.c * updating DIRECTORY.md * updating DIRECTORY.md * updating DIRECTORY.md * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * There was typo while calling delete_first_node ! * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <[email protected]> * updating DIRECTORY.md * Suggested changes are done. Done the suggested changes in functions 1. delete_first_node() 2. delete_last_node() * updating DIRECTORY.md * updating DIRECTORY.md * Worked on Suggested Changes * Suggested changes are done. * Update circular_doubly_linked_list.c Worked on all the suggested changes. Co-Authored-By: David Leal <[email protected]> Co-Authored-By: CascadingCascade <[email protected]> Co-Authored-By: Taj <[email protected]> * updating DIRECTORY.md * updating DIRECTORY.md * Worked on suggested changes for test cases. Check the code's functionality [here](https://leetcode.com/playground/WcRBMWa8) Co-Authored-By: CascadingCascade <[email protected]> * updating DIRECTORY.md * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: CascadingCascade <[email protected]> * Update circular_doubly_linked_list.c Update: Worked on suggested changes. * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: CascadingCascade <[email protected]> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: CascadingCascade <[email protected]> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: CascadingCascade <[email protected]> * Worked on suggested changes. * Minor upgrade. * updating DIRECTORY.md --------- Co-authored-by: David Leal <[email protected]> Co-authored-by: github-actions[bot] <[email protected]> Co-authored-by: CascadingCascade <[email protected]> Co-authored-by: Taj <[email protected]>
1 parent 1cfb88c commit f141ae4

File tree

2 files changed

+305
-0
lines changed

2 files changed

+305
-0
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
* [Min Heap](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/heap/min_heap.c)
8787
* Linked List
8888
* [Ascending Priority Queue](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/ascending_priority_queue.c)
89+
* [Circular Doubly Linked List](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/circular_doubly_linked_list.c)
8990
* [Circular Linked List](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/circular_linked_list.c)
9091
* [Doubly Linked List](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/doubly_linked_list.c)
9192
* [Merge Linked Lists](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/merge_linked_lists.c)
Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
/**
2+
* @file
3+
*
4+
* @details
5+
* Circular [Doubly Linked
6+
* List](https://en.wikipedia.org/wiki/Doubly_linked_list) combines the
7+
* properties of a doubly linked list and a circular linked list in which two
8+
* consecutive elements are linked or connected by the previous. Next, the
9+
* pointer and the last node point to the first node via the next pointer, and
10+
* the first node points to the last node via the previous pointer.
11+
*
12+
* In this implementation, functions to insert at the head, insert at the last
13+
* index, delete the first node, delete the last node, display list, and get
14+
* list size functions are coded.
15+
*
16+
* @author [Sahil Kandhare](https://github.com/SahilK-027)
17+
*
18+
*/
19+
20+
#include <assert.h> /// to verify assumptions made by the program and print a diagnostic message if this assumption is false.
21+
#include <inttypes.h> /// to provide a set of integer types with universally consistent definitions that are operating system-independent
22+
#include <stdio.h> /// for IO operations
23+
#include <stdlib.h> /// for including functions involving memory allocation such as `malloc`
24+
25+
/**
26+
* @brief Circular Doubly linked list struct
27+
*/
28+
typedef struct node
29+
{
30+
struct node *prev, *next; ///< List pointers
31+
uint64_t value; ///< Data stored on each node
32+
} ListNode;
33+
34+
/**
35+
* @brief Create a list node
36+
* @param data the data that the node initialises with
37+
* @return ListNode* pointer to the newly created list node
38+
*/
39+
ListNode *create_node(uint64_t data)
40+
{
41+
ListNode *new_list = (ListNode *)malloc(sizeof(ListNode));
42+
new_list->value = data;
43+
new_list->next = new_list;
44+
new_list->prev = new_list;
45+
return new_list;
46+
}
47+
48+
/**
49+
* @brief Insert a node at start of list
50+
* @param head start pointer of list
51+
* @param data the data that the node initialises with
52+
* @return ListNode* pointer to the newly created list node
53+
* inserted at the head
54+
*/
55+
ListNode *insert_at_head(ListNode *head, uint64_t data)
56+
{
57+
if (head == NULL)
58+
{
59+
head = create_node(data);
60+
return head;
61+
}
62+
else
63+
{
64+
ListNode *temp;
65+
ListNode *new_node = create_node(data);
66+
temp = head->prev;
67+
new_node->next = head;
68+
head->prev = new_node;
69+
new_node->prev = temp;
70+
temp->next = new_node;
71+
head = new_node;
72+
return head;
73+
}
74+
}
75+
76+
/**
77+
* @brief Insert a node at end of list
78+
*
79+
* @param head start pointer of list
80+
* @param data the data that the node initialises with
81+
* @return ListNode* pointer to the newly added list node that was
82+
* inserted at the head of list.
83+
*/
84+
ListNode *insert_at_tail(ListNode *head, uint64_t data)
85+
{
86+
if (head == NULL)
87+
{
88+
head = create_node(data);
89+
return head;
90+
}
91+
else
92+
{
93+
ListNode *temp1, *temp2;
94+
ListNode *new_node = create_node(data);
95+
temp1 = head;
96+
temp2 = head->prev;
97+
new_node->prev = temp2;
98+
new_node->next = temp1;
99+
temp1->prev = new_node;
100+
temp2->next = new_node;
101+
return head;
102+
}
103+
}
104+
105+
/**
106+
* @brief Function for deletion of the first node in list
107+
*
108+
* @param head start pointer of list
109+
* @return ListNode* pointer to the list node after deleting first node
110+
*/
111+
ListNode *delete_from_head(ListNode *head)
112+
{
113+
if (head == NULL)
114+
{
115+
printf("The list is empty\n");
116+
return head;
117+
}
118+
ListNode *temp1, *temp2;
119+
temp1 = head;
120+
temp2 = temp1->prev;
121+
if (temp1 == temp2)
122+
{
123+
free(temp2);
124+
head = NULL;
125+
return head;
126+
}
127+
temp2->next = temp1->next;
128+
(temp1->next)->prev = temp2;
129+
head = temp1->next;
130+
free(temp1);
131+
return head;
132+
}
133+
134+
/**
135+
* @brief Function for deletion of the last node in list
136+
*
137+
* @param head start pointer of list
138+
* @return ListNode* pointer to the list node after deleting first node
139+
*/
140+
ListNode *delete_from_tail(ListNode *head)
141+
{
142+
if (head == NULL)
143+
{
144+
printf("The list is empty\n");
145+
return head;
146+
}
147+
148+
ListNode *temp1, *temp2;
149+
temp1 = head;
150+
temp2 = temp1->prev;
151+
if (temp1 == temp2)
152+
{
153+
free(temp2);
154+
head = NULL;
155+
return head;
156+
}
157+
(temp2->prev)->next = temp1;
158+
temp1->prev = temp2->prev;
159+
free(temp2);
160+
return head;
161+
}
162+
163+
/**
164+
* @brief The function that will return current size of list
165+
*
166+
* @param head start pointer of list
167+
* @return int size of list
168+
*/
169+
int getsize(ListNode *head)
170+
{
171+
if (!head)
172+
{
173+
return 0;
174+
}
175+
int size = 1;
176+
ListNode *temp = head->next;
177+
while (temp != head)
178+
{
179+
temp = temp->next;
180+
size++;
181+
}
182+
return size;
183+
}
184+
185+
/**
186+
* @brief Display list function
187+
* @param head start pointer of list
188+
* @returns void
189+
*/
190+
191+
void display_list(ListNode *head)
192+
{
193+
printf("\nContents of your linked list: ");
194+
ListNode *temp;
195+
temp = head;
196+
if (head != NULL)
197+
{
198+
while (temp->next != head)
199+
{
200+
printf("%" PRIu64 " <-> ", temp->value);
201+
temp = temp->next;
202+
}
203+
if (temp->next == head)
204+
{
205+
printf("%" PRIu64, temp->value);
206+
}
207+
}
208+
else
209+
{
210+
printf("The list is empty");
211+
}
212+
printf("\n");
213+
}
214+
215+
/**
216+
* @brief access the list by index
217+
* @param list pointer to the target list
218+
* @param index access location
219+
* @returns the value at the specified index,
220+
* wrapping around if the index is larger than the size of the target
221+
* list
222+
*/
223+
uint64_t get(ListNode *list, const int index)
224+
{
225+
if (list == NULL || index < 0)
226+
{
227+
exit(EXIT_FAILURE);
228+
}
229+
ListNode *temp = list;
230+
for (int i = 0; i < index; ++i)
231+
{
232+
temp = temp->next;
233+
}
234+
return temp->value;
235+
}
236+
237+
/**
238+
* @brief Self-test implementations
239+
* @returns void
240+
*/
241+
static void test()
242+
{
243+
ListNode *testList = NULL;
244+
unsigned int array[] = {2, 3, 4, 5, 6};
245+
246+
assert(getsize(testList) == 0);
247+
248+
printf("Testing inserting elements:\n");
249+
for (int i = 0; i < 5; ++i)
250+
{
251+
display_list(testList);
252+
testList = insert_at_head(testList, array[i]);
253+
assert(testList->value == array[i]);
254+
assert(getsize(testList) == i + 1);
255+
}
256+
257+
printf("\nTesting removing elements:\n");
258+
for (int i = 4; i > -1; --i)
259+
{
260+
display_list(testList);
261+
assert(testList->value == array[i]);
262+
testList = delete_from_head(testList);
263+
assert(getsize(testList) == i);
264+
}
265+
266+
printf("\nTesting inserting at tail:\n");
267+
for (int i = 0; i < 5; ++i)
268+
{
269+
display_list(testList);
270+
testList = insert_at_tail(testList, array[i]);
271+
assert(get(testList, i) == array[i]);
272+
assert(getsize(testList) == i + 1);
273+
}
274+
275+
printf("\nTesting removing from tail:\n");
276+
for (int i = 4; i > -1; --i)
277+
{
278+
display_list(testList);
279+
testList = delete_from_tail(testList);
280+
assert(getsize(testList) == i);
281+
// If list is not empty, assert that accessing the just removed element
282+
// will wrap around to the list head
283+
if (testList != NULL)
284+
{
285+
assert(get(testList, i) == testList->value);
286+
}
287+
else
288+
{
289+
// If the list is empty, assert that the elements were removed after
290+
// the correct number of iterations
291+
assert(i == 0);
292+
}
293+
}
294+
}
295+
296+
/**
297+
* @brief Main function
298+
* @returns 0 on exit
299+
*/
300+
int main()
301+
{
302+
test(); // run self-test implementations
303+
return 0;
304+
}

0 commit comments

Comments
 (0)