Chapter 13 of 32

Circular Linked List

In a normal linked list, the last node points to null.

For example:

10 → 20 → 30 → null

Once we reach 30, we know that the list has ended.

A circular linked list works differently. Instead of the last node pointing to null, it points back to the first node.

10 → 20 → 30
↑         ↓
└─────────┘

So there is no null at the end. The nodes form a circle.

What is a Circular Linked List?

A circular linked list is a linked list where the last node points back to the first node.

For example:

10 → 20 → 30
↑         ↓
└─────────┘

Here:

10 → 20
20 → 30
30 → 10

The last node, 30, points back to 10.

This means we can keep moving through the list forever if we don't have a condition to stop.

Creating a Node

Just like a singly linked list, a node can contain data and a reference to the next node:

class Node {
    int data;
    Node next;

    Node(int data) {
        this.data = data;
    }
}

Now let's create three nodes:

Node first = new Node(10);
Node second = new Node(20);
Node third = new Node(30);

We connect them:

first.next = second;
second.next = third;
third.next = first;

Now we have:

first
 ↓
10 → 20 → 30
↑         ↓
└─────────┘

Notice the important part:

third.next = first;

That's what makes the linked list circular.

Traversing a Circular Linked List

With a normal linked list, we usually stop when:

current == null

But a circular linked list never reaches null.

So this would be a problem:

while (current != null) {
    // ...
}

The loop would never stop.

Instead, we can stop when we reach the head again.

For example:

Node current = first;

do {
    System.out.println(current.data);
    current = current.next;

} while (current != first);

Output:

10
20
30

The do-while loop works nicely here because we want to process the first node before checking whether we've returned to it.

Why Does It Stop?

Let's follow the references:

Start at 10
    ↓
20
    ↓
30
    ↓
10 ← back to starting point

When current becomes first again, we stop.

current != first

becomes false.

Adding a Node

Suppose we have:

10 → 20 → 30
↑         ↓
└─────────┘

and want to add 40 at the end.

We need to change the links:

10 → 20 → 30 → 40
↑              ↓
└──────────────┘

If 30 is the last node:

Node newNode = new Node(40);

newNode.next = first;
third.next = newNode;

Now 40 points to the first node, and 30 points to 40.

The result is:

10 → 20 → 30 → 40
↑              ↓
└──────────────┘

Adding a Node at the Beginning

Suppose we have:

10 → 20 → 30
↑         ↓
└─────────┘

We want to add 5 at the beginning.

The new structure should be:

5 → 10 → 20 → 30
↑              ↓
└──────────────┘

We need to make the new node point to the current first node and update the last node's next reference.

For example:

Node newNode = new Node(5);

newNode.next = first;
third.next = newNode;

first = newNode;

Now first points to 5.

Deleting a Node

Suppose our circular linked list is:

10 → 20 → 30
↑         ↓
└─────────┘

We want to remove 20.

We need to make 10 point directly to 30:

10 → 30
↑    ↓
└────┘

In code:

first.next = third;

Now 20 is no longer connected to the circular list.

Circular Linked List with a Tail

A useful approach is to maintain a tail reference.

For example:

head
 ↓
10 → 20 → 30
↑         ↓
└─────────┘
          ↑
         tail

The tail points to the last node, and:

tail.next

points back to the head.

This can make certain operations easier.

For example, if we want to add a new node at the end:

Node newNode = new Node(40);

newNode.next = tail.next;
tail.next = newNode;

tail = newNode;

Now:

10 → 20 → 30 → 40
↑              ↓
└──────────────┘

Circular Singly vs Circular Doubly Linked List

A circular linked list can be either singly or doubly linked.

A circular singly linked list looks like:

10 → 20 → 30
↑         ↓
└─────────┘

Each node only knows the next node.

A circular doubly linked list has both prev and next references:

10 ⇄ 20 ⇄ 30
↑           ↓
└───────────┘

So you can move in both directions while still forming a circle.

Circular Linked List vs Normal Linked List

Let's compare them.

Feature

Normal Linked List

Circular Linked List

Last node points to

null

First node

Forms a circle

No

Yes

Can traverse continuously

No

Yes

Natural stopping point

null

Starting node

Useful for repeated cycles

Less suitable

Very suitable

The biggest difference is simple:

Normal:
10 → 20 → 30 → null

Circular:
10 → 20 → 30 ─┐
↑              │
└──────────────┘

Real-Life Example

A great example of a circular linked list is a round-robin system.

Imagine four players:

John → Jason → Alex → Michael
 ↑                         ↓
 └─────────────────────────┘

After Michael's turn, it goes back to John.

Then:

John
 ↓
Jason
 ↓
Alex
 ↓
Michael
 ↓
John
 ↓
...

There isn't really a final player. The turns keep going around.

This is exactly the kind of situation where a circular linked list can be useful.

Another Real-Life Example

Imagine a music player with repeat mode.

Your playlist is:

Song A → Song B → Song C
  ↑                 ↓
  └─────────────────┘

After Song C finishes, the player goes back to Song A.

The playlist keeps cycling until the user stops it.

Time Complexity

The time complexity depends on the operation and whether we already have references such as head or tail.

Common operations are roughly:

Operation

Time

Access by position

O(n)

Search

O(n)

Insert at beginning with tail

O(1)

Insert at end with tail

O(1)

Traverse

O(n)

Just like other linked lists, accessing an element by position isn't O(1) because we have to follow the links to reach it.

A Complete Example

Let's create a simple circular linked list:

class Node {
    int data;
    Node next;

    Node(int data) {
        this.data = data;
    }
}

class Main {
    public static void main(String[] args) {

        Node first = new Node(10);
        Node second = new Node(20);
        Node third = new Node(30);

        first.next = second;
        second.next = third;
        third.next = first;

        Node current = first;

        do {
            System.out.println(current.data);
            current = current.next;

        } while (current != first);
    }
}

Output:

10
20
30

The important part is:

third.next = first;

This connects the last node back to the first node and makes the list circular.

When Should You Use a Circular Linked List?

Circular linked lists are useful when data needs to be processed repeatedly in a cycle.

Common examples include:

  • Round-robin scheduling

  • Multiplayer turn systems

  • Repeating playlists

  • Circular buffers

  • Repeated task scheduling

  • Systems where there is no natural "last" element

The main idea is:

A circular linked list is a linked list where the last node points back to the first node instead of pointing to null.

So while a normal linked list looks like:

10 → 20 → 30 → null

a circular linked list looks like:

10 → 20 → 30
↑         ↓
└─────────┘

Once you understand that one difference, the rest of the concept becomes much easier.