Split a Circular Linked List into two halves

Asked by Bharani

                         Original Linked List  

                         Result Linked List 1  

                         Result Linked List 2  

Thanks to Geek4u for suggesting the algorithm.
1) Store the mid and last pointers of the circular linked list using tortoise and hare algorithm.
2) Make the second half circular.
3) Make the first half circular.
4) Set head (or start) pointers of the two linked lists.

In the below implementation, if there are odd nodes in the given circular linked list then the first result list has 1 more node than the second result list.

C

/* Program to split a circular linked list into two halves */
#include<stdio.h> 
#include<stdlib.h> 

/* structure for a node */
struct node
{
  int data;
  struct node *next;
}; 

/* Function to split a list (starting with head) into two lists.
   head1_ref and head2_ref are references to head nodes of 
    the two resultant linked lists */
void splitList(struct node *head, struct node **head1_ref, 
                                            struct node **head2_ref)
{
  struct node *slow_ptr = head;
  struct node *fast_ptr = head; 

  if(head == NULL)
    return;
 
  /* If there are odd nodes in the circular list then
     fast_ptr->next becomes head and for even nodes 
     fast_ptr->next->next becomes head */
  while(fast_ptr->next != head &&
         fast_ptr->next->next != head) 
  {
     fast_ptr = fast_ptr->next->next;
     slow_ptr = slow_ptr->next;
  }  

 /* If there are even elements in list then move fast_ptr */
  if(fast_ptr->next->next == head)
    fast_ptr = fast_ptr->next;      
  
  /* Set the head pointer of first half */
  *head1_ref = head;    
     
  /* Set the head pointer of second half */
  if(head->next != head)
    *head2_ref = slow_ptr->next;
  
  /* Make second half circular */   
  fast_ptr->next = slow_ptr->next;
  
  /* Make first half circular */   
  slow_ptr->next = head;       
}

/* UTILITY FUNCTIONS */
/* Function to insert a node at the begining of a Circular 
   linked lsit */
void push(struct node **head_ref, int data)
{
  struct node *ptr1 = (struct node *)malloc(sizeof(struct node));
  struct node *temp = *head_ref; 
  ptr1->data = data;  
  ptr1->next = *head_ref; 
  
  /* If linked list is not NULL then set the next of 
    last node */
  if(*head_ref != NULL)
  {
    while(temp->next != *head_ref)
      temp = temp->next;        
    temp->next = ptr1; 
  }
  else
     ptr1->next = ptr1; /*For the first node */

  *head_ref = ptr1;     
} 

/* Function to print nodes in a given Circular linked list */
void printList(struct node *head)
{
  struct node *temp = head; 
  if(head != NULL)
  {
    printf("\n");
    do {
      printf("%d ", temp->data);
      temp = temp->next;
    } while(temp != head);
  }
}

/* Driver program to test above functions */
int main()
{
  int list_size, i; 
  
  /* Initialize lists as empty */
  struct node *head = NULL;
  struct node *head1 = NULL;
  struct node *head2 = NULL;  

  /* Created linked list will be 12->56->2->11 */
  push(&head, 12); 
  push(&head, 56);   
  push(&head, 2);   
  push(&head, 11);   

  printf("Original Circular Linked List");
  printList(head);      
 
  /* Split the list */ 
  splitList(head, &head1, &head2);
 
  printf("\nFirst Circular Linked List");
  printList(head1);  

  printf("\nSecond Circular Linked List");
  printList(head2);  
  
  getchar();
  return 0;
} 

Java

// Java program to delete a node from doubly linked list

class LinkedList {

    static Node head, head1, head2;

    static class Node {

        int data;
        Node next, prev;

        Node(int d) {
            data = d;
            next = prev = null;
        }
    }

    /* Function to split a list (starting with head) into two lists.
     head1_ref and head2_ref are references to head nodes of 
     the two resultant linked lists */
    void splitList() {
        Node slow_ptr = head;
        Node fast_ptr = head;

        if (head == null) {
            return;
        }

        /* If there are odd nodes in the circular list then
         fast_ptr->next becomes head and for even nodes 
         fast_ptr->next->next becomes head */
        while (fast_ptr.next != head
                && fast_ptr.next.next != head) {
            fast_ptr = fast_ptr.next.next;
            slow_ptr = slow_ptr.next;
        }

        /* If there are even elements in list then move fast_ptr */
        if (fast_ptr.next.next == head) {
            fast_ptr = fast_ptr.next;
        }

        /* Set the head pointer of first half */
        head1 = head;

        /* Set the head pointer of second half */
        if (head.next != head) {
            head2 = slow_ptr.next;
        }
        /* Make second half circular */
        fast_ptr.next = slow_ptr.next;

        /* Make first half circular */
        slow_ptr.next = head;
    }

    /* Function to print nodes in a given singly linked list */
    void printList(Node node) {
        Node temp = node;
        if (node != null) {
            do {
                System.out.print(temp.data + " ");
                temp = temp.next;
            } while (temp != node);
        }
    }

    public static void main(String[] args) {
        LinkedList list = new LinkedList();

        //Created linked list will be 12->56->2->11
        list.head = new Node(12);
        list.head.next = new Node(56);
        list.head.next.next = new Node(2);
        list.head.next.next.next = new Node(11);
        list.head.next.next.next.next = list.head;

        System.out.println("Original Circular Linked list ");
        list.printList(head);

        // Split the list
        list.splitList();
        System.out.println("");
        System.out.println("First Circular List ");
        list.printList(head1);
        System.out.println("");
        System.out.println("Second Circular List ");
        list.printList(head2);
        
    }
}

// This code has been contributed by Mayank Jaiswal

Python


# Python program to split circulart linked list into two halves

# A node structure
class Node:
    
    # Constructor to create a new node
    def __init__(self, data):
        self.data = data
        self.next = None


# Class to create a new  Circular Linked list
class CircularLinkedList:
    
    # Constructor to create a empty circular linked list
    def __init__(self):
        self.head = None

    # Function to insert a node at the beginning of a
    # circular linked list
    def push(self, data):
        ptr1 = Node(data)
        temp = self.head
        
        ptr1.next = self.head

        # If linked list is not None then set the next of
        # last node
        if self.head is not None:
            while(temp.next != self.head):
                temp = temp.next 
            temp.next = ptr1

        else:
            ptr1.next = ptr1 # For the first node

        self.head = ptr1 

    # Function to print nodes in a given circular linked list
    def printList(self):
        temp = self.head
        if self.head is not None:
            while(True):
                print "%d" %(temp.data),
                temp = temp.next
                if (temp == self.head):
                    break 


    # Function to split a list (starting with head) into 
    # two lists. head1 and head2 are the head nodes of the
    # two resultant linked lists
    def splitList(self, head1, head2):
        slow_ptr = self.head 
        fast_ptr = self.head
    
        if self.head is None:
            return 
        
        # If htere are odd nodes in the circular list then
        # fast_ptr->next becomes head and for even nodes
        # fast_ptr->next->next becomes head
        while(fast_ptr.next != self.head and 
            fast_ptr.next.next != self.head ):
            fast_ptr = fast_ptr.next.next
            slow_ptr = slow_ptr.next

        # If there are event elements in list then
        # move fast_ptr
        if fast_ptr.next.next == self.head:
            fast_ptr = fast_ptr.next

        # Set the head pointer of first half
        head1.head = self.head

        # Set the head pointer of second half
        if self.head.next != self.head:
            head2.head = slow_ptr.next

        # Make second half circular
        fast_ptr.next = slow_ptr.next
    
        # Make first half circular
        slow_ptr.next = self.head


# Driver program to test above functions

# Initialize lists as empty
head = CircularLinkedList() 
head1 = CircularLinkedList()
head2 = CircularLinkedList()

head.push(12)
head.push(56)
head.push(2)
head.push(11)

print "Original Circular Linked List"
head.printList()

# Split the list 
head.splitList(head1 , head2)

print "\nFirst Circular Linked List"
head1.printList()

print "\nSecond Circular Linked List"
head2.printList()

# This code is contributed by Nikhil Kumar Singh(nickzuck_007)

Output:

Original Circular Linked List
11 2 56 12 
First Circular Linked List
11 2 
Second Circular Linked List
56 12 

Time Complexity: O(n)

Please write comments if you find any bug in above code/algorithm, or find other ways to solve the same problem

GATE CS Corner    Company Wise Coding Practice





Writing code in comment? Please use code.geeksforgeeks.org, generate link and share the link here.