Implementing Doubly Circular Linked Lists in C
A doubly circular linked list is a sophisticated data structure that enhances the basic linked list concept. Unlike singly linked lists, each node in this structure contains pointers to both its successor and predecessor nodes. The "circular" aspect means the last node points back to the first node, and the first node points to the last as its predecessor, creating a seamless loop.
Structure Definition
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define DATA_TYPE int
// Node structure for doubly circular linked list
typedef struct CircularNode {
DATA_TYPE value;
struct CircularNode* prev;
struct CircularNode* next;
} CircularNode;
// Doubly circular linked list structure
typedef struct CircularList {
CircularNode* header; // Header node
CircularNode* last; // Last node
size_t length; // Number of nodes
} CircularList;
Node Creation Function
// Create a new node for the doubly circular linked list
CircularNode* create_node(DATA_TYPE value) {
CircularNode* newNode = (CircularNode*)malloc(sizeof(CircularNode));
newNode->value = value;
newNode->prev = newNode;
newNode->next = newNode;
return newNode;
}
List Initialization Function
// Initialize an empty doubly circular linked list
CircularList* initialize_list(void) {
CircularList* list = (CircularList*)malloc(sizeof(CircularList));
CircularNode* dummyNode = create_node(0);
list->header = dummyNode;
list->last = dummyNode;
list->length = 0;
return list;
}
Front Insertion Function
// Add a node at the front of the list
bool insert_at_front(CircularList* list, DATA_TYPE value) {
if (NULL == list) return false;
CircularNode* newNode = create_node(value);
if (list->length == 0) {
newNode->prev = list->header;
newNode->next = list->header;
list->header->next = newNode;
list->header->prev = newNode;
list->last = newNode;
} else {
newNode->prev = list->header;
newNode->next = list->header->next;
list->header->next->prev = newNode;
list->header->next = newNode;
}
list->length++;
return true;
}
Rear Insertion Function
// Add a node at the end of the list
bool insert_at_rear(CircularList* list, DATA_TYPE value) {
if (NULL == list) return false;
CircularNode* newNode = create_node(value);
if (list->length == 0) {
newNode->prev = list->header;
newNode->next = list->header;
list->header->next = newNode;
list->header->prev = newNode;
list->last = newNode;
} else {
list->last->next = newNode;
newNode->prev = list->last;
newNode->next = list->header;
list->header->prev = newNode;
list->last = newNode;
}
list->length++;
return true;
}
Position-based Insertion Function
// Insert a node at a specific position
bool insert_at_position(CircularList* list, int position, DATA_TYPE value) {
if (position < 0 || position > list->length) return false;
if (position == 0) return insert_at_front(list, value);
if (position == list->length) return insert_at_rear(list, value);
CircularNode* current = list->header->next;
CircularNode* newNode = create_node(value);
for (int i = 1; i < position; i++) {
current = current->next;
}
newNode->next = current->next;
current->next->prev = newNode;
newNode->prev = current;
current->next = newNode;
list->length++;
return true;
}
Node Removal Functions
// Remove a node by position
bool remove_by_position(CircularList* list, int position) {
if (position < 0 || position >= list->length) return false;
CircularNode* targetNode = list->header;
if (position == 0) {
targetNode = list->header->next;
list->header->next = list->header->next->next;
list->header->next->prev = list->header;
} else if (position == list->length - 1) {
targetNode = list->last;
list->header->prev = list->last->prev;
list->last->prev->next = list->header;
} else {
targetNode = list->header->next;
for (int i = 0; i < position; i++) {
targetNode = targetNode->next;
}
targetNode->prev->next = targetNode->next;
targetNode->next->prev = targetNode->prev;
}
free(targetNode);
targetNode = NULL;
list->length--;
return true;
}
// Remove nodes by value
bool remove_by_value(CircularList* list, DATA_TYPE value) {
if (0 == list->length) return false;
bool found = false;
CircularNode* current = list->header->next;
while (current != list->header) {
CircularNode* temp = current;
current = current->next;
if (temp->value == value) {
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
free(temp);
list->length--;
found = true;
}
}
return found;
}
Node Update Functions
// Update a node's value by position
bool update_by_position(CircularList* list, int position, DATA_TYPE newValue) {
if (position < 0 || position >= list->length) return false;
CircularNode* current = list->header->next;
for (int i = 0; i < position; i++) {
current = current->next;
}
current->value = newValue;
return true;
}
// Update a node's value by finding an existing value
bool update_by_value(CircularList* list, DATA_TYPE oldValue, DATA_TYPE newValue) {
if (0 == list->length) return false;
CircularNode* current = list->header->next;
for (int i = 0; i < list->length; i++) {
if (current->value == oldValue) {
current->value = newValue;
return true;
}
current = current->next;
}
return false;
}
List Traversal Function
// Display all elements in the list
void display_list(CircularList* list) {
if (0 == list->length) {
printf("The list is empty.\n");
return;
}
CircularNode* current = list->header->next;
printf("List elements: ");
for (int i = 0; i < list->length; i++) {
printf("%d ", current->value);
current = current->next;
}
printf("\n");
}
Example Usage
int main(int argc, const char* argv[]) {
CircularList* list = initialize_list();
// Insert elements at the front
for (int i = 0; i < 10; i++) {
insert_at_front(list, i);
}
display_list(list);
// Insert elements at the rear
for (int i = 0; i < 10; i++) {
insert_at_rear(list, i);
}
display_list(list);
// Insert at a specific position
insert_at_position(list, 3, 88);
display_list(list);
// Remove by position
remove_by_position(list, 3);
display_list(list);
// Remove by value
remove_by_value(list, 6);
display_list(list);
// Update by position
update_by_position(list, 6, 333);
display_list(list);
// Update by value
update_by_value(list, 0, 99);
display_list(list);
return 0;
}