A Circular Linked List is a variation of a linked list in which the last node points back to the first node, creating a circle. There is no 'null' at the end. This structure is useful for applications that require continuous looping, like managing processes in a round-robin scheduler.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
{
"status": "Initializing Circular Linked List"
}Overview
A circular linked list is a linked list whose last node points back to the first instead of to null. There is no natural end: starting from any node and following next will eventually bring you back to where you began.
This makes it a natural fit for anything that cycles: round-robin CPU scheduling, players taking turns in a game, or a playlist on repeat. Keeping a pointer to the tail is a useful trick, because tail.next is the head, so both ends are reachable in O(1).
The default commands insert 10, 20, 30 and 40 at the end. After each insertion, the new last node's next is pointed back at 10, closing the loop. The final structure is 10 -> 20 -> 30 -> 40 -> (back to 10).
Step by step
- Insert into an empty list: the new node becomes the head and points to itself.
- Insert at the end: walk until
current.next === head, setcurrent.next = newNodeandnewNode.next = head. - Traverse: start at the head and stop when you arrive back at the head, not when you hit null.
- Delete: unlink as in a singly linked list, taking care when the head itself is removed.
Complexity
| Case | Cost | Why |
|---|---|---|
| Access / search | O(n) | Sequential traversal. |
| Insert at end | O(n) or O(1) | O(1) if you keep a tail pointer. |
| Insert at head | O(1) with tail pointer | Insert after the tail and update tail.next. |
| Space | O(n) | One pointer per node. |
When to use it
- Round-robin scheduling and turn-based games.
- Circular buffers and repeating playlists.
- The Josephus problem and other 'go around the circle' puzzles.
Common mistakes
- A traversal loop that waits for null never ends — always stop when you return to the start.
- Deleting the head requires updating the last node's
nextas well. - Single-node lists point to themselves; check that case explicitly.
A dry run is the best way to check your understanding of Circular Linked List: follow each row, predict the next one, and compare. The run below takes 10 steps in total. The Line column refers to the line numbers in the code listing above.
- Input
- insert 10,insert 20,insert 30,insert 40
- Result
- status = Operations complete
| Step | Line | What happens |
|---|---|---|
| 1 | 7 | status = Initializing Circular Linked List |
| 2 | 11 | action = insert(10) |
| 3 | 19 | status = Inserted 10, head = 10 |
| 4 | 11 | action = insert(20) |
| 5 | 19 | status = Inserted 20, head = 10 |
| 6 | 11 | action = insert(30) |
| 7 | 19 | status = Inserted 30, head = 10 |
| 8 | 11 | action = insert(40) |
| 9 | 19 | status = Inserted 40, head = 10 |
| 10 | 20 | status = Operations complete |
What is a Circular Linked List?
What are the advantages of a Circular Linked List?
How do you know when you've traversed the whole list?
What are the time complexities for operations?
- Search: O(n).
- Insertion at beginning/end: O(1) if a `tail` pointer is maintained, otherwise O(n).
- Deletion: O(n) to find the element, but O(1) if a pointer to the node (and its predecessor) is known.