Merge Sort for Linked Lists
Last Updated :
19 Sep, 2024
Improve
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 -> NULLInput: 9 -> 5 -> 2 -> 8 -> NULL
Output: 2 -> 5 -> 8 -> 9 -> NULL
Try it on GfG Practice
Approach:
The prerequisite for this problem is Merge Sort. Here we have to maintain a MergeSort function that sorts the list in three steps:
- 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.
- 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.
- 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++ 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 program for merge sort on singly linked list
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
// Function to split the singly linked list into two halves
struct Node* split(struct Node* head) {
struct Node* fast = head;
struct Node* slow = head;
// Move fast pointer two steps and slow pointer
// one step until fast reaches the end
while (fast != NULL && fast->next != NULL) {
fast = fast->next->next;
if (fast != NULL) {
slow = slow->next;
}
}
// Split the list into two halves
struct Node* temp = slow->next;
slow->next = NULL;
return temp;
}
// Function to merge two sorted singly linked lists
struct Node* merge(struct Node* first, struct Node* second) {
// If either list is empty, return the other list
if (first == NULL) return second;
if (second == NULL) 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
struct Node* MergeSort(struct Node* head) {
// Base case: if the list is empty or has only one node,
// it's already sorted
if (head == NULL || head->next == NULL) {
return head;
}
// Split the list into two halves
struct 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(struct Node* head) {
struct Node* curr = head;
while (curr != NULL) {
printf("%d ", curr->data);
curr = curr->next;
}
printf("\n");
}
// Function to create a new node
struct Node* createNode(int x) {
struct Node* newNode =
(struct Node*)malloc(sizeof(struct Node));
newNode->data = x;
newNode->next = NULL;
return newNode;
}
int main() {
// Create a hard-coded singly linked list:
// 9 -> 8 -> 5 -> 2
struct Node* head = createNode(9);
head->next = createNode(8);
head->next->next = createNode(5);
head->next->next->next = createNode(2);
head = MergeSort(head);
printList(head);
return 0;
}
// Java program for merge sort on singly linked list
class Node {
int data;
Node next;
Node(int x) {
data = x;
next = null;
}
}
// Function to split the singly linked list into two halves
class GfG {
static 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 != null && fast.next != null) {
fast = fast.next.next;
if (fast != null) {
slow = slow.next;
}
}
// Split the list into two halves
Node temp = slow.next;
slow.next = null;
return temp;
}
// Function to merge two sorted singly linked lists
static Node merge(Node first, Node second) {
// If either list is empty, return the other list
if (first == null) return second;
if (second == null) 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
static Node mergeSort(Node head) {
// Base case: if the list is empty or has only one node,
// it's already sorted
if (head == null || head.next == null) {
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);
}
static void printList(Node head) {
Node curr = head;
while (curr != null) {
System.out.print(curr.data + " ");
curr = curr.next;
}
System.out.println();
}
public static void main(String[] args) {
// 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);
}
}
# Python program for merge sort on singly linked list
class Node:
def __init__(self, x):
self.data = x
self.next = None
def split(head):
fast = head
slow = head
# Move fast pointer two steps and slow pointer
# one step until fast reaches the end
while fast and fast.next:
fast = fast.next.next
if fast:
slow = slow.next
# Split the list into two halves
second = slow.next
slow.next = None
return second
def merge(first, second):
# If either list is empty, return the other list
if not first:
return second
if not second:
return first
# Pick the smaller value between first and second nodes
if first.data < second.data:
first.next = merge(first.next, second)
return first
else:
second.next = merge(first, second.next)
return second
def merge_sort(head):
# Base case: if the list is empty or has only one node,
# it's already sorted
if not head or not head.next:
return head
# Split the list into two halves
second = split(head)
# Recursively sort each half
head = merge_sort(head)
second = merge_sort(second)
# Merge the two sorted halves
return merge(head, second)
def print_list(head):
curr = head
while curr:
print(curr.data, end=" ")
curr = curr.next
print()
if __name__ == "__main__":
# Create a hard-coded singly linked list:
# 9 -> 8 -> 5 -> 2
head = Node(9)
head.next = Node(8)
head.next.next = Node(5)
head.next.next.next = Node(2)
head = merge_sort(head)
print_list(head)
// C# program for merge sort on singly linked list
using System;
class Node {
public int data;
public Node next;
public Node(int x)
{
data = x;
next = null;
}
}
// Function to split the singly linked list into two halves
class GfG {
static 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 != null && fast.next != null) {
fast = fast.next.next;
if (fast != null) {
slow = slow.next;
}
}
// Split the list into two halves
Node temp = slow.next;
slow.next = null;
return temp;
}
// Function to merge two sorted singly linked lists
static Node Merge(Node first, Node second)
{
// If either list is empty, return the other list
if (first == null)
return second;
if (second == null)
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
static Node MergeSort(Node head)
{
// Base case: if the list is empty or has only one
// node, it's already sorted
if (head == null || head.next == null)
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);
}
static void PrintList(Node head)
{
Node curr = head;
while (curr != null) {
Console.Write(curr.data + " ");
curr = curr.next;
}
Console.WriteLine();
}
public static void 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);
}
}
// JavaScript program for merge sort on singly linked list
class Node {
constructor(x)
{
this.data = x;
this.next = null;
}
}
// Function to split the singly linked list into two halves
function split(head)
{
let fast = head;
let slow = head;
// Move fast pointer two steps and slow pointer
// one step until fast reaches the end
while (fast && fast.next) {
fast = fast.next.next;
if (fast) {
slow = slow.next;
}
}
// Split the list into two halves
let second = slow.next;
slow.next = null;
return second;
}
// Function to merge two sorted singly linked lists
function merge(first, second)
{
// If either list is empty, return the other list
if (!first)
return second;
if (!second)
return first;
// Pick the smaller value between first and second nodes
if (first.data < second.data) {
first.next = merge(first.next, second);
return first;
}
else {
second.next = merge(first, second.next);
return second;
}
}
// Function to perform merge sort on a singly linked list
function mergeSort(head)
{
// Base case: if the list is empty or has only one node,
// it's already sorted
if (!head || !head.next)
return head;
// Split the list into two halves
let second = split(head);
// Recursively sort each half
head = mergeSort(head);
second = mergeSort(second);
// Merge the two sorted halves
return merge(head, second);
}
function printList(head)
{
let curr = head;
while (curr) {
console.log(curr.data + " ");
curr = curr.next;
}
console.log();
}
// Create a hard-coded singly linked list:
// 9 -> 8 -> 5 -> 2
let 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);
Output
2 5 8 9
Time Complexity: O(n*log(n))
Auxiliary Space: O(logn)