Circular Linked List in Data Structure (C++)
Last Updated on: 3rd Jan 2026 22:37:14 PM
A Circular Linked List is a variation of a linked list in which the last node is connected back to the first node instead of pointing to NULL. This circular connection makes traversal continuous and eliminates the concept of a definite end of the list.
Circular Linked Lists are especially useful in applications where data needs to be accessed repeatedly in a cyclic manner. Because of this looping nature, they are widely used in operating systems, scheduling algorithms, and real-time applications.
In this tutorial, we will study the structure, types, operations, advantages, limitations, applications, and a complete C++ implementation of Circular Linked List with time complexity analysis.
What is a Circular Linked List?
A Circular Linked List is a linked list in which the last node points to the first node, forming a circular loop. Unlike a linear linked list, no node in a circular linked list contains a NULL pointer.
Real-Life Example
Consider a round table meeting. After the last person speaks, the turn again comes to the first person. There is no fixed start or end. This cyclic behavior represents a circular linked list.
Structure of Circular Linked List
Each node contains:
-
Data – the value stored
-
Next pointer – stores the address of the next node
The last node’s next pointer stores the address of the first node.
Node Representation
[ Data | Next ]
↑_______|
Types of Circular Linked List
1. Singly Circular Linked List
A Singly Circular Linked List contains nodes with only one pointer ( next ). The last node’s next pointer stores the address of the first node.
Real-Life Example
A circular playlist where songs keep playing repeatedly from the beginning after the last song.
Key Points
-
Only forward traversal is possible
-
Memory efficient compared to doubly circular list
-
Widely used in scheduling problems
Node Structure in C++
struct Node {
int data;
Node* next;
};
2. Doubly Circular Linked List
A Doubly Circular Linked List contains two pointers:
-
prevpointer to the previous node -
nextpointer to the next node
The first node’s prev pointer points to the last node, and the last node’s next pointer points to the first node.
Real-Life Example
A carousel ride, where movement is possible both forward and backward in a circular path.
Key Points
-
Traversal possible in both directions
-
Faster deletion compared to singly circular list
-
Requires extra memory
Node Structure in C++
struct Node {
int data;
Node* prev;
Node* next;
};
Operations on Circular Linked List
We will implement operations using a Singly Circular Linked List for simplicity.
Operations Covered
-
Insertion at Beginning
-
Insertion at End
-
Deletion from Beginning
-
Deletion from End
-
Traversal
Insertion Operations
Insertion at the Beginning
A new node is inserted before the current head. The last node’s next pointer must be updated to point to the new head.
Time Complexity: O(n)
Reason: Traversal is required to reach the last node.
Insertion at the End
A new node is inserted after the last node, and its next pointer is set to the head.
Time Complexity: O(n)
Reason: Traversal is needed to locate the last node.
Deletion Operations
Deletion from the Beginning
The head node is removed, and the last node’s next pointer is updated to the new head.
Time Complexity: O(n)
Reason: The last node must be located.
Deletion from the End
The last node is removed by locating the second-last node and updating its next pointer.
Time Complexity: O(n)
Reason: Full traversal is required to find the previous node.
Traversal Operation
Traversal
Traversal starts from the head and continues until the head is reached again.
Time Complexity: O(n)
Reason: Each node is visited exactly once.
Complete C++ Program: Circular Singly Linked List
#include <iostream>
using namespace std;
struct Node {
int data;
Node* next;
};
Node* head = NULL;
/* Insert at Beginning */
void insertAtBeginning(int value) {
Node* newNode = new Node();
newNode->data = value;
if (head == NULL) {
head = newNode;
newNode->next = head;
return;
}
Node* temp = head;
while (temp->next != head)
temp = temp->next;
newNode->next = head;
temp->next = newNode;
head = newNode;
}
/* Insert at End */
void insertAtEnd(int value) {
Node* newNode = new Node();
newNode->data = value;
if (head == NULL) {
head = newNode;
newNode->next = head;
return;
}
Node* temp = head;
while (temp->next != head)
temp = temp->next;
temp->next = newNode;
newNode->next = head;
}
/* Delete from Beginning */
void deleteFromBeginning() {
if (head == NULL) {
cout << "List is empty\n";
return;
}
if (head->next == head) {
delete head;
head = NULL;
return;
}
Node* temp = head;
Node* last = head;
while (last->next != head)
last = last->next;
head = head->next;
last->next = head;
delete temp;
}
/* Delete from End */
void deleteFromEnd() {
if (head == NULL) {
cout << "List is empty\n";
return;
}
if (head->next == head) {
delete head;
head = NULL;
return;
}
Node* temp = head;
Node* prev = NULL;
while (temp->next != head) {
prev = temp;
temp = temp->next;
}
prev->next = head;
delete temp;
}
/* Traversal */
void traverse() {
if (head == NULL) {
cout << "List is empty\n";
return;
}
Node* temp = head;
cout << "Circular Linked List: ";
do {
cout << temp->data << " -> ";
temp = temp->next;
} while (temp != head);
cout << "(back to head)\n";
}
/* Main Function */
int main() {
insertAtEnd(10);
insertAtEnd(20);
insertAtBeginning(5);
insertAtEnd(30);
traverse();
deleteFromBeginning();
traverse();
deleteFromEnd();
traverse();
return 0;
}
Output
Circular Linked List: 5 -> 10 -> 20 -> 30 -> (back to head)
Circular Linked List: 10 -> 20 -> 30 -> (back to head)
Circular Linked List: 10 -> 20 -> (back to head)
C++ Example: Doubly Circular Linked List
#include <iostream>
using namespace std;
struct Node {
int data;
Node* prev;
Node* next;
};
Node* head = NULL;
void insert(int value) {
Node* newNode = new Node();
newNode->data = value;
if (head == NULL) {
head = newNode;
newNode->next = head;
newNode->prev = head;
} else {
Node* last = head->prev;
last->next = newNode;
newNode->prev = last;
newNode->next = head;
head->prev = newNode;
}
}
void display() {
if (head == NULL) return;
Node* temp = head;
do {
cout << temp->data << " ";
temp = temp->next;
} while (temp != head);
}
int main() {
insert(1);
insert(2);
insert(3);
display();
return 0;
}
Time Complexity Analysis (With Reason)
| Operation | Time Complexity | Reason |
|---|---|---|
| Insert at Beginning | O(n) | Last node must be found to update its next pointer |
| Insert at End | O(n) | Traversal needed to reach last node |
| Delete from Beginning | O(n) | Last node traversal required |
| Delete from End | O(n) | Traversal needed to find second-last node |
| Traversal | O(n) | Each node visited once |
Advantages of Circular Linked List
-
No
NULLpointers are used -
Efficient for repeated traversal
-
Any node can be treated as the first node
-
Ideal for cyclic processes
Limitations of Circular Linked List
-
More complex logic than linear linked list
-
Infinite loops can occur if traversal condition is wrong
-
Deletion operations require careful pointer handling
Applications of Circular Linked List
-
CPU scheduling (Round Robin Scheduling)
-
Circular queues
-
Multiplayer games turn management
-
Music and video playlists
-
Buffer management
Conclusion
Circular Linked Lists are powerful data structures used when data needs to be processed in a continuous loop. Understanding their structure, types, operations, and time complexity helps in solving real-world problems efficiently and prepares students for advanced data structure concepts.
Keep practicing — you're doing amazing!
Happy Coding! ![]()