
Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
C++ Program to Split a Circular Linked List
A circular linked list is a type of linked list where the last node and first node are the same, forming a loop. There are many real-life applications of splitting a circular linked list into two halves for easier processing, load balancing, or efficient data manipulation.
In this article, we are going to learn different approaches to split a circular linked list into two halves in C++.
What is the Splitting of a Circular Linked List?
Splitting of a Circular linked list is dividing the given linked list into two separate linked lists:
- If the total number of nodes in the original linked list is even, then both linked lists have an equal number of nodes.
- If the total number of nodes in the original linked list is odd, then one extra node is added in the first half of the linked list.
Let's understand this with given example below:
Input: Circular Linked List: 1 ? 2 ? 3 ? 4 ? 5 ? 6 ? (back to first node i.e. 1) Output: First Half: 1 ? 2 ? 3 ? (back to 1) Second Half: 4 ? 5 ? 6 ? (back to 4)
Below are different approaches to split a circular linked list into two halves:
Using Node Counting Method
This is a kind of brute force approach. This is a simple and direct approach. In this approach, we count the total number of nodes and then iterate again to split the list into two halves.
- We define a function and take the circular linked list as a parameter.
- Now, count the total number of nodes in the linked list.
- Iterate through the linked list again and divide it into two halves at the middle.
- Adjust the last nodes of both halves to make them circular.
- Return both halves of the linked list.
Example
Here is an example code implementing above steps to split a circular linked list using node counting method.
#include <bits/stdc++.h> using namespace std; struct Node { int data; Node *next; Node(int val) { data = val; next = nullptr; } }; void splitCircularList(Node *head, Node **head1, Node **head2) { if (!head) return; Node *slow = head, *fast = head; while (fast->next != head && fast->next->next != head) { slow = slow->next; fast = fast->next->next; } if (fast->next->next == head) fast = fast->next; *head1 = head; *head2 = slow->next; fast->next = *head2; slow->next = *head1; } void printList(Node *head) { Node *temp = head; if (!head) return; do { cout << temp->data << " -> "; temp = temp->next; } while (temp != head); cout << "(back to " << head->data << ")" << endl; } int main() { Node *head = new Node(1); head->next = new Node(2); head->next->next = new Node(3); head->next->next->next = new Node(4); head->next->next->next->next = new Node(5); head->next->next->next->next->next = head; Node *head1 = nullptr, *head2 = nullptr; splitCircularList(head, &head1, &head2); cout << "First Half: "; printList(head1); cout << "Second Half: "; printList(head2); return 0; }
Using Fast and Slow Pointer Approach
In this approach, we use two pointers, i.e., slow and fast pointers. Slow Pointer moves one step at a time, whereas Fast Pointer moves two steps at a time. When the fast pointer reaches the last node, the slow pointer will be at the middle of the linked list. The list is then divided into two halves, i.e., into two circular linked lists.
- Define a structure for the circular linked list.
- Now, use the slow and fast pointer approach to find the middle node of the linked list.
- Break the circular link and create two separate circular linked lists.
- Print both circular halves.
Example
The following example code uses fast and slow pointers to split a circular linked list.
#include <bits/stdc++.h> using namespace std; class Node { public: int data; Node *next; }; void splitCircularList(Node *head, Node **head1, Node **head2) { if (!head) return; Node *slow = head; Node *fast = head; while (fast->next != head && fast->next->next != head) { slow = slow->next; fast = fast->next->next; } if (fast->next->next == head) fast = fast->next; *head1 = head; *head2 = slow->next; slow->next = *head1; fast->next = *head2; } void insert(Node **head, int data) { Node *newNode = new Node(); newNode->data = data; newNode->next = *head; if (*head == NULL) { *head = newNode; newNode->next = *head; } else { Node *temp = *head; while (temp->next != *head) temp = temp->next; temp->next = newNode; } } void printList(Node *head) { if (!head) return; Node *temp = head; do { cout << temp->data << " "; temp = temp->next; } while (temp != head); cout << endl; } int main() { Node *head = NULL; Node *head1 = NULL; Node *head2 = NULL; insert(&head, 10); insert(&head, 20); insert(&head, 30); insert(&head, 40); insert(&head, 50); insert(&head, 60); cout << "Original Circular Linked List: "; printList(head); splitCircularList(head, &head1, &head2); cout << "First Half: "; printList(head1); cout << "Second Half: "; printList(head2); return 0; }
Complexity Comparison
Here is a comparison of time and space complexity of all the above approaches.
Approach | Time Complexity | Space Complexity |
---|---|---|
Node Counting Method | O(n) | O(1) |
Fast and Slow Pointer | O(n) | O(1) |