Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Implementing Doubly Circular Linked Lists in C

Tech May 17 3

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;
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.