mirror of
https://github.com/TheAlgorithms/C
synced 2024-11-21 21:11:57 +03:00
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 <halfpacho@gmail.com> * 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 <halfpacho@gmail.com> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <halfpacho@gmail.com> * 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 <halfpacho@gmail.com> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <halfpacho@gmail.com> * 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 <halfpacho@gmail.com> * There was typo while calling delete_first_node ! * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <halfpacho@gmail.com> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: David Leal <halfpacho@gmail.com> * 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 <halfpacho@gmail.com> Co-Authored-By: CascadingCascade <122662061+CascadingCascade@users.noreply.github.com> Co-Authored-By: Taj <tjgurwara99@users.noreply.github.com> * 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 <122662061+CascadingCascade@users.noreply.github.com> * updating DIRECTORY.md * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: CascadingCascade <122662061+CascadingCascade@users.noreply.github.com> * 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 <122662061+CascadingCascade@users.noreply.github.com> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: CascadingCascade <122662061+CascadingCascade@users.noreply.github.com> * Update data_structures/linked_list/circular_doubly_linked_list.c Co-authored-by: CascadingCascade <122662061+CascadingCascade@users.noreply.github.com> * Worked on suggested changes. * Minor upgrade. * updating DIRECTORY.md --------- Co-authored-by: David Leal <halfpacho@gmail.com> Co-authored-by: github-actions[bot] <github-actions@users.noreply.github.com> Co-authored-by: CascadingCascade <122662061+CascadingCascade@users.noreply.github.com> Co-authored-by: Taj <tjgurwara99@users.noreply.github.com>
This commit is contained in:
parent
1cfb88c5eb
commit
f141ae4166
@ -86,6 +86,7 @@
|
||||
* [Min Heap](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/heap/min_heap.c)
|
||||
* Linked List
|
||||
* [Ascending Priority Queue](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/ascending_priority_queue.c)
|
||||
* [Circular Doubly Linked List](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/circular_doubly_linked_list.c)
|
||||
* [Circular Linked List](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/circular_linked_list.c)
|
||||
* [Doubly Linked List](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/doubly_linked_list.c)
|
||||
* [Merge Linked Lists](https://github.com/TheAlgorithms/C/blob/HEAD/data_structures/linked_list/merge_linked_lists.c)
|
||||
|
304
data_structures/linked_list/circular_doubly_linked_list.c
Normal file
304
data_structures/linked_list/circular_doubly_linked_list.c
Normal file
@ -0,0 +1,304 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @details
|
||||
* Circular [Doubly Linked
|
||||
* List](https://en.wikipedia.org/wiki/Doubly_linked_list) combines the
|
||||
* properties of a doubly linked list and a circular linked list in which two
|
||||
* consecutive elements are linked or connected by the previous. Next, the
|
||||
* pointer and the last node point to the first node via the next pointer, and
|
||||
* the first node points to the last node via the previous pointer.
|
||||
*
|
||||
* In this implementation, functions to insert at the head, insert at the last
|
||||
* index, delete the first node, delete the last node, display list, and get
|
||||
* list size functions are coded.
|
||||
*
|
||||
* @author [Sahil Kandhare](https://github.com/SahilK-027)
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assert.h> /// to verify assumptions made by the program and print a diagnostic message if this assumption is false.
|
||||
#include <inttypes.h> /// to provide a set of integer types with universally consistent definitions that are operating system-independent
|
||||
#include <stdio.h> /// for IO operations
|
||||
#include <stdlib.h> /// for including functions involving memory allocation such as `malloc`
|
||||
|
||||
/**
|
||||
* @brief Circular Doubly linked list struct
|
||||
*/
|
||||
typedef struct node
|
||||
{
|
||||
struct node *prev, *next; ///< List pointers
|
||||
uint64_t value; ///< Data stored on each node
|
||||
} ListNode;
|
||||
|
||||
/**
|
||||
* @brief Create a list node
|
||||
* @param data the data that the node initialises with
|
||||
* @return ListNode* pointer to the newly created list node
|
||||
*/
|
||||
ListNode *create_node(uint64_t data)
|
||||
{
|
||||
ListNode *new_list = (ListNode *)malloc(sizeof(ListNode));
|
||||
new_list->value = data;
|
||||
new_list->next = new_list;
|
||||
new_list->prev = new_list;
|
||||
return new_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert a node at start of list
|
||||
* @param head start pointer of list
|
||||
* @param data the data that the node initialises with
|
||||
* @return ListNode* pointer to the newly created list node
|
||||
* inserted at the head
|
||||
*/
|
||||
ListNode *insert_at_head(ListNode *head, uint64_t data)
|
||||
{
|
||||
if (head == NULL)
|
||||
{
|
||||
head = create_node(data);
|
||||
return head;
|
||||
}
|
||||
else
|
||||
{
|
||||
ListNode *temp;
|
||||
ListNode *new_node = create_node(data);
|
||||
temp = head->prev;
|
||||
new_node->next = head;
|
||||
head->prev = new_node;
|
||||
new_node->prev = temp;
|
||||
temp->next = new_node;
|
||||
head = new_node;
|
||||
return head;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert a node at end of list
|
||||
*
|
||||
* @param head start pointer of list
|
||||
* @param data the data that the node initialises with
|
||||
* @return ListNode* pointer to the newly added list node that was
|
||||
* inserted at the head of list.
|
||||
*/
|
||||
ListNode *insert_at_tail(ListNode *head, uint64_t data)
|
||||
{
|
||||
if (head == NULL)
|
||||
{
|
||||
head = create_node(data);
|
||||
return head;
|
||||
}
|
||||
else
|
||||
{
|
||||
ListNode *temp1, *temp2;
|
||||
ListNode *new_node = create_node(data);
|
||||
temp1 = head;
|
||||
temp2 = head->prev;
|
||||
new_node->prev = temp2;
|
||||
new_node->next = temp1;
|
||||
temp1->prev = new_node;
|
||||
temp2->next = new_node;
|
||||
return head;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for deletion of the first node in list
|
||||
*
|
||||
* @param head start pointer of list
|
||||
* @return ListNode* pointer to the list node after deleting first node
|
||||
*/
|
||||
ListNode *delete_from_head(ListNode *head)
|
||||
{
|
||||
if (head == NULL)
|
||||
{
|
||||
printf("The list is empty\n");
|
||||
return head;
|
||||
}
|
||||
ListNode *temp1, *temp2;
|
||||
temp1 = head;
|
||||
temp2 = temp1->prev;
|
||||
if (temp1 == temp2)
|
||||
{
|
||||
free(temp2);
|
||||
head = NULL;
|
||||
return head;
|
||||
}
|
||||
temp2->next = temp1->next;
|
||||
(temp1->next)->prev = temp2;
|
||||
head = temp1->next;
|
||||
free(temp1);
|
||||
return head;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function for deletion of the last node in list
|
||||
*
|
||||
* @param head start pointer of list
|
||||
* @return ListNode* pointer to the list node after deleting first node
|
||||
*/
|
||||
ListNode *delete_from_tail(ListNode *head)
|
||||
{
|
||||
if (head == NULL)
|
||||
{
|
||||
printf("The list is empty\n");
|
||||
return head;
|
||||
}
|
||||
|
||||
ListNode *temp1, *temp2;
|
||||
temp1 = head;
|
||||
temp2 = temp1->prev;
|
||||
if (temp1 == temp2)
|
||||
{
|
||||
free(temp2);
|
||||
head = NULL;
|
||||
return head;
|
||||
}
|
||||
(temp2->prev)->next = temp1;
|
||||
temp1->prev = temp2->prev;
|
||||
free(temp2);
|
||||
return head;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The function that will return current size of list
|
||||
*
|
||||
* @param head start pointer of list
|
||||
* @return int size of list
|
||||
*/
|
||||
int getsize(ListNode *head)
|
||||
{
|
||||
if (!head)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int size = 1;
|
||||
ListNode *temp = head->next;
|
||||
while (temp != head)
|
||||
{
|
||||
temp = temp->next;
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Display list function
|
||||
* @param head start pointer of list
|
||||
* @returns void
|
||||
*/
|
||||
|
||||
void display_list(ListNode *head)
|
||||
{
|
||||
printf("\nContents of your linked list: ");
|
||||
ListNode *temp;
|
||||
temp = head;
|
||||
if (head != NULL)
|
||||
{
|
||||
while (temp->next != head)
|
||||
{
|
||||
printf("%" PRIu64 " <-> ", temp->value);
|
||||
temp = temp->next;
|
||||
}
|
||||
if (temp->next == head)
|
||||
{
|
||||
printf("%" PRIu64, temp->value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("The list is empty");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief access the list by index
|
||||
* @param list pointer to the target list
|
||||
* @param index access location
|
||||
* @returns the value at the specified index,
|
||||
* wrapping around if the index is larger than the size of the target
|
||||
* list
|
||||
*/
|
||||
uint64_t get(ListNode *list, const int index)
|
||||
{
|
||||
if (list == NULL || index < 0)
|
||||
{
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
ListNode *temp = list;
|
||||
for (int i = 0; i < index; ++i)
|
||||
{
|
||||
temp = temp->next;
|
||||
}
|
||||
return temp->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Self-test implementations
|
||||
* @returns void
|
||||
*/
|
||||
static void test()
|
||||
{
|
||||
ListNode *testList = NULL;
|
||||
unsigned int array[] = {2, 3, 4, 5, 6};
|
||||
|
||||
assert(getsize(testList) == 0);
|
||||
|
||||
printf("Testing inserting elements:\n");
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
display_list(testList);
|
||||
testList = insert_at_head(testList, array[i]);
|
||||
assert(testList->value == array[i]);
|
||||
assert(getsize(testList) == i + 1);
|
||||
}
|
||||
|
||||
printf("\nTesting removing elements:\n");
|
||||
for (int i = 4; i > -1; --i)
|
||||
{
|
||||
display_list(testList);
|
||||
assert(testList->value == array[i]);
|
||||
testList = delete_from_head(testList);
|
||||
assert(getsize(testList) == i);
|
||||
}
|
||||
|
||||
printf("\nTesting inserting at tail:\n");
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
display_list(testList);
|
||||
testList = insert_at_tail(testList, array[i]);
|
||||
assert(get(testList, i) == array[i]);
|
||||
assert(getsize(testList) == i + 1);
|
||||
}
|
||||
|
||||
printf("\nTesting removing from tail:\n");
|
||||
for (int i = 4; i > -1; --i)
|
||||
{
|
||||
display_list(testList);
|
||||
testList = delete_from_tail(testList);
|
||||
assert(getsize(testList) == i);
|
||||
// If list is not empty, assert that accessing the just removed element
|
||||
// will wrap around to the list head
|
||||
if (testList != NULL)
|
||||
{
|
||||
assert(get(testList, i) == testList->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the list is empty, assert that the elements were removed after
|
||||
// the correct number of iterations
|
||||
assert(i == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Main function
|
||||
* @returns 0 on exit
|
||||
*/
|
||||
int main()
|
||||
{
|
||||
test(); // run self-test implementations
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user