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)
Updated on: 2025-04-24T10:41:46+05:30

37 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements