Iterative Merge Sort for Linked List - GeeksforGeeks

31 Oct, 2021
Given a singly linked list of integers, the task is to sort it using iterative merge sort. 
 
Merge Sort is often preferred for sorting a linked list. It is discussed here. However, the method discussed above uses Stack for storing recursion calls. This may consume a lot of memory if the linked list to be sorted is too large. Hence, a purely iterative method for Merge Sort with no recursive calls is discussed in this post.We use bottom-up approach of Merge Sort in this post. We know that Merge Sort first merges two items, then 4 items and so on. The idea is to use an integer variable to store the gap to find the midpoint around which the linked list needs to be sorted. So the problem reduces to merging two sorted Linked List which is discussed here. However, we do not use an additional list to keep the merged list. Instead we merge the lists within itself. The gap is incremented exponentially by 2 in each iteration and the process is repeated. 
C++
Java
Python3
C#
Javascript
// Iterative C++ program to do merge sort on// linked list#include <iostream>using namespace std; /* Structure of the Node */struct Node {    int data;    struct Node* next;};  /* Function to calculate length of linked list */int length(struct Node* current){    int count = 0;    while (current != NULL) {        current = current->next;        count++;    }    return count;} /* Merge function of Merge Sort to Merge the two sorted parts   of the Linked List. We compare the next value of start1 and   current value of start2 and insert start2 after start1 if   it's smaller than next value of start1. We do this until   start1 or start2 end. If start1 ends, then we assign next   of start1 to start2 because start2 may have some elements   left out which are greater than the last value of start1.   If start2 ends then we assign end2 to end1. This is necessary   because we use end2 in another function (mergeSort function)   to determine the next start1 (i.e) start1 for next   iteration = end2->next */void merge(struct Node** start1, struct Node** end1,          struct Node** start2, struct Node** end2){     // Making sure that first node of second    // list is higher.    struct Node* temp = NULL;    if ((*start1)->data > (*start2)->data) {        swap(*start1, *start2);        swap(*end1, *end2);    }     // Merging remaining nodes    struct Node* astart = *start1, *aend = *end1;    struct Node* bstart = *start2, *bend = *end2;    struct Node* bendnext = (*end2)->next;    while (astart != aend && bstart != bendnext) {        if (astart->next->data > bstart->data) {            temp = bstart->next;            bstart->next = astart->next;            astart->next = bstart;            bstart = temp;        }        astart = astart->next;    }    if (astart == aend)        astart->next = bstart;    else        *end2 = *end1;} /* MergeSort of Linked List   The gap is initially 1. It is incremented as   2, 4, 8, .. until it reaches the length of the   linked list. For each gap, the linked list is   sorted around the gap.   The prevend stores the address of the last node after   sorting a part of linked list so that it's next node   can be assigned after sorting the succeeding list.   temp is used to store the next start1 because after   sorting, the last node will be different. So it   is necessary to store the address of start1 before   sorting. We select the start1, end1, start2, end2 for   sorting. start1 - end1 may be considered as a list   and start2 - end2 may be considered as another list   and we are merging these two sorted list in merge   function and assigning the starting address to the   previous end address. */void mergeSort(struct Node** head){    if (*head == NULL)        return;    struct Node* start1 = NULL, *end1 = NULL;    struct Node* start2 = NULL, *end2 = NULL;    struct Node* prevend = NULL;    int len = length(*head);     for (int gap = 1; gap < len; gap = gap*2) {        start1 = *head;        while (start1) {             // If this is first iteration            bool isFirstIter = 0;            if (start1 == *head)                isFirstIter = 1;             // First part for merging            int counter = gap;            end1 = start1;            while (--counter && end1->next)                end1 = end1->next;             // Second part for merging            start2 = end1->next;            if (!start2)                break;            counter = gap;            end2 = start2;            while (--counter && end2->next)                end2 = end2->next;             // To store for next iteration.            Node *temp = end2->next;             // Merging two parts.            merge(&start1, &end1, &start2, &end2);             // Update head for first iteration, else            // append after previous list            if (isFirstIter)                *head = start1;            else                prevend->next = start1;             prevend = end2;            start1 = temp;        }        prevend->next = start1;    }}  /* Function to print the Linked List */void print(struct Node** head){    if ((*head) == NULL)        return;    struct Node* temp = *head;    while (temp != NULL) {        printf("%d ", temp->data);        temp = temp->next;    }    printf("\n");}  /* Given a reference (pointer to     pointer) to the head of a list    and an int, push a new node on    the front of the list. */void push(struct Node** head_ref,          int new_data){    struct Node* new_node = new Node;    new_node->data = new_data;    new_node->next = (*head_ref);    (*head_ref) = new_node;}   int main(){    // start with empty list    struct Node* head = NULL;       // create linked list    // 1->2->3->4->5->6->7    push(&head, 7);    push(&head, 6);    push(&head, 5);    push(&head, 4);    push(&head, 3);    push(&head, 2);    push(&head, 1);     mergeSort(&head);     print(&head);}
// Iterative Java program to do merge sort on// linked listclass GFG{     /* Structure of the Node */static class Node{    int data;    Node next;};  /* Function to calculate length of linked list */static int length(Node current){    int count = 0;    while (current != null)    {        current = current.next;        count++;    }    return count;} /* Merge function of Merge Sort to Merge the two sorted partsof the Linked List. We compare the next value of start1 andcurrent value of start2 and insert start2 after start1 ifit's smaller than next value of start1. We do this untilstart1 or start2 end. If start1 ends, then we assign nextof start1 to start2 because start2 may have some elementsleft out which are greater than the last value of start1.If start2 ends then we assign end2 to end1. This is necessarybecause we use end2 in another function (mergeSort function)to determine the next start1 (i.e) start1 for nextiteration = end2.next */static Node merge(Node start1, Node end1,        Node start2, Node end2){     // Making sure that first node of second    // list is higher.    Node temp = null;    if ((start1).data > (start2).data)    {        Node t = start1;        start1 = start2;        start2 = t;        t = end1;        end1 = end2;        end2 = t;    }     // Merging remaining nodes    Node astart = start1, aend = end1;    Node bstart = start2, bend = end2;    Node bendnext = (end2).next;    while (astart != aend && bstart != bendnext)    {        if (astart.next.data > bstart.data)        {            temp = bstart.next;            bstart.next = astart.next;            astart.next = bstart;            bstart = temp;        }        astart = astart.next;    }    if (astart == aend)        astart.next = bstart;    else        end2 = end1;                 return start1;} /* MergeSort of Linked ListThe gap is initially 1. It is incremented as2, 4, 8, .. until it reaches the length of thelinked list. For each gap, the linked list issorted around the gap.The prevend stores the address of the last node aftersorting a part of linked list so that it's next nodecan be assigned after sorting the succeeding list.temp is used to store the next start1 because aftersorting, the last node will be different. So itis necessary to store the address of start1 beforesorting. We select the start1, end1, start2, end2 forsorting. start1 - end1 may be considered as a listand start2 - end2 may be considered as another listand we are merging these two sorted list in mergefunction and assigning the starting address to theprevious end address. */static Node mergeSort(Node head){    if (head == null)        return head;    Node start1 = null, end1 = null;    Node start2 = null, end2 = null;    Node prevend = null;    int len = length(head);     for (int gap = 1; gap < len; gap = gap*2)    {        start1 = head;        while (start1 != null)        {             // If this is first iteration            boolean isFirstIter = false;            if (start1 == head)                isFirstIter = true;             // First part for merging            int counter = gap;            end1 = start1;            while (--counter > 0 && end1.next != null)                end1 = end1.next;             // Second part for merging            start2 = end1.next;            if (start2 == null)                break;            counter = gap;            end2 = start2;            while (--counter > 0 && end2.next != null)                end2 = end2.next;             // To store for next iteration.            Node temp = end2.next;             // Merging two parts.            merge(start1, end1, start2, end2);             // Update head for first iteration, else            // append after previous list            if (isFirstIter)                head = start1;            else                prevend.next = start1;             prevend = end2;            start1 = temp;        }        prevend.next = start1;    }    return head;}  /* Function to print the Linked List */static void print(Node head){    if ((head) == null)        return;    Node temp = head;    while (temp != null)    {        System.out.printf("%d ", temp.data);        temp = temp.next;    }    System.out.printf("\n");}  /* Given a reference (pointer topointer) to the head of a listand an int, push a new node onthe front of the list. */static Node push( Node head_ref,        int new_data){    Node new_node = new Node();    new_node.data = new_data;    new_node.next = (head_ref);    (head_ref) = new_node;    return head_ref;} public static void main(String args[]){    // start with empty list    Node head = null;         // create linked list    // 1.2.3.4.5.6.7    head = push(head, 7);    head = push(head, 6);    head = push(head, 5);    head = push(head, 4);    head = push(head, 3);    head = push(head, 2);    head = push(head, 1);     head = mergeSort(head);     print(head);}} // This code is contributed by Arnab Kundu
# Iterative Python3 program to do merge sort on# linked list class Node:       """Structure of the Node."""    def __init__(self, data: int):        self.data = data        self.next = None  class LinkedList:    """Encapsulate each left/right part's nodes in order to pass them as    pointers. Without this workaround, the code would only work for a    reverse-ordered list."""         head: Node    tail: Node         def __init__(self, head=None, tail=None):        self.start = head        self.end = tail  def list_length(current: Node):    """Function to calculate length of linked list."""    count = 0;         while (current != None):        current = current.next;        count += 1     return count;          def merge(left: LinkedList, right: LinkedList) -> None:    """Merge the two sorted parts of the original linked list in order.    Merge function of Merge Sort to Merge the two sorted parts of the    Linked List. We compare the next value of start1 and current value of    start2 and insert start2 after start1 if it's smaller than next value    of start1. We do this until start1 or start2 end. If start1 ends, then    we assign next of start1 to start2 because start2 may have some elements    left out which are greater than the last value of start1. If start2 ends    then we assign end2 to end1. This is necessary because we use end2 in    another function (mergeSort function) to determine the next start1 (i.e)    start1 for next iteration = end2.next"""         # Ensure the first node of the second list is higher.    if left.start.data > right.start.data:        left.start, right.start = right.start, left.start        left.end, right.end = right.end, left.end         # Merge all remaining nodes.    astart = left.start    aend = left.end         bstart = right.start    bendnext = right.end.next         while astart != aend and bstart != bendnext:                 if astart.next.data > bstart.data:            temp = bstart.next            bstart.next = astart.next            astart.next = bstart            bstart = temp                 astart = astart.next         if astart == aend:        astart.next = bstart         else:        right.end = left.end  def mergeSort(head: LinkedList) -> None:    """MergeSort of Linked List The gap is initially 1. It is incremented as    2, 4, 8, .. until it reaches the length of the  linked list. For each gap,    the linked list is sorted around the gap. The prevend stores the address    of the last node after sorting a part of linked list so that it's next    node can be assigned after sorting the succeeding list. temp is used to    store the next start1 because after sorting, the last node will be    different. So it is necessary to store the address of start1 before    sorting. We select the start1, end1, start2, end2 for sorting.    start1 - end1 may be considered as a list and start2 - end2 may be    considered as another list and we are merging these two sorted list in    merge function and assigning the starting address to the previous end    address."""         # Reject empty lists.    if not head:        return             gap = 1    length = list_length(head.start)         left = LinkedList()    right = LinkedList()         while gap < length:                 left.start = head.start                 while left.start:                         # If this is first iteration            isFirstIter = False                         if left.start == head.start:                isFirstIter = True                         # First part for merging            counter = gap            left.end = left.start                         counter -= 1            while counter != 0 and left.end.next:                counter -= 1                left.end = left.end.next             # Second part for merging                           right.start = left.end.next                         if not right.start:                break                         counter = gap            right.end = right.start                         counter -= 1            while counter != 0 and right.end.next:                counter -= 1                right.end = right.end.next             # To store for next iteration.                           temp = right.end.next             # Merging two parts.                       merge(left, right)                         # Update head for first iteration, else append after previous list.            if isFirstIter:                head.start = left.start                             else:                prevend.next = left.start                             prevend = right.end            left.start = temp                     gap = gap * 2                     prevend.next = left.start      def prints(head):    """Print the linked list."""         if not head:        return         temp = head         while temp:        print(temp.data, end=' ')        temp = temp.next           print()  def push(head: LinkedList, data: int) -> None:    """Given a reference (pointer to pointer) to the head of a list and an    int, push a new node on the front of the list."""    new_node = Node(data)    new_node.next = head.start    head.start = new_node  # Driver codeif __name__=='__main__':         # start with empty list    head = LinkedList()        # create linked list    # 1.2.3.4.5.6.7    push(head, 6)    push(head, 7)    push(head, 2)    push(head, 1)    push(head, 3)    push(head, 5)    push(head, 4)         mergeSort(head)    prints(head.start) # This code is contributed by har2 (har-at-usf)
// Iterative C# program to do merge sort on// linked listusing System;class GFG{     /* Structure of the Node */public class Node{    public int data;    public Node next;};  /* Function to calculate length of linked list */static int length(Node current){    int count = 0;    while (current != null)    {        current = current.next;        count++;    }    return count;} /* Merge function of Merge Sort to Merge the two sorted partsof the Linked List. We compare the next value of start1 andcurrent value of start2 and insert start2 after start1 ifit's smaller than next value of start1. We do this untilstart1 or start2 end. If start1 ends, then we assign nextof start1 to start2 because start2 may have some elementsleft out which are greater than the last value of start1.If start2 ends then we assign end2 to end1. This is necessarybecause we use end2 in another function (mergeSort function)to determine the next start1 (i.e) start1 for nextiteration = end2.next */static Node merge(Node start1, Node end1,        Node start2, Node end2){     // Making sure that first node of second    // list is higher.    Node temp = null;    if ((start1).data > (start2).data)    {        Node t = start1;        start1 = start2;        start2 = t;        t = end1;        end1 = end2;        end2 = t;    }     // Merging remaining nodes    Node astart = start1, aend = end1;    Node bstart = start2, bend = end2;    Node bendnext = (end2).next;    while (astart != aend && bstart != bendnext)    {        if (astart.next.data > bstart.data)        {            temp = bstart.next;            bstart.next = astart.next;            astart.next = bstart;            bstart = temp;        }        astart = astart.next;    }    if (astart == aend)        astart.next = bstart;    else        end2 = end1;                 return start1;} /* MergeSort of Linked ListThe gap is initially 1. It is incremented as2, 4, 8, .. until it reaches the length of thelinked list. For each gap, the linked list issorted around the gap.The prevend stores the address of the last node aftersorting a part of linked list so that it's next nodecan be assigned after sorting the succeeding list.temp is used to store the next start1 because aftersorting, the last node will be different. So itis necessary to store the address of start1 beforesorting. We select the start1, end1, start2, end2 forsorting. start1 - end1 may be considered as a listand start2 - end2 may be considered as another listand we are merging these two sorted list in mergefunction and assigning the starting address to theprevious end address. */static Node mergeSort(Node head){    if (head == null)        return head;    Node start1 = null, end1 = null;    Node start2 = null, end2 = null;    Node prevend = null;    int len = length(head);     for (int gap = 1; gap < len; gap = gap*2)    {        start1 = head;        while (start1 != null)        {             // If this is first iteration            Boolean isFirstIter = false;            if (start1 == head)                isFirstIter = true;             // First part for merging            int counter = gap;            end1 = start1;            while (--counter > 0 && end1.next != null)                end1 = end1.next;             // Second part for merging            start2 = end1.next;            if (start2 == null)                break;            counter = gap;            end2 = start2;            while (--counter > 0 && end2.next != null)                end2 = end2.next;             // To store for next iteration.            Node temp = end2.next;             // Merging two parts.            merge(start1, end1, start2, end2);             // Update head for first iteration, else            // append after previous list            if (isFirstIter)                head = start1;            else                prevend.next = start1;             prevend = end2;            start1 = temp;        }        prevend.next = start1;    }    return head;} /* Function to print the Linked List */static void print(Node head){    if ((head) == null)        return;    Node temp = head;    while (temp != null)    {        Console.Write( temp.data + " ");        temp = temp.next;    }    Console.Write("\n");} /* Given a reference (pointer topointer) to the head of a listand an int, push a new node onthe front of the list. */static Node push( Node head_ref,                    int new_data){    Node new_node = new Node();    new_node.data = new_data;    new_node.next = (head_ref);    (head_ref) = new_node;    return head_ref;} // Driver codepublic static void Main(String []args){    // start with empty list    Node head = null;         // create linked list    // 1.2.3.4.5.6.7    head = push(head, 7);    head = push(head, 6);    head = push(head, 5);    head = push(head, 4);    head = push(head, 3);    head = push(head, 2);    head = push(head, 1);     head = mergeSort(head);     print(head);}} // This code is contributed by Arnab Kundu
<script>       // Iterative JavaScript program to do merge sort on      // linked list      /* Structure of the Node */      class Node {        constructor() {          this.data = 0;          this.next = null;        }      }       /* Function to calculate length of linked list */      function length(current) {        var count = 0;        while (current != null) {          current = current.next;          count++;        }        return count;      }       /* Merge function of Merge Sort to Merge the two sorted partsof the Linked List. We compare the next value of start1 andcurrent value of start2 and insert start2 after start1 ifit's smaller than next value of start1. We do this untilstart1 or start2 end. If start1 ends, then we assign nextof start1 to start2 because start2 may have some elementsleft out which are greater than the last value of start1.If start2 ends then we assign end2 to end1. This is necessarybecause we use end2 in another function (mergeSort function)to determine the next start1 (i.e) start1 for nextiteration = end2.next */      function merge(start1, end1, start2, end2) {        // Making sure that first node of second        // list is higher.        var temp = null;        if (start1.data > start2.data) {          var t = start1;          start1 = start2;          start2 = t;          t = end1;          end1 = end2;          end2 = t;        }         // Merging remaining nodes        var astart = start1,          aend = end1;        var bstart = start2,          bend = end2;        var bendnext = end2.next;        while (astart != aend && bstart != bendnext) {          if (astart.next.data > bstart.data) {            temp = bstart.next;            bstart.next = astart.next;            astart.next = bstart;            bstart = temp;          }          astart = astart.next;        }        if (astart == aend) astart.next = bstart;        else end2 = end1;         return start1;      }       /* MergeSort of Linked ListThe gap is initially 1. It is incremented as2, 4, 8, .. until it reaches the length of thelinked list. For each gap, the linked list issorted around the gap.The prevend stores the address of the last node aftersorting a part of linked list so that it's next nodecan be assigned after sorting the succeeding list.temp is used to store the next start1 because aftersorting, the last node will be different. So itis necessary to store the address of start1 beforesorting. We select the start1, end1, start2, end2 forsorting. start1 - end1 may be considered as a listand start2 - end2 may be considered as another listand we are merging these two sorted list in mergefunction and assigning the starting address to theprevious end address. */      function mergeSort(head) {        if (head == null) return head;        var start1 = null,          end1 = null;        var start2 = null,          end2 = null;        var prevend = null;        var len = length(head);         for (var gap = 1; gap < len; gap = gap * 2) {          start1 = head;          while (start1 != null) {            // If this is first iteration            var isFirstIter = false;            if (start1 == head) isFirstIter = true;             // First part for merging            var counter = gap;            end1 = start1;            while (--counter > 0 && end1.next != null)            end1 = end1.next;             // Second part for merging            start2 = end1.next;            if (start2 == null) break;            counter = gap;            end2 = start2;            while (--counter > 0 && end2.next != null)            end2 = end2.next;             // To store for next iteration.            var temp = end2.next;             // Merging two parts.            merge(start1, end1, start2, end2);             // Update head for first iteration, else            // append after previous list            if (isFirstIter) head = start1;            else prevend.next = start1;             prevend = end2;            start1 = temp;          }          prevend.next = start1;        }        return head;      }       /* Function to print the Linked List */      function print(head) {        if (head == null) return;        var temp = head;        while (temp != null) {          document.write(temp.data + " ");          temp = temp.next;        }        document.write("<br>");      }       /* Given a reference (pointer topointer) to the head of a listand an int, push a new node onthe front of the list. */      function push(head_ref, new_data) {        var new_node = new Node();        new_node.data = new_data;        new_node.next = head_ref;        head_ref = new_node;        return head_ref;      }       // Driver code      // start with empty list      var head = null;       // create linked list      // 1.2.3.4.5.6.7      head = push(head, 7);      head = push(head, 6);      head = push(head, 5);      head = push(head, 4);      head = push(head, 3);      head = push(head, 2);      head = push(head, 1);       head = mergeSort(head);       print(head);       </script>
1 2 3 4 5 6 7 

Time Complexity : O(n Log n) Auxiliary Space : O(1) 
andrew1234
rutvik_56
rdtank
har2
Linked-List-Sorting
Merge Sort
Linked List
Linked List
Merge Sort
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Delete a Linked List node at a given position
Queue - Linked List Implementation
Implement a stack using singly linked list
Implementing a Linked List in Java using Class
Circular Linked List | Set 1 (Introduction and Applications)
Remove duplicates from a sorted linked list
Function to check if a singly linked list is palindrome
Find Length of a Linked List (Iterative and Recursive)
Top 20 Linked List Interview Question
Remove duplicates from an unsorted linked list