Unit 1 · Lesson 318 minAcademic review pending

A list with no end

Point the last node's next back at the first and the list becomes a ring — useful for anything that cycles, and a common source of infinite loops if you traverse it like a plain list.

Choose explanation

After this lesson

You should be able to

  • Build a circular singly linked list.
  • Traverse it correctly without looping forever.
  • Explain why a while (cur != NULL) traversal fails on a circular list.

Try it before you read

Try it live

circular_list.c0 node(s)

head → NULL

The last node points back to head instead of NULL — there is no natural stopping point.

01

One pointer changes everything

A circular linked list is a singly linked list with exactly one difference: the last node's next points back to the first node instead of holding NULL. There is no longer an 'end' — every node has a valid successor.

This suits anything that genuinely cycles: a round-robin turn order, a playlist that repeats, a circular buffer of recent events. The ring shape matches the problem shape.

Everything from Lesson 2, plus one closing link
/* Circular list of three nodes: 10 -> 20 -> 30 -> (back to 10) */
Node *head = NULL;
head = insert_front(head, 30);
head = insert_front(head, 20);
head = insert_front(head, 10);

/* find current last node and close the ring */
Node *last = head;
while (last->next != head)
    last = last->next;
last->next = head;   /* the one line that makes it circular */
02

The traversal bug this shape creates

Lesson 2's traversal stopped when cur became NULL. In a circular list, cur never becomes NULL — the chain has no end to reach, so that loop runs forever. This is the most common mistake when moving from singly linked to circular lists, and it compiles without any warning.

The fix is to stop on a condition that is actually true for this shape: traverse using a do { } while loop and stop when you return to the node you started from, not when you meet NULL.

do-while, because you must visit head before testing
void print_circular(const Node *head)
{
    if (head == NULL) return;

    const Node *cur = head;
    do {
        printf("%d -> ", cur->data);
        cur = cur->next;
    } while (cur != head);   /* stop on return, not on NULL */
    printf("(back to start)\n");
}
03

Insertion needs the ring re-closed

Inserting after a given node in a circular list is otherwise identical to a plain list — allocate, link the new node's next to what came after, link the previous node to the new one. The ring shape does not change this step, because you are working locally around one node.

Deleting the only remaining node is the case people forget: you must set head to NULL rather than leaving it pointing at freed memory that now points at itself.

Try it yourself

Build a circular linked list of n players, then simulate passing a turn marker k steps at a time, printing whose turn it is each step, for a fixed number of rounds.

Need a hint?

Advancing k steps around a ring is just calling cur = cur->next k times — the ring means you never fall off the end.

Check the worked solution

The ring is what makes the turn marker able to walk past the last player and land back on the first without any special-case code — that seamlessness is the entire reason to use a circular list here rather than checking for NULL and manually wrapping the index.

#include <stdio.h>
#include <stdlib.h>

struct Node { int player; struct Node *next; };
typedef struct Node Node;

int main(void)
{
    int n = 4, k = 2, rounds = 6;
    Node *head = NULL, *last;

    for (int i = n; i >= 1; i--) {
        Node *node = malloc(sizeof(Node));
        node->player = i;
        node->next = head;
        head = node;
    }
    last = head;
    while (last->next != head) last = last->next;
    last->next = head;

    Node *cur = head;
    for (int r = 0; r < rounds; r++) {
        for (int step = 0; step < k; step++)
            cur = cur->next;
        printf("Round %d: player %d\n", r + 1, cur->player);
    }

    return 0;
}

Quick check

Traversing a circular linked list with while (cur != NULL) usually results in what?

Select an answer to check your thinking.

Why this lesson exists

Syllabus mapping

Circular Linked Lists

Maps to course outcomes CO1, CO4.