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.
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
head → NULL
The last node points back to head instead of NULL — there is no natural stopping point.
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.
/* 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 */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.
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");
}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?
Why this lesson exists
Syllabus mapping
Circular Linked Lists
Maps to course outcomes CO1, CO4.