This Tutorial Explains what is Merge Sort in Java, MergeSort Algorithm, Pseudo Code, Merge Sort Implementation, Examples of Iterative & Recursive MergeSort:
Merge sort technique uses a “Divide-and-Conquer” strategy. In this technique, the data set that is to be sorted is divided into smaller units to sort it.
=> Read Through The Easy Java Training Series.
Table of Contents:
Merge Sort In Java
For example, if an array is to be sorted using mergesort, then the array is divided around its middle element into two sub-arrays. These two sub-arrays are further divided into smaller units until we have only 1 element per unit.
Once the division is done, this technique merges these individual units by comparing each element and sorting them when merging. This way by the time the entire array is merged back, we get a sorted array.
In this tutorial, we will discuss all the details of this sorting technique in general including its algorithm and pseudo codes as well as the implementation of the technique in Java.
MergeSort Algorithm In Java
Following is the algorithm for the technique.
#1) Declare an array myArray of length N
#2) Check if N=1, myArray is already sorted
#3) If N is greater than 1,
- set left = 0, right = N-1
- compute middle = (left + right)/2
- Call subroutine merge_sort (myArray,left,middle) => this sorts first half of the array
- Call subroutine merge_sort (myArray,middle+1,right) => this will sort the second half of the array
- Call subroutine merge (myArray, left, middle, right) to merge arrays sorted in the above steps.
#4) Exit
As seen in the algorithm steps, the array is divided into two in the middle. Then we recursively sort the left half of the array and then the right half. Once we individually sort both the halves, they are merged together to obtain a sorted array.
Merge Sort Pseudo Code
Let’s see the pseudo-code for the Mergesort technique. As already discussed since this is a ‘divide-and-conquer’ technique, we will present the routines for dividing the data set and then merging the sorted data sets.
procedure mergesort( var intarray as array )
if ( n == 1 ) return intarray
var lArray as array = intarray[0] ... intarray [n/2]
var rArray as array = intarray [n/2+1] ... intarray [n]
lArray = mergesort(lArray )
rArray = mergesort(rArray )
return merge(lArray, rArray )
end procedure
procedure merge( var l_array as array, var r_array as array )
var result as array
while (l_array and r_array have elements )
if (l_array [0] > r_array [0] )
add r_array [0] to the end of result
remove r_array [0] from r_array
else
add l_array [0] to the end of result
remove l_array [0] from l_array
end if
end while
while (l_array has elements )
add l_array [0] to the end of result
remove l_array [0] from l_array
end while
while (r_array has elements )
add r_array [0] to the end of result
remove r_array [0] from r_array
end while
return result
end procedure
In the above pseudo-code, we have two routines i.e. Mergesort and merge. The routine Mergesort splits the input array into an individual array that is easy enough to sort. Then it calls the merge routine.
The merge routine merges the individual sub-arrays and returns a resultant sorted array. Having seen the algorithm and pseudo-code for Merge sort, let’s now illustrate this technique using an example.
MergeSort Illustration
Consider the following array that is to be sorted using this technique.
Now according to the Merge sort algorithm, we will split this array at its mid element into two sub-arrays. Then we will continue splitting the sub-arrays into smaller arrays till we get a single element in each array.
Once each sub-array has only one element in it, we merge the elements. While merging, we compare the elements and ensure that they are in order in the merged array. So we work our way up to get a merged array that is sorted.
The process is shown below:
As shown in the above illustration, we see that the array is divided repeatedly and then merged to get a sorted array. With this concept in mind, let’s move onto the implementation of Mergesort in Java programming language.
Merge Sort Implementation In Java
We can implement the technique in Java using two approaches.
Iterative Merge Sort
This is a bottom-up approach. The sub-arrays of one element each are sorted and merged to form two-element arrays. These arrays are then merged to form four-element arrays and so on. This way the sorted array is built by going upwards.
The below Java example shows the iterative Merge Sort technique.
import java.util.Arrays;
class Main
{
// merge arrays : intArray[start...mid] and intArray[mid+1...end]
public static void merge(int[] intArray, int[] temp, int start, int mid, int end)
{
int k = start, i = start, j = mid + 1;
// traverse through elements of left and right arrays
while (i <= mid && j <= end) {
if (intArray[i] < intArray[j]) {
temp[k++] = intArray[i++];
} else {
temp[k++] = intArray[j++];
}
}
// Copy remaining elements
while (i <= mid) {
temp[k++] = intArray[i++];
}
// copy temp array back to the original array to reflect sorted order
for (i = start; i <= end; i++) {
intArray[i] = temp[i];
}
}
// sorting intArray[low...high] using iterative approach
public static void mergeSort(int[] intArray)
{
int low = 0;
int high = intArray.length - 1;
// sort array intArray[] using temporary array temp
int[] temp = Arrays.copyOf(intArray, intArray.length);
// divide the array into blocks of size m
// m = [1, 2, 4, 8, 16...]
for (int m = 1; m <= high - low; m = 2*m)
{
for (int i = low; i < high; i += 2*m)
{
int start = i;
int mid = i + m - 1;
int end = Integer.min(i + 2 * m - 1, high);
//call merge routine to merge the arrays
merge(intArray, temp, start, mid, end);
}
}
}
public static void main(String[] args)
{
//define array to be sorted
int[] intArray = { 10,23,-11,54,2,9,-10,45 };
//print the original array
System.out.println("Original Array : " + Arrays.toString(intArray));
//call mergeSort routine
mergeSort(intArray);
//print the sorted array
System.out.println("Sorted Array : " + Arrays.toString(intArray));
}
}
Output:
Original Array : [10, 23, -11, 54, 2, 9, -10, 45]
Sorted Array : [-11, -10, 2, 9, 10, 23, 45, 54]
Recursive Merge Sort
This is a top-down approach. In this approach, the array to be sorted is broken down into smaller arrays until each array contains only one element. Then the sorting becomes easy to implement.
The following Java code implements the recursive approach of the Merge sort technique.
import java.util.Arrays;
public class Main {
public static void merge_Sort(int[] numArray) {
//return if array is empty
if(numArray == null) {
return;
}
if(numArray.length > 1) {
int mid = numArray.length / 2; //find mid of the array
// left half of the array
int[] left = new int[mid];
for(int i = 0; i < mid; i++) {
left[i] = numArray[i];
}
// right half of the array
int[] right = new int[numArray.length - mid];
for(int i = mid; i < numArray.length; i++) {
right[i - mid] = numArray[i];
}
merge_Sort(left); //call merge_Sort routine for left half of the array
merge_Sort(right); // call merge_Sort routine for right half of the array
int i = 0;
int j = 0;
int k = 0;
// now merge two arrays
while(i < left.length && j < right.length) {
if(left[i] < right[j]) {
numArray[k] = left[i];
i++;
}
else {
numArray[k] = right[j];
j++;
}
k++;
}
// remaining elements
while(i < left.length) {
numArray[k] = left[i];
i++;
k++;
}
while(j < right.length) {
numArray[k] = right[j];
j++;
k++;
}
}
}
public static void main(String[] args) {
int numArray[] = {10, 23, -11, 54, 2, 9, -10, 45};
int i=0;
//print original array
System.out.println("Original Array:" + Arrays.toString(numArray));
//call merge_Sort routine to sort arrays recursively
merge_Sort(numArray);
//print the sorted array
System.out.println("Sorted array:" + Arrays.toString(numArray));
}
}
Output:
Original Array:[10, 23, -11, 54, 2, 9, -10, 45]
Sorted array:[-11, -10, 2, 9, 10, 23, 45, 54]
In the next section, let’s switch from arrays and use the technique to sort the linked list and array list data structures.
Sort Linked List Using Merge Sort In Java
Mergesort technique is the most preferred one for sorting linked lists. Other sorting techniques perform poorly when it comes to the linked list because of its mostly sequential access.
The following program sorts a linked list using this technique.
import java.util.*;
// A singly linked list node
class Node
{
int data;
Node next;
Node(int data, Node next) {
this.data = data;
this.next = next;
}
};
class Main {
//two sorted linked list are merged together to form one sorted linked list
public static Node Sorted_MergeSort(Node node1, Node node2) {
//return other list if one is null
if (node1 == null)
return node2;
else if (node2 == null)
return node1;
Node result;
// Pick either node1 or node2, and recur
if (node1.data <= node2.data) {
result = node1;
result.next = Sorted_MergeSort(node1.next, node2);
}
else {
result = node2;
result.next = Sorted_MergeSort(node1, node2.next);
}
return result;
}
//splits the given linked list into two halves
public static Node[] FrontBackSplit(Node source) {
// empty list
if (source == null || source.next == null) {
return new Node[]{ source, null } ;
}
Node slow_ptr = source;
Node fast_ptr = source.next;
// Advance 'fast' two nodes, and advance 'slow' one node
while (fast_ptr != null) {
fast_ptr = fast_ptr.next;
if (fast_ptr != null) {
slow_ptr = slow_ptr.next;
fast_ptr = fast_ptr.next;
}
}
// split the list at slow_ptr just before mid
Node[] l_list = new Node[]{ source, slow_ptr.next };
slow_ptr.next = null;
return l_list;
}
// use Merge sort technique to sort the linked list
public static Node Merge_Sort(Node head) {
// list is empty or has single node
if (head == null || head.next == null) {
return head;
}
// Split head into 'left' and 'right' sublists
Node[] l_list = FrontBackSplit(head);
Node left = l_list[0];
Node right = l_list[1];
// Recursively sort the sublists
left = Merge_Sort(left);
right = Merge_Sort(right);
// merge the sorted sublists
return Sorted_MergeSort(left, right);
}
// function to print nodes of given linked list
public static void printNode(Node head) {
Node node_ptr = head;
while (node_ptr != null) {
System.out.print(node_ptr.data + " -> ");
node_ptr = node_ptr.next;
}
System.out.println("null");
}
public static void main(String[] args) {
// input linked list
int[] l_list = { 4,1,6,2,7,3,8 };
Node head = null;
for (int key: l_list) {
head = new Node(key, head);
}
//print the original list
System.out.println("Original Linked List: ");
printNode(head);
// sort the list
head = Merge_Sort(head);
// print the sorted list
System.out.println("\nSorted Linked List:");
printNode(head);
}
}
Output:
Original Linked List:
8 -> 3 -> 7 -> 2 -> 6 -> 1 -> 4 -> null
Sorted Linked List:
1 -> 2 -> 3 -> 4 -> 6 -> 7 -> 8 -> null
Sort ArrayList Using Merge Sort In Java
Like Arrays and Linked lists, we can also use this technique for sorting an ArrayList. We will use similar routines to divide the ArrayList recursively and then merge the sublists.
The below Java code implements the Merge sort technique for ArrayList.
import java.util.ArrayList;
class Main {
//splits arrayList into sub lists.
public static void merge_Sort(ArrayList<Integer> numList){
int mid;
ArrayList<Integer> left = new ArrayList<>();
ArrayList<Integer> right = new ArrayList<>();
if (numList.size() > 1) {
mid = numList.size() / 2;
// left sublist
for (int i = 0; i < mid; i++)
left.add(numList.get(i));
//right sublist
for (int j = mid; j < numList.size(); j++)
right.add(numList.get(j));
//recursively call merge_Sort for left and right sublists
merge_Sort(left);
merge_Sort(right);
//now merge both arrays
merge(numList, left, right);
}
}
private static void merge(ArrayList<Integer> numList, ArrayList<Integer> left, ArrayList<Integer> right){
//temporary arraylist to build the merged list
ArrayList<Integer> temp = new ArrayList<>();
//initial indices for lists
int numbersIndex = 0;
int leftIndex = 0;
int rightIndex = 0;
//traverse left and righ lists for merging
while (leftIndex < left.size() && rightIndex < right.size()) {
if (left.get(leftIndex) < right.get(rightIndex) ) {
numList.set(numbersIndex, left.get(leftIndex));
leftIndex++;
} else {
numList.set(numbersIndex, right.get(rightIndex));
rightIndex++;
}
numbersIndex++;
}
//copy remaining elements from both lists, if any.
int tempIndex = 0;
if (leftIndex >= left.size()) {
temp = right;
tempIndex = rightIndex;
}
else {
temp = left;
tempIndex = leftIndex;
}
for (int i = tempIndex; i < temp.size(); i++) {
numList.set(numbersIndex, temp.get(i));
numbersIndex++;
}
}
public static void main(String[] args) {
//declare an ArrayList
ArrayList<Integer> numList = new ArrayList<>();
int temp;
//populate the ArrayList with random numbers
for (int i = 1; i <= 9; i++)
numList.add( (int)(Math.random() * 50 + 1) );
//print original ArrayList of random numbers
System.out.println("Original ArrayList:");
for(int val: numList)
System.out.print(val + " ");
//call merge_Sort routine
merge_Sort(numList);
//print the sorted ArrayList
System.out.println("\nSorted ArrayList:");
for(int ele: numList)
System.out.print(ele + " ");
System.out.println();
}
}
Output:
Original ArrayList:
17 40 36 7 6 23 35 2 38
Sorted ArrayList:
2 6 7 17 23 35 36 38 40
Frequently Asked Questions
Q #1) Can Merge sort be done without Recursion?
Answer: Yes. We can perform a non-recursive Merge sort called ‘iterative Merge sort’. This is a bottom-up approach that begins by merging sub-arrays with a single element into a sub-array of two elements.
Then these 2-element sub-arrays are merged into 4-element sub arrays and so on using iterative constructs. This process continues until we have a sorted array.
Q #2) Can Merge sort be done in place?
Answer: Merge sort generally is not in-place. But we can make it in-place by using some clever implementation. For example, by storing two elements value at one position. This can be extracted afterward using modulus and division.
Q #3) What is a 3 way Merge sort?
Answer: The technique we have seen above is a 2-way Merge sort wherein we split the array to be sorted into two parts. Then we sort and merge the array.
In a 3-way Merge sort, instead of splitting the array into 2 parts, we split it into 3 parts, then sort and finally merge it.
Q #4) What is the time complexity of Mergesort?
Answer: The overall time complexity of Merge sort in all cases is O (nlogn).
Q #5) Where is the Merge sort used?
Answer: It is mostly used in sorting the linked list in O (nlogn) time. It is also used in distributed scenarios wherein new data comes in the system before or post sorting. This is also used in various database scenarios.
Conclusion
Merge sort is a stable sort and is performed by first splitting the data set repeatedly into subsets and then sorting and merging these subsets to form a sorted data set. The data set is split until each data set is trivial and easy to sort.
We have seen the recursive and iterative approaches to the sorting technique. We have also discussed the sorting of Linked List and ArrayList data structure using Mergesort.
We will continue with the discussion of more sorting techniques in our upcoming tutorials. Stay Tuned!
=> Visit Here For The Exclusive Java Training Tutorial Series.












