Open In App

Merge Sort for Linked Lists

Last Updated : 19 Sep, 2024
Comments
Improve
Suggest changes
314 Likes
Like
Report

Given a singly linked list, The task is to sort the linked list in non-decreasing order using merge sort.

Examples:

Input: 40 -> 20 -> 60 -> 10 -> 50 -> 30 -> NULL
Output: 10 -> 20 -> 30 -> 40 -> 50 -> 60 -> NULL

Input: 9 -> 5 -> 2 -> 8 -> NULL
Output: 2 -> 5 -> 8 -> 9 -> NULL

Approach:

The prerequisite for this problem is Merge Sort. Here we have to maintain a MergeSort function that sorts the list in three steps:

  1. Split the List into Two Halves: Use two pointers, fast and slow, starting at the head. Move fast two steps and slow one step. When fast reaches the end, slow is at the midpoint. Split the list into two halves: the first half from head to just before slow, and the second from slow->next to the end. Set slow->next to NULL.
  2. Apply MergeSort Recursively: Recursively call MergeSort() on both halves. The base case is when the list is empty (head == NULL) or has one node (head->next == NULL), in which case return the list as is.
  3. Merge the Two Sorted Halves: After sorting both halves, call merge() to merge them by comparing nodes and linking accordingly. Append any remaining nodes from the exhausted half. Finally, returns the new head of the sorted list.
C++
// C++ program for merge sort on singly linked list

#include <iostream>
using namespace std;

class Node {
  public:
    int data;
    Node *next;
    Node(int x) {
        data = x;
        next = nullptr;
    }
};

// Function to split the singly linked list into two halves
Node *split(Node *head) {
    Node *fast = head;
    Node *slow = head;

    // Move fast pointer two steps and slow pointer
    // one step until fast reaches the end
    while (fast != nullptr && fast->next != nullptr) {
        fast = fast->next->next;
        if (fast != nullptr) {
            slow = slow->next;
        }
    }

    // Split the list into two halves
    Node *temp = slow->next;
    slow->next = nullptr;
    return temp;
}

// Function to merge two sorted singly linked lists
Node *merge(Node *first, Node *second) {
  
    // If either list is empty, return the other list
    if (first == nullptr) return second;
    if (second == nullptr) return first;

    // Pick the smaller value between first and second nodes
    if (first->data < second->data) {

        // Recursively merge the rest of the lists and
        // link the result to the current node
        first->next = merge(first->next, second);
        return first;
    }
    else {
        // Recursively merge the rest of the lists
        // and link the result to the current node
        second->next = merge(first, second->next);
        return second;
    }
}

// Function to perform merge sort on a singly linked list
Node *MergeSort(Node *head) {
  
    // Base case: if the list is empty or has only one node, 
    // it's already sorted
    if (head == nullptr || head->next == nullptr)
        return head;

    // Split the list into two halves
    Node *second = split(head);

    // Recursively sort each half
    head = MergeSort(head);
    second = MergeSort(second);

    // Merge the two sorted halves
    return merge(head, second);
}

void printList(Node *head) {
    Node *curr = head;
    while (curr != nullptr) {
        cout << curr->data << " ";
        curr = curr->next;
    }
    cout << endl;
}

int main() {
      
    // Create a hard-coded singly linked list:
    // 9 -> 8 -> 5 -> 2
    Node *head = new Node(9);
    head->next = new Node(8);
    head->next->next = new Node(5);
    head->next->next->next = new Node(2);

    head = MergeSort(head);
    printList(head);

    return 0;
}
C Java Python C# JavaScript

Output
2 5 8 9 

Time Complexity: O(n*log(n))
Auxiliary Space: O(logn)



Next Article

Similar Reads