Given a doubly linked list, The task is to sort the doubly linked list in non-decreasing order using merge sort.
Examples:
Input: 10 <-> 8 <-> 4 <-> 2
Output: 2 <-> 4 <-> 8 <-> 10
Input: 5 <-> 3 <-> 2
Output: 2 <-> 3 <-> 5
Merge sort for a singly linked list has already been discussed. The important change here is to modify the previous pointers when merging two lists.
Approach :
The idea is to maintain a mergeSort function that sorts the list in three steps:
Divide: Split the list into two halves using a mid node. The first half runs from the head to just before mid, and the second half starts at mid and runs to the end.
Recursively Sort: Apply mergeSort recursively on both halves.
Merge: Merge the two sorted halves into one sorted list and return the new head node.
// C++ program for merge sort on doubly linked list
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node *next;
Node *prev;
Node(int x) {
data = x;
next = nullptr;
prev = nullptr;
}
};
// Function to split the doubly 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->next->next!= nullptr) {
fast = fast->next->next;
slow = slow->next;
}
// Split the list into two halves
Node *temp = slow->next;
slow->next = nullptr;
if (temp!= nullptr) {
temp->prev = nullptr;
}
return temp;
}
// Function to merge two sorted doubly 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);
if (first->next!= nullptr) {
first->next->prev = first;
}
first->prev = nullptr;
return first;
}
else {
// Recursively merge the rest of the lists
// and link the result to the current node
second->next = merge(first, second->next);
if (second->next!= nullptr) {
second->next->prev = second;
}
second->prev = nullptr;
return second;
}
}
// Function to perform merge sort on a doubly 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 doubly linked list:
// 10 <-> 8 <-> 5 <-> 2
Node *head = new Node(10);
head->next = new Node(8);
head->next->prev = head;
head->next->next = new Node(5);
head->next->next->prev = head->next;
head->next->next->next = new Node(2);
head->next->next->next->prev = head->next->next;
head = mergeSort(head);
printList(head);
return 0;
}
// C program for merge sort on doubly linked list
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
struct Node *prev;
};
// Function to split the doubly 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->next->next != NULL) {
fast = fast->next->next;
slow = slow->next;
}
// Split the list into two halves
struct Node *temp = slow->next;
slow->next = NULL;
if (temp != NULL) {
temp->prev = NULL;
}
return temp;
}
// Function to merge two sorted doubly 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);
if (first->next != NULL) {
first->next->prev = first;
}
first->prev = NULL;
return first;
}
else {
// Recursively merge the rest of the lists and
// link the result to the current node
second->next = merge(first, second->next);
if (second->next != NULL) {
second->next->prev = second;
}
second->prev = NULL;
return second;
}
}
// Function to perform merge sort on a doubly 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");
}
struct Node *createNode(int data) {
struct Node *newNode =
(struct Node *)malloc(sizeof(struct Node));
newNode->data = data;
newNode->next = NULL;
newNode->prev = NULL;
return newNode;
}
int main() {
// Create a hard-coded doubly linked list:
// 10 <-> 8 <-> 5 <-> 2
struct Node *head = createNode(10);
head->next = createNode(8);
head->next->prev = head;
head->next->next = createNode(5);
head->next->next->prev = head->next;
head->next->next->next = createNode(2);
head->next->next->next->prev = head->next->next;
head = mergeSort(head);
printList(head);
return 0;
}
// Java program for merge sort on doubly
// linked list
class Node {
int data;
Node next;
Node prev;
Node(int data) {
this.data = data;
this.next = null;
this.prev = null;
}
}
public class GfG {
// Function to split the doubly
// linked list into twohalves
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.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
// Split the list into two halves
Node temp = slow.next;
slow.next = null;
if (temp != null) {
temp.prev = null;
}
return temp;
}
// Function to merge two sorted doubly 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);
if (first.next != null) {
first.next.prev = first;
}
first.prev = null;
return first;
}
else {
// Recursively merge the rest of the lists and
// link the result to the current node
second.next = merge(first, second.next);
if (second.next != null) {
second.next.prev = second;
}
second.prev = null;
return second;
}
}
// Function to perform merge sort on
// a doubly 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 doubly linked list:
// 10 <-> 8 <-> 5 <-> 2
Node head = new Node(10);
head.next = new Node(8);
head.next.prev = head;
head.next.next = new Node(5);
head.next.next.prev = head.next;
head.next.next.next = new Node(2);
head.next.next.next.prev = head.next.next;
head = mergeSort(head);
printList(head);
}
}
# Python Program for merge sort on doubly linked list
class Node:
def __init__(self, data):
self.data = data
self.next = None
self.prev = None
# Function to split the doubly linked
# list into two halves
def split(head):
fast = head
slow = head
# Move fast pointer two steps and slow pointer
# one step until fast reaches the end
while fast is not None and fast.next is not None \
and fast.next.next is not None:
fast = fast.next.next
slow = slow.next
# Split the list into two halves
temp = slow.next
slow.next = None
if temp is not None:
temp.prev = None
return temp
# Function to merge two sorted doubly linked lists
def merge(first, second):
# If either list is empty, return the other list
if first is None:
return second
if second is None:
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)
if first.next is not None:
first.next.prev = first
first.prev = None
return first
else:
# Recursively merge the rest of the lists and
# link the result to the current node
second.next = merge(first, second.next)
if second.next is not None:
second.next.prev = second
second.prev = None
return second
# Function to perform merge sort on a
# doubly linked list
def mergeSort(head):
# Base case: if the list is empty or has only
# one node, it's already sorted
if head is None or head.next is None:
return head
# Split the list into two halves
second = split(head)
# Recursively sort each half
head = mergeSort(head)
second = mergeSort(second)
# Merge the two sorted halves
return merge(head, second)
def printList(head):
curr = head
while curr is not None:
print(curr.data, end=" ")
curr = curr.next
print()
if __name__ == "__main__":
# Create a hard-coded doubly linked list:
# 10 <-> 8 <-> 5 <-> 2
head = Node(10)
head.next = Node(8)
head.next.prev = head
head.next.next = Node(5)
head.next.next.prev = head.next
head.next.next.next = Node(2)
head.next.next.next.prev = head.next.next
head = mergeSort(head)
printList(head)
// C# Program for merge sort
// on doubly linked list
using System;
class Node {
public int data;
public Node next;
public Node prev;
public Node(int data) {
this.data = data;
this.next = null;
this.prev = null;
}
}
class GfG {
// Function to split the doubly linked list into two
// halves
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.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
// Split the list into two halves
Node temp = slow.next;
slow.next = null;
if (temp != null) {
temp.prev = null;
}
return temp;
}
// Function to merge two sorted doubly 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);
if (first.next != null) {
first.next.prev = first;
}
first.prev = null;
return first;
}
else {
// Recursively merge the rest of the lists and
// link the result to the current node
second.next = Merge(first, second.next);
if (second.next != null) {
second.next.prev = second;
}
second.prev = null;
return second;
}
}
// Function to perform merge sort on a doubly 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();
}
static void Main(string[] args) {
// Create a hard-coded doubly linked list:
// 10 <-> 8 <-> 5 <-> 2
Node head = new Node(10);
head.next = new Node(8);
head.next.prev = head;
head.next.next = new Node(5);
head.next.next.prev = head.next;
head.next.next.next = new Node(2);
head.next.next.next.prev = head.next.next;
head = mergeSort(head);
PrintList(head);
}
}
// Javascript Program for merge sort
// on doubly linked list
class Node {
constructor(data) {
this.data = data;
this.next = null;
this.prev = null;
}
}
// Function to split the doubly 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 !== null && fast.next !== null
&& fast.next.next !== null) {
fast = fast.next.next;
slow = slow.next;
}
// Split the list into two halves
let temp = slow.next;
slow.next = null;
if (temp !== null) {
temp.prev = null;
}
return temp;
}
// Function to merge two sorted doubly linked lists
function merge(first, 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);
if (first.next !== null) {
first.next.prev = first;
}
first.prev = null;
return first;
}
else {
// Recursively merge the rest of the lists and link
// the result to the current node
second.next = merge(first, second.next);
if (second.next !== null) {
second.next.prev = second;
}
second.prev = null;
return second;
}
}
// Function to perform merge sort on a
// doubly linked list
function mergeSort(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
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 !== null) {
console.log(curr.data + " ");
curr = curr.next;
}
}
// Create a hard-coded doubly linked list:
// 10 <-> 8 <-> 5 <-> 2
let head = new Node(10);
head.next = new Node(8);
head.next.prev = head;
head.next.next = new Node(5);
head.next.next.prev = head.next;
head.next.next.next = new Node(2);
head.next.next.next.prev = head.next.next;
head = mergeSort(head);
printList(head);
Output
2 5 8 10
Time Complexity: O(n Log n)
Auxiliary Space: O(1)