
Circular Linked List
Hey Coders! Today, we are going to dive deeper into the concept of circular linked lists. We'll explore various aspects of circular linked lists, including their definition and purpose, how to create and traverse a circular linked list, adding and deleting nodes at different positions, performing operations on the list elements, and managing/manipulating data stored in the nodes.
List of content:
- Defintion.
- Need of Circular Linked List.
- Creation and Traversal.
- Performing Operations.
Let's start.....
Definition:
A circular linked list is a variation of a linked list in which the last node points back to the first node, creating a loop. This structure is useful in applications where it’s necessary to continuously cycle through data, such as in buffer management or round-robin scheduling
Need of Circular Linked List:
Circular linked lists are needed when we require a cyclic or continuous way to store and manage data. Unlike standard linked lists, circular linked lists offer :
- Continuous Navigation: Since the last node links back to the first, traversals can go on indefinitely without encountering
NULL
. - Efficient Cyclic Traversals: This is particularly useful in applications like multimedia playlists, buffer allocations, and task schedulers.
- Memory Utilization: They allow dynamic memory management and efficient insertions/deletions like other linked lists.
- Ease of Implementation: Circular linked lists simplify certain operations where cycling through elements repeatedly is needed.
Creation, Traversal and Operations:
In C :
1. Define the Node Structure:
struct Node {
int data;
Node* next;
};
2. Creating a Circular Linked List:
Node* head = NULL;
Node* tail = NULL;
// Example to add nodes 1, 2, 3
void addNode(int value) {
Node* newNode = new Node();
newNode->data = value;
if (head == NULL) {
head = newNode;
tail = newNode;
newNode->next = head;
} else {
tail->next = newNode;
tail = newNode;
tail->next = head;
}
}
3. Traversing:
void traverse() {
if (head == NULL) return;
Node* temp = head;
do {
printf("%d",temp->data );
temp = temp->next;
} while (temp != head);
}
4. Add at Beginning:
void addAtBeginning(int value) {
Node* newNode = new Node();
newNode->data = value;
newNode->next = head;
tail->next = newNode;
head = newNode;
}
5. Add at a Specific Position:
void addAtPosition(int value, int pos) {
Node* newNode = new Node();
newNode->data = value;
if (pos == 1) {
addAtBeginning(value);
return;
}
Node* temp = head;
for (int i = 1; i < pos - 1 && temp->next != head; i++) {
temp = temp->next;
}
newNode->next = temp->next;
temp->next = newNode;
}
6. Delete at Beginning:
void deleteAtBeginning() {
if (head == NULL) return;
Node* temp = head;
head = head->next;
tail->next = head;
delete temp;
}
7. Delete at End:
void deleteAtEnd() {
Node* temp = head;
while (temp->next != tail) {
temp = temp->next;
}
temp->next = head;
delete tail;
tail = temp;
}
8. Delete at a Specific Position:
void deleteAtPosition(int pos) {
if (pos == 1) {
deleteAtBeginning();
return;
}
Node* temp = head;
for (int i = 1; i < pos - 1; i++) {
temp = temp->next;
}
Node* toDelete = temp->next;
temp->next = toDelete->next;
if (toDelete == tail) tail = temp;
delete toDelete;
}
In Java :
1. Define the Node Class:
class Node {
int data;
Node next;
Node(int data) {
this.data = data;
this.next = null;
}
}
2. Create and Connect Nodes:
Node head = null;
Node tail = null;
void addNode(int value) {
Node newNode = new Node(value);
if (head == null) {
head = newNode;
tail = newNode;
tail.next = head;
} else {
tail.next = newNode;
tail = newNode;
tail.next = head;
}
}
3. Traversing:
void traverse() {
if (head == null) return;
Node temp = head;
do {
System.out.print(temp.data + " ");
temp = temp.next;
} while (temp != head);
}
4. Add at Beginning:
void addAtBeginning(int value) {
Node newNode = new Node(value);
newNode.next = head;
tail.next = newNode;
head = newNode;
}
5. Add at a Specific Position:
void addAtPosition(int value, int pos) {
Node newNode = new Node(value);
if (pos == 1) {
addAtBeginning(value);
return;
}
Node temp = head;
for (int i = 1; i < pos - 1 && temp.next != head; i++) {
temp = temp.next;
}
newNode.next = temp.next;
temp.next = newNode;
}
6. Delete at Beginning:
void deleteAtBeginning() {
if (head == null) return;
Node temp = head;
head = head.next;
tail.next = head;
temp = null;
}
7. Delete at End:
void deleteAtEnd() {
Node temp = head;
while (temp.next != tail) {
temp = temp.next;
}
temp.next = head;
tail = temp;
}
8. Delete at a Specific Position:
void deleteAtPosition(int pos) {
if (pos == 1) {
deleteAtBeginning();
return;
}
Node temp = head;
for (int i = 1; i < pos - 1; i++) {
temp = temp.next;
}
Node toDelete = temp.next;
temp.next = toDelete.next;
if (toDelete == tail) tail = temp;
toDelete = null;
}
In C++ :
1. Define the Node Class:
struct Node {
int data;
Node* next;
};
2. Create and Connect Nodes:
Node* head = NULL;
Node* tail = NULL;
void addNode(int value) {
Node* newNode = new Node();
newNode->data = value;
if (head == NULL) {
head = newNode;
tail = newNode;
newNode->next = head;
} else {
tail->next = newNode;
tail = newNode;
tail->next = head;
}
}
3. Traversing:
void traverse() {
if (head == NULL) return;
Node* temp = head;
do {
std::cout << temp->data << " ";
temp = temp->next;
} while (temp != head);
std::cout << std::endl;
}
4. Add at Beginning:
void addAtBeginning(int value) {
Node* newNode = new Node();
newNode->data = value;
newNode->next = head;
tail->next = newNode;
head = newNode;
}
5. Add at a Specific Position:
void addAtPosition(int value, int pos) {
Node* newNode = new Node();
newNode->data = value;
if (pos == 1) {
addAtBeginning(value);
return;
}
Node* temp = head;
for (int i = 1; i < pos - 1 && temp->next != head; i++) {
temp = temp->next;
}
newNode->next = temp->next;
temp->next = newNode;
}
6. Delete at Beginning:
void deleteAtBeginning() {
if (head == NULL) return;
Node* temp = head;
head = head->next;
tail->next = head;
delete temp;
}
7. Delete at End:
void deleteAtEnd() {
if (head == NULL) return;
Node* temp = head;
while (temp->next != tail) {
temp = temp->next;
}
temp->next = head;
delete tail;
tail = temp;
}
8. Delete at a Specific Position:
void deleteAtPosition(int pos) {
if (head == NULL) return;
if (pos == 1) {
deleteAtBeginning();
return;
}
Node* temp = head;
for (int i = 1; i < pos - 1 && temp->next != head; i++) {
temp = temp->next;
}
Node* toDelete = temp->next;
temp->next = toDelete->next;
if (toDelete == tail) tail = temp;
delete toDelete;
}
A circular linked list is a specialized form of a linked list in which the last node is connected back to the first node, forming a closed loop. Unlike a linear linked list that ends with a NULL
pointer, a circular linked list allows continuous traversal from any point in the list. This structure can be either singly circular, where each node points only to the next node, or doubly circular, where each node also points to the previous one, enabling bidirectional navigation.
Circular linked lists are particularly useful in scenarios that require cycling through elements repeatedly, such as in round-robin scheduling, multiplayer board games, or circular buffers. Because of their looped nature, they allow easy rotation of data and efficient implementation of algorithms where the end of the list naturally wraps around to the beginning.
Let's explore doubly linked lists and circular linked lists click here.
For more topics click here.
Happy Coding!
4 Reactions
0 Bookmarks