Skip to content

05 The Circular Linked List

1. The Concept & Purpose

What is it? A list where the last node does not point to NULL. Instead, it points back to the Head (or the Sentinel). * Visual: [Sentinel] -> [A] -> [B] -> [C] --(points back)--> [Sentinel]

Why introduce it? (The Logic) 1. Continuous Looping: Useful for applications that need to cycle through data repeatedly without resetting (e.g., Round-Robin process scheduling in Operating Systems, media players on "Repeat" mode). 2. Accessibility: From any node in the list, you can reach any other node just by keeping moving forward. You never hit a dead end (NULL).


2. Modifications Required

We assume a Singly Linked List with a Sentinel as the base.

A. Initialization (createList)

  • Change: The Sentinel must point to itself, not NULL.
  • Why: An empty circular list is just a Sentinel pointing to the Sentinel.
LinkedList* createList() {
    LinkedList* list = (LinkedList*)malloc(sizeof(LinkedList));
    list->head = (Node*)malloc(sizeof(Node));

    // THE CHANGE: Point back to self
    list->head->next = list->head; 
    return list;
}

B. Insertion at Back (pushBack)

  • Change: The new tail must point to the Sentinel, not NULL.
void pushBack(LinkedList* list, int val) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = val;

    // 1. New node points back to Head (Sentinel)
    newNode->next = list->head; 

    // 2. Old tail points to New Node
    // (Assuming we have a 'tail' pointer for O(1) access)
    list->tail->next = newNode;
    list->tail = newNode;
}

C. Traversal / Printing (The Critical Change)

  • Change: You cannot use while (p != NULL). That loop will run forever (Infinite Loop).
  • New Logic: You must stop when the pointer wraps around to the start.
void printList(LinkedList* list) {
    Node* p = list->head->next; // Start at first data node

    // Stop if we hit the Sentinel again
    while (p != list->head) {
        printf("%d -> ", p->data);
        p = p->next;
    }
    printf("(back to start)\n");
}

3. Unique Precautions (Gotchas)

  1. The Infinite Loop Trap: This is the #1 bug. If you write while(p) or while(p->next), your program will freeze. Always check if (p == head).
  2. Josephus Problem: When deleting nodes in a circle, be very careful not to delete the Sentinel if your logic assumes data nodes only.