Circular linked lists are a fascinating data structure that offers unique advantages over other types of linked lists due to their circular nature. Unlike singly or doubly linked lists, the last node of a circular linked list points back to the head, forming a loop. This allows traversal from any node to the rest of the list and makes certain operations more efficient. However, this structure also introduces some complexities, especially when performing deletions.
Table of Contents

In this detailed post, we will explore how to delete the last node in a circular linked list, step by step, ensuring clarity for beginners and experts alike.
Understanding the Problem: Deleting the Last Node
To delete the last node in a circular linked list, it is essential to maintain the integrity of the circular structure. This requires careful manipulation of the pointers within the list. The steps involve identifying the last node, updating the necessary pointers to bypass it, and ensuring no memory leaks occur. The process can be divided into three cases:
- The list is empty.
- The list contains only one node.
- The list contains multiple nodes.
Each of these scenarios requires specific handling to ensure the operation is executed correctly.

Step-by-Step Approach
Step 1: Check if the List is Empty
The first step in deleting the last node is to determine if the list is empty. This is done by checking if the last
pointer is set to nullptr
. If the list is empty, the operation cannot proceed.
Implementation in C++ Programming Language:
if (last == nullptr) {
std::cout << "List is empty, nothing to delete." << std::endl;
return nullptr;
}
In this scenario, since there are no nodes in the list, there is nothing to delete, and the function simply returns nullptr
. This prevents unnecessary operations and ensures the program does not attempt to access invalid memory.
Step 2: Get the Head Node
If the list is not empty, the next step is to retrieve the head node. In a circular linked list, the head node is the node pointed to by last->next
.
Explanation: The last
pointer in a circular linked list always points to the last node, and the next
pointer of this node points back to the head of the list.
Implementation in C++ Programming Language:
Node* head = last->next;
This step prepares us for the subsequent operations by providing access to the starting point of the list.
Step 3: Check for a Single Node
In a circular linked list with only one node, the head
is equal to last
. This is a unique scenario that requires deleting the only node in the list and updating the last
pointer to nullptr
.
Implementation in C++ Programming Language:
if (head == last) {
delete last;
last = nullptr;
return last;
}
Key Consideration: This step ensures the list becomes empty, and the memory used by the node is released appropriately. The last
pointer is set to nullptr
, indicating the list is now empty.
Step 4: Find the Second Last Node
For lists with multiple nodes, the next step is to locate the second last node. This node will become the new last node after the deletion.
Explanation: The second last node is identified as the node whose next
pointer points to the current last node. Traversal is necessary to find this node.
Implementation in C++ Programming Language:
Node* curr = head;
while (curr->next != last) {
curr = curr->next;
}
Traversal Details: Starting from the head, the loop continues until the condition curr->next == last
is met. At this point, curr
points to the second last node.
Step 5: Update the Pointers
Once the second last node is identified, its next
pointer is updated to point back to the head, effectively bypassing the last node.
Implementation in C++ Programming Language:
curr->next = head;
This ensures the circular nature of the list is preserved, as the second last node now becomes the last node and links back to the head.
Step 6: Delete the Last Node
The final step is to delete the current last node to free up memory. The last
pointer is then updated to point to the second last node, which is now the new last node.
Implementation in C++ Programming Language:
delete last;
last = curr;
Memory Management: Deleting the last node prevents memory leaks, ensuring efficient use of system resources.
Complete Implementation
Below is the complete C++ Programming implementation of deleting the last node in a circular linked list:
Node* deleteLastNode(Node* last) {
if (last == nullptr) {
std::cout << "List is empty, nothing to delete." << std::endl;
return nullptr;
}
Node* head = last->next;
if (head == last) {
delete last;
last = nullptr;
return last;
}
Node* curr = head;
while (curr->next != last) {
curr = curr->next;
}
curr->next = head;
delete last;
last = curr;
return last;
}
By following this detailed step-by-step approach, you can confidently delete the last node in a circular linked list while maintaining its structure and efficiency. This operation highlights the importance of understanding pointer manipulation and memory management in C++ programming.
Code Implementation In Multiple Programming Languages
Here is the detailed implementation of the code of deleting the last node in a circular linked list while maintaining its structure and efficiency in multiple programming languages. {Like: C, C++, C#, Java, JavaScript, and Python}

C Programming
#include <stdio.h>
#include <stdlib.h>
// Define the structure for a node in the circular linked list
struct Node {
int data;
struct Node* next;
};
// Function to delete the last node in the circular linked list
struct Node* deleteLastNode(struct Node* last) {
if (last == NULL) {
// If the list is empty, print a message and return NULL
printf("List is empty, nothing to delete.\n");
return NULL;
}
struct Node* head = last->next;
// If there is only one node in the list
if (head == last) {
free(last);
last = NULL; // The list becomes empty
return last;
}
// Traverse the list to find the second last node
struct Node* curr = head;
while (curr->next != last) {
curr = curr->next;
}
// Update the second last node's next pointer to point to the head
curr->next = head;
// Free the memory occupied by the last node
free(last);
// Update the last pointer to point to the second last node
last = curr;
return last;
}
// Function to print the circular linked list
void printList(struct Node* last) {
if (last == NULL) {
// If the list is empty, return
printf("List is Empty\n");
return;
}
struct Node* head = last->next;
do {
printf("%d ", head->data);
head = head->next;
} while (head != last->next);
printf("\n");
}
// Function to create a new node
struct Node* createNode(int value) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = value;
newNode->next = NULL;
return newNode;
}
int main() {
// Create a circular linked list: 2 -> 3 -> 4 -> 2
struct Node* first = createNode(2);
first->next = createNode(3);
first->next->next = createNode(4);
struct Node* last = first->next->next;
last->next = first; // Circular link: last node points to first
printf("Original list: ");
printList(last);
// Delete the last node
last = deleteLastNode(last);
printf("List after deleting last node: ");
printList(last);
return 0;
}
Explanation of the Code
- Struct Definition:
- The
struct Node
defines the structure of a node in the circular linked list, containing an integerdata
and a pointernext
to the next node.
- The
createNode
Function:- This function takes an integer value as input, creates a new node, assigns the value to
data
, and sets thenext
pointer toNULL
.
- This function takes an integer value as input, creates a new node, assigns the value to
deleteLastNode
Function:- This function is responsible for deleting the last node in the circular linked list:
- It first checks if the list is empty (
last == NULL
). If empty, it prints a message and returnsNULL
. - If the list contains only one node (i.e., the head is the same as the last node), it frees the memory of that node and sets
last
toNULL
, effectively making the list empty. - If there are multiple nodes, it traverses the list to find the second last node (i.e., the node whose
next
pointer points to the last node). - Once the second last node is found, its
next
pointer is updated to point back to the head, removing the last node from the circular list. - The last node is then deleted (
free(last)
), and thelast
pointer is updated to point to the second last node.
- It first checks if the list is empty (
- This function is responsible for deleting the last node in the circular linked list:
printList
Function:- This function prints all the nodes in the circular linked list:
- If the list is empty (
last == NULL
), it prints “List is Empty”. - It starts from the head (i.e.,
last->next
) and prints thedata
of each node until it loops back to the head.
- If the list is empty (
- This function prints all the nodes in the circular linked list:
main
Function:- This function demonstrates the creation of a circular linked list and performs the operation of deleting the last node:
- It first creates a list with values
2 -> 3 -> 4
and links the last node back to the first node to form a circular list. - It prints the original list using
printList
. - It then deletes the last node using
deleteLastNode
and prints the updated list.
- It first creates a list with values
- This function demonstrates the creation of a circular linked list and performs the operation of deleting the last node:
C++ Implementation
#include <iostream>
using namespace std;
// Node structure
struct Node {
int data;
Node* next;
};
// Function to delete the last node
Node* deleteLastNode(Node* last) {
if (!last) {
cout << "List is empty, nothing to delete.\n";
return nullptr;
}
Node* head = last->next;
if (head == last) {
delete last;
return nullptr;
}
Node* curr = head;
while (curr->next != last) {
curr = curr->next;
}
curr->next = head;
delete last;
return curr;
}
// Function to print the circular linked list
void printList(Node* last) {
if (!last) {
cout << "List is empty.\n";
return;
}
Node* head = last->next;
do {
cout << head->data << " ";
head = head->next;
} while (head != last->next);
cout << endl;
}
// Function to create a new node
Node* createNode(int value) {
Node* newNode = new Node();
newNode->data = value;
newNode->next = nullptr;
return newNode;
}
int main() {
Node* first = createNode(2);
first->next = createNode(3);
first->next->next = createNode(4);
Node* last = first->next->next;
last->next = first;
cout << "Original list: ";
printList(last);
last = deleteLastNode(last);
cout << "List after deleting last node: ";
printList(last);
return 0;
}
C# Implementation
using System;
class Node {
public int Data;
public Node Next;
}
class CircularLinkedList {
public static Node DeleteLastNode(Node last) {
if (last == null) {
Console.WriteLine("List is empty, nothing to delete.");
return null;
}
Node head = last.Next;
if (head == last) {
last = null;
return null;
}
Node curr = head;
while (curr.Next != last) {
curr = curr.Next;
}
curr.Next = head;
last = curr;
return last;
}
public static void PrintList(Node last) {
if (last == null) {
Console.WriteLine("List is empty.");
return;
}
Node head = last.Next;
do {
Console.Write(head.Data + " ");
head = head.Next;
} while (head != last.Next);
Console.WriteLine();
}
public static Node CreateNode(int value) {
return new Node { Data = value, Next = null };
}
public static void Main() {
Node first = CreateNode(2);
first.Next = CreateNode(3);
first.Next.Next = CreateNode(4);
Node last = first.Next.Next;
last.Next = first;
Console.WriteLine("Original list: ");
PrintList(last);
last = DeleteLastNode(last);
Console.WriteLine("List after deleting last node: ");
PrintList(last);
}
}
Java Implementation
class Node {
int data;
Node next;
Node(int data) {
this.data = data;
this.next = null;
}
}
public class CircularLinkedList {
static Node deleteLastNode(Node last) {
if (last == null) {
System.out.println("List is empty, nothing to delete.");
return null;
}
Node head = last.next;
if (head == last) {
return null;
}
Node curr = head;
while (curr.next != last) {
curr = curr.next;
}
curr.next = head;
last = curr;
return last;
}
static void printList(Node last) {
if (last == null) {
System.out.println("List is empty.");
return;
}
Node head = last.next;
do {
System.out.print(head.data + " ");
head = head.next;
} while (head != last.next);
System.out.println();
}
public static void main(String[] args) {
Node first = new Node(2);
first.next = new Node(3);
first.next.next = new Node(4);
Node last = first.next.next;
last.next = first;
System.out.println("Original list: ");
printList(last);
last = deleteLastNode(last);
System.out.println("List after deleting last node: ");
printList(last);
}
}
JavaScript Implementation
class Node {
constructor(data) {
this.data = data;
this.next = null;
}
}
function deleteLastNode(last) {
if (!last) {
console.log("List is empty, nothing to delete.");
return null;
}
const head = last.next;
if (head === last) {
return null;
}
let curr = head;
while (curr.next !== last) {
curr = curr.next;
}
curr.next = head;
return curr;
}
function printList(last) {
if (!last) {
console.log("List is empty.");
return;
}
const head = last.next;
let temp = head;
do {
process.stdout.write(temp.data + " ");
temp = temp.next;
} while (temp !== head);
console.log();
}
function createNode(value) {
return new Node(value);
}
// Main logic
const first = createNode(2);
first.next = createNode(3);
first.next.next = createNode(4);
let last = first.next.next;
last.next = first;
console.log("Original list:");
printList(last);
last = deleteLastNode(last);
console.log("List after deleting last node:");
printList(last);
Python Implementation
class Node:
def __init__(self, data):
self.data = data
self.next = None
def delete_last_node(last):
if not last:
print("List is empty, nothing to delete.")
return None
head = last.next
if head == last:
return None
curr = head
while curr.next != last:
curr = curr.next
curr.next = head
return curr
def print_list(last):
if not last:
print("List is empty.")
return
head = last.next
temp = head
while True:
print(temp.data, end=" ")
temp = temp.next
if temp == head:
break
print()
# Main logic
first = Node(2)
first.next = Node(3)
first.next.next = Node(4)
last = first.next.next
last.next = first
print("Original list:")
print_list(last)
last = delete_last_node(last)
print("List after deleting last node:")
print_list(last)
Output
Original list: 2 3 4
List after deleting last node: 2 3
Complexities
- Time Complexity: O(1)
- Auxiliary Space: O(1)
Key Takeaways
- Circular Linked List: This data structure requires special handling due to its circular nature.
- Memory Management: Properly deleting nodes and updating pointers is crucial to avoid memory leaks and ensure the integrity of the list.
- Edge Cases: Always handle edge cases, such as an empty list or a list with only one node, to prevent undefined behavior.
Conclusion
The process of deleting the last node in a circular linked list demonstrates the intricate balance between maintaining the structural integrity of a data structure and ensuring optimal memory management.
By understanding the unique properties of circular linked lists and employing careful pointer manipulation, developers can efficiently handle operations that may seem complex at first glance. Whether dealing with empty lists, single-node scenarios, or multi-node traversals, a systematic approach ensures the correctness and reliability of the program.
Mastering such operations not only enhances one’s skills in C, C++, C#, Java, JavaScript, Python, etc programming languages but also provides deeper insights into the foundational principles of computer science.
As data structures like circular linked lists continue to find applications in real-world systems, the ability to implement and manipulate them accurately remains an invaluable asset for any programmer.
Related Articles
- Introduction to Circular Linked Lists: A Comprehensive Guide
- Understanding Circular Singly Linked Lists: A Comprehensive Guide
- Circular Doubly Linked List: A Comprehensive Guide
- Insertion in Circular Singly Linked List: A Comprehensive Guide
- Insertion in an Empty Circular Linked List: A Detailed Exploration
- Insertion at the Beginning in Circular Linked List: A Detailed Exploration
- Insertion at the End of a Circular Linked List: A Comprehensive Guide
- Insertion at a Specific Position in a Circular Linked List: A Detailed Exploration
- Deletion from a Circular Linked List: A Comprehensive Guide
- Deletion from the Beginning of a Circular Linked List: A Detailed Exploration
- Deletion at Specific Position in Circular Linked List: A Detailed Exploration
- Deletion at the End of a Circular Linked List: A Comprehensive Guide
- Searching in a Circular Linked List: A Comprehensive Exploration
Read More Articles
- Data Structure (DS) Array:
- Why the Analysis of Algorithms is Important?
- Worst, Average, and Best Case Analysis of Algorithms: A Comprehensive Guide
- Understanding Pointers in C Programming: A Comprehensive Guide
- Understanding Arrays in Data Structures: A Comprehensive Exploration
- Memory Allocation of an Array: An In-Depth Comprehensive Exploration
- Understanding Basic Operations in Arrays: A Comprehensive Guide
- Understanding 2D Arrays in Programming: A Comprehensive Guide
- Mapping a 2D Array to a 1D Array: A Comprehensive Exploration
- Data Structure Linked List:
- Understanding Linked Lists in Data Structures: A Comprehensive Exploration
- Types of Linked List: Detailed Exploration, Representations, and Implementations
- Understanding Singly Linked Lists: A Detailed Exploration
- Understanding Doubly Linked List: A Comprehensive Guide
- Operations of Doubly Linked List with Implementation: A Detailed Exploration
- Insertion in Doubly Linked List with Implementation: A Detailed Exploration
- Inserting a Node at the beginning of a Doubly Linked List: A Detailed Exploration
- Inserting a Node After a Given Node in a Doubly Linked List: A Detailed Exploration
- Inserting a Node Before a Given Node in a Doubly Linked List: A Detailed Exploration
- Inserting a Node at a Specific Position in a Doubly Linked List: A Detailed Exploration
- Inserting a New Node at the End of a Doubly Linked List: A Detailed Exploration
- Deletion in a Doubly Linked List with Implementation: A Comprehensive Guide
- Deletion at the Beginning in a Doubly Linked List: A Detailed Exploration
- Deletion after a given node in Doubly Linked List: A Comprehensive Guide
- Deleting a Node Before a Given Node in a Doubly Linked List: A Detailed Exploration
- Deletion at a Specific Position in a Doubly Linked List: A Detailed Exploration
- Deletion at the End in Doubly Linked List: A Comprehensive Exploration
- Introduction to Circular Linked Lists: A Comprehensive Guide
- Understanding Circular Singly Linked Lists: A Comprehensive Guide
- Circular Doubly Linked List: A Comprehensive Guide
- Insertion in Circular Singly Linked List: A Comprehensive Guide
- Insertion in an Empty Circular Linked List: A Detailed Exploration
- Insertion at the Beginning in Circular Linked List: A Detailed Exploration
- Insertion at the End of a Circular Linked List: A Comprehensive Guide
- Insertion at a Specific Position in a Circular Linked List: A Detailed Exploration
- Deletion from a Circular Linked List: A Comprehensive Guide
- Deletion from the Beginning of a Circular Linked List: A Detailed Exploration
- Deletion at Specific Position in Circular Linked List: A Detailed Exploration
- Deletion at the End of a Circular Linked List: A Comprehensive Guide
- Searching in a Circular Linked List: A Comprehensive Exploration
Frequently Asked Questions (FAQs)
What is a circular linked list, and why is it unique?
A circular linked list is a type of linked list where the last node points back to the head, forming a loop. This structure allows continuous traversal of the list from any node. Unlike singly linked lists, circular linked lists do not have a nullptr
to signify the end of the list, which makes them efficient for applications requiring cyclic traversal, such as real-time systems or resource scheduling.
How do you identify the head in a circular linked list?
In a circular linked list, the head node is the node pointed to by last->next
. Since the last
pointer always points to the last node, its next
pointer links back to the head, providing a way to access the starting point of the list.
What challenges arise when deleting nodes in a circular linked list?
The key challenges include:
- Maintaining the circular structure by correctly updating pointers.
- Handling edge cases such as empty lists or lists with only one node.
- Ensuring proper memory management to avoid memory leaks.
What happens if you try to delete from an empty circular linked list?
If the last
pointer is nullptr
, the list is empty, and no deletion can occur. Attempting to access or modify nodes in this state would lead to undefined behavior. Proper checks should be implemented to handle this scenario gracefully.
How do you delete the only node in a circular linked list?
When the list contains only one node, the head
is equal to last
. Deleting this node involves releasing its memory and setting the last
pointer to nullptr
, making the list empty.
How do you locate the second last node in a circular linked list?
To find the second last node, start from the head and traverse the list until you reach the node whose next
pointer points to last
. This requires iterating through the nodes and carefully evaluating the pointer conditions.
Why is pointer manipulation critical in circular linked lists?
Pointer manipulation ensures the circular nature of the list is preserved during operations like insertion or deletion. Failing to update pointers correctly can lead to broken loops or memory leaks, compromising the list’s integrity.
Can you explain the importance of memory management in circular linked lists?
Memory management is crucial to prevent leaks and ensure efficient use of resources. When deleting nodes, the memory occupied by those nodes must be explicitly freed, especially in languages like C++, where garbage collection is not automatic.
How does deleting the last node affect the circular structure?
Deleting the last node requires updating the second last node’s next
pointer to point to the head. This preserves the loop and ensures the list remains circular even after the deletion.
What are the real-world applications of circular linked lists?
Circular linked lists are widely used in:
- Operating Systems: For scheduling processes in round-robin algorithms.
- Data Buffers: In scenarios requiring continuous data flow, like network buffers.
- Gaming Systems: To manage player turns in multiplayer games.
Their cyclic nature makes them ideal for applications where repetitive traversal is required.
What is a circular linked list, and how does it differ from other linked lists?
A circular linked list is a type of linked list where the last node points back to the head node, forming a continuous loop. This is different from a singly linked list, where the last node points to nullptr
, and a doubly linked list, which has pointers to both the previous and next nodes but is not circular by default.
The circular nature of this data structure allows traversal from any node to all other nodes without needing a specific starting or ending point. This makes certain operations, like insertion and deletion, more efficient in some scenarios. However, it also introduces complexities, especially when maintaining the circular structure during deletions.
Why is deleting the last node in a circular linked list more complex than in a singly linked list?
Deleting the last node in a circular linked list requires additional steps to maintain the circular structure. Unlike in a singly linked list, where you can simply set the second last node’s next
pointer to nullptr
, in a circular linked list, you must ensure that the second last node points back to the head node.
Moreover, identifying the second last node involves traversing the entire list since there’s no direct reference to it. These steps require careful manipulation of pointers to avoid breaking the circular nature of the list.
What happens if you try to delete a node from an empty circular linked list?
If the circular linked list is empty (i.e., the last
pointer is nullptr
), there are no nodes to delete. Attempting to delete a node in such a scenario should be handled gracefully by checking if the last
pointer is nullptr
and returning without making changes.
Example Implementation:
if (last == nullptr) {
std::cout << "List is empty, nothing to delete." << std::endl;
return nullptr;
}
This ensures the program does not access invalid memory or crash due to dereferencing a null pointer.
How can you identify a single-node circular linked list?
In a single-node circular linked list, the last
pointer and the head
pointer refers to the same node. This unique property makes it easy to identify such lists.
Example Check:
if (head == last) {
// Single-node circular linked list
}
Handling single-node cases is crucial because deleting this node results in an empty list, requiring the last
pointer to be set to nullptr
.
What steps are involved in deleting the last node from a single-node circular linked list?
To delete the last node from a single-node circular linked list:
- Check if the list is empty (
last == nullptr
). - Confirm that the
head
is equal tolast
, indicating a single-node list. - Delete the node using
delete last
. - Set the
last
pointer tonullptr
to signify the list is now empty.
Example Code:
if (head == last) {
delete last;
last = nullptr;
}
How do you find the second last node in a circular linked list?
Finding the second last node involves traversing the list from the head and stopping when the next
pointer of the current node points to the last
node.
Example Code:
Node* curr = head;
while (curr->next != last) {
curr = curr->next;
}
This traversal ensures you locate the second last node, which is required to update its next
pointer during deletion.
Why is it necessary to update the second last node’s pointer during deletion?
In a circular linked list, the second last node’s next
pointer must point back to the head to maintain the circular structure after deleting the last node. Failure to update this pointer breaks the circularity, rendering the list invalid.
Example Update:
curr->next = head;
How do you delete the last node in a multi-node circular linked list?
To delete the last node in a multi-node circular linked list:
- Check if the list is empty.
- Retrieve the head node (
head = last->next
). - Find the second last node.
- Update the second last node’s
next
pointer to point to the head. - Delete the last node using
delete last
. - Update the
last
pointer to the second last node.
Complete Code Example:
if (last != nullptr) {
Node* head = last->next;
Node* curr = head;
while (curr->next != last) {
curr = curr->next;
}
curr->next = head;
delete last;
last = curr;
}
How do you handle memory management during deletion?
Proper memory management ensures no memory leaks occur when deleting a node. Always use delete
to free the memory allocated for the last node and update pointers to prevent dangling references.
What are common edge cases to consider when deleting the last node?
Edge cases include:
- An empty list (
last == nullptr
). - A single-node list (
head == last
). - Multi-node lists where traversal is required.
- Ensuring the
last
pointer is updated correctly.