Merge Sort for Doubly Linked List
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
Note: 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.The MergeSort function will return the node representing the new head of the sorted doubly linked list.
Below is the implementation of above approach :
// 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 = NULL;
prev = NULL;
}
};
// 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 != 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
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
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);
}
void printList(Node *head) {
Node *curr = head;
while (curr != NULL) {
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(nLogn)
Auxiliary Space: O(1)
Related Articles: