Mergesort in java

Mergesort is a divide and conquer algorithm. It works by breaking an array into sub-arrays and then recursively sorting the sub-arrays.

Steps for Mergesort

  1. Divide the list with n elements into n sublists with each sublist having 1 element. We will divide list into 2 sublists by dividing in the middle and then recursively dividing the 2 sublists from the middle until we are left with sublists with all of them having 1 element.
  2. Merge all the sublists to produce sorted sublists and then merge the already merged sublists. Do that until only one list is created and no more merging can be performed.

Mergesort example

Here is an animation of the mergesort

Mergesort Animation

Mergesort Animation

Mergesort Java implementation

Here is a java implementation. I have added a lot of logging so that from the output all the steps become clear.
package com.programtalk.mergesort.example;

import java.util.Arrays;

public class MergerSort {
	
	
	public static void main(String[] args) {
		int[] array4Sort = { 8,5,6,7,2,1,3,4};
		System.out.println("To be sorted array: " + Arrays.toString(array4Sort));
		sort(array4Sort);
		System.out.println("Sorted array: " +  Arrays.toString(array4Sort));
	}

	
	
	public static void sort(int[] array4Sort) {
		int[] emptyArray = new int[array4Sort.length];
		int rightEndIndex = array4Sort.length - 1;
		int leftStartIndex = 0;
		recusrsiveMergeSort(array4Sort, emptyArray, leftStartIndex, rightEndIndex);
	}

	private static void recusrsiveMergeSort(int[] array4Sort, int[] tmpArray, int leftIndex, int rightIndex) {
		if (rightIndex <= leftIndex) {
			return;
		}

		int center = (rightIndex + leftIndex) / 2;
		recusrsiveMergeSort(array4Sort, tmpArray, leftIndex, center);
		recusrsiveMergeSort(array4Sort, tmpArray, center + 1, rightIndex);
		mergeLeftAndRight(array4Sort, tmpArray, leftIndex, center + 1, rightIndex);
	}

	private static void mergeLeftAndRight(int[] array2Merge, int[] tmpArrayUsed4Merge, int leftStartIndex, int rightStartIndex,
			int rightEndIndex) {

		System.out.println(
				"left array: " + Arrays.toString(Arrays.copyOfRange(array2Merge, leftStartIndex, rightStartIndex)));
		System.out.println(
				"right array: " + Arrays.toString(Arrays.copyOfRange(array2Merge, rightStartIndex, rightEndIndex + 1)));
		
		int leftEndIndex = rightStartIndex - 1;
		int tmpArray4MergeIndex = leftStartIndex;
		final int startIndexForMergedArray = leftStartIndex;

		for (;leftStartIndex <= leftEndIndex && rightStartIndex <= rightEndIndex; tmpArray4MergeIndex++) {
			// the lower value element goes to the merged array
			if (array2Merge[leftStartIndex] < (array2Merge[rightStartIndex]))
				tmpArrayUsed4Merge[tmpArray4MergeIndex] = array2Merge[leftStartIndex++];
			else
				tmpArrayUsed4Merge[tmpArray4MergeIndex] = array2Merge[rightStartIndex++];
		}
		
		while (leftStartIndex <= leftEndIndex) {
			tmpArrayUsed4Merge[tmpArray4MergeIndex++] = array2Merge[leftStartIndex++];
		}
		while (rightStartIndex <= rightEndIndex) {
			tmpArrayUsed4Merge[tmpArray4MergeIndex++] = array2Merge[rightStartIndex++];
		}

		System.out.println("Temporary array after merging:" + Arrays.toString(tmpArrayUsed4Merge));
		int length = rightEndIndex - startIndexForMergedArray +1;
		System.arraycopy(tmpArrayUsed4Merge, startIndexForMergedArray, array2Merge, startIndexForMergedArray, length);

	}

}

Output:

To be sorted array: [8, 5, 6, 7, 2, 1, 3, 4]
left array: [8]
right array: [5]
Temporary array after merging:[5, 8, 0, 0, 0, 0, 0, 0]
left array: [6]
right array: [7]
Temporary array after merging:[5, 8, 6, 7, 0, 0, 0, 0]
left array: [5, 8]
right array: [6, 7]
Temporary array after merging:[5, 6, 7, 8, 0, 0, 0, 0]
left array: [2]
right array: [1]
Temporary array after merging:[5, 6, 7, 8, 1, 2, 0, 0]
left array: [3]
right array: [4]
Temporary array after merging:[5, 6, 7, 8, 1, 2, 3, 4]
left array: [1, 2]
right array: [3, 4]
Temporary array after merging:[5, 6, 7, 8, 1, 2, 3, 4]
left array: [5, 6, 7, 8]
right array: [1, 2, 3, 4]
Temporary array after merging:[1, 2, 3, 4, 5, 6, 7, 8]
Sorted array: [1, 2, 3, 4, 5, 6, 7, 8]
Like this post? Don’t forget to share it!

10 Comments

  1. Amit Karkera

    hi, i dont get how does mergeleftandright gets recursively called. stuck on mergesort since a week! could you possibly explain it

    • Tak

      mergeleftandright does not do recursion over itself. I have added some more outputs in the below program. And have reduced the array size also so as to get a better understanding. Try it out


      package com.programtalk.mergesort.example;

      import java.util.Arrays;

      public class MergerSort {

      public static void main(String[] args) {
      int[] array4Sort = { 8,5,6,7};
      System.out.println("To be sorted array: " + Arrays.toString(array4Sort));
      sort(array4Sort);
      System.out.println("Sorted array: " + Arrays.toString(array4Sort));
      }

      public static void sort(int[] array4Sort) {
      int[] emptyArray = new int[array4Sort.length];
      int rightEndIndex = array4Sort.length - 1;
      int leftStartIndex = 0;
      recusrsiveMergeSort(array4Sort, emptyArray, leftStartIndex, rightEndIndex);
      }

      private static void recusrsiveMergeSort(int[] array4Sort, int[] tmpArray, int leftIndex, int rightIndex) {
      if (rightIndex <= leftIndex) {
      return;
      }

      int center = (rightIndex + leftIndex) / 2;
      System.out.println("recusrsiveMergeSort for left array, right index:" + center + ", left index:" + leftIndex);
      recusrsiveMergeSort(array4Sort, tmpArray, leftIndex, center);
      System.out.println("recusrsiveMergeSort for right array, right index:" + rightIndex+ ", left index:" + (center + 1));
      recusrsiveMergeSort(array4Sort, tmpArray, center + 1, rightIndex);
      mergeLeftAndRight(array4Sort, tmpArray, leftIndex, center + 1, rightIndex);
      }

      private static void mergeLeftAndRight(int[] array2Merge, int[] tmpArrayUsed4Merge, int leftStartIndex, int rightStartIndex,
      int rightEndIndex) {
      System.out.println("inside : mergeLeftAndRight");
      System.out.println(
      "left array: " + Arrays.toString(Arrays.copyOfRange(array2Merge, leftStartIndex, rightStartIndex)));
      System.out.println(
      "right array: " + Arrays.toString(Arrays.copyOfRange(array2Merge, rightStartIndex, rightEndIndex + 1)));

      int leftEndIndex = rightStartIndex - 1;
      int tmpArray4MergeIndex = leftStartIndex;
      final int startIndexForMergedArray = leftStartIndex;

      for (;leftStartIndex <= leftEndIndex && rightStartIndex <= rightEndIndex; tmpArray4MergeIndex++) {
      // the lower value element goes to the merged array
      if (array2Merge[leftStartIndex] < (array2Merge[rightStartIndex]))
      tmpArrayUsed4Merge[tmpArray4MergeIndex] = array2Merge[leftStartIndex++];
      else
      tmpArrayUsed4Merge[tmpArray4MergeIndex] = array2Merge[rightStartIndex++];
      }

      while (leftStartIndex <= leftEndIndex) {
      tmpArrayUsed4Merge[tmpArray4MergeIndex++] = array2Merge[leftStartIndex++];
      }
      while (rightStartIndex <= rightEndIndex) {
      tmpArrayUsed4Merge[tmpArray4MergeIndex++] = array2Merge[rightStartIndex++];
      }

      System.out.println("Temporary array after merging:" + Arrays.toString(tmpArrayUsed4Merge));
      int length = rightEndIndex - startIndexForMergedArray +1;
      System.arraycopy(tmpArrayUsed4Merge, startIndexForMergedArray, array2Merge, startIndexForMergedArray, length);

      }

      }

      • Amit Karkera

        thank you for your time and effort, but i still dont get how the recusrsiveMergeSort gets called after the first call to mergeLeftAndRight

        • Tak

          You can only understand it by following the flow of the program, that is why i tried to reduce the number of elements in the array. First the left array is sorted recursively and then the right array is sorted recursively. When you reduce the array to be sorted to {8,5} then the output is as below
          To be sorted array: [8, 5]
          recusrsiveMergeSort for left array, right index:0, left index:0
          recusrsiveMergeSort for right array, right index:1, left index:1
          inside : mergeLeftAndRight
          left array: [8]
          right array: [5]
          Temporary array after merging:[5, 8]
          Sorted array: [5, 8]

          Let me try to explain the flow:
          1. recusrsiveMergeSort is called from sort for array {5,8}
          2. recusrsiveMergeSort is called within recusrsiveMergeSort for left array which is 5.
          3. Inside recusrsiveMergeSort both right index and left index are 0 and hence confirming to the exit condition of recursion. So the method stops recursion for this call and returns.
          By exit condition i mean this code:
          if (rightIndex <= leftIndex) {
          return;
          }

          4. recusrsiveMergeSort is called within recusrsiveMergeSort for right array which is 8.
          5. Inside recusrsiveMergeSort both right index and left index are 1 and hence confirming to the exit condition of recursion. So the method stops recursion for this call and returns.
          6. Now mergeLeftAndRight is called.

          • Amit Karkera

            yes i get it sir, but if we are working with a bigger array say with 8 elements… and all the above steps have been done, i.e. mergeleftandright is called. how does the flow go back to recusrsiveMergeSort after the mergeleftandright is exited.

          • Tak

            Here is the output for a bigger array
            To be sorted array: [8, 5, 6, 7, 2, 1, 3, 4]
            recusrsiveMergeSort for left array, right index:3, left index:0
            recusrsiveMergeSort for left array, right index:1, left index:0
            recusrsiveMergeSort for left array, right index:0, left index:0
            recusrsiveMergeSort for right array, right index:1, left index:1
            inside : mergeLeftAndRight
            left array: [8]
            right array: [5]
            Temporary array after merging:[5, 8, 0, 0, 0, 0, 0, 0]
            recusrsiveMergeSort for right array, right index:3, left index:2
            recusrsiveMergeSort for left array, right index:2, left index:2
            recusrsiveMergeSort for right array, right index:3, left index:3
            inside : mergeLeftAndRight
            left array: [6]
            right array: [7]
            Temporary array after merging:[5, 8, 6, 7, 0, 0, 0, 0]
            inside : mergeLeftAndRight
            left array: [5, 8]
            right array: [6, 7]
            Temporary array after merging:[5, 6, 7, 8, 0, 0, 0, 0]
            recusrsiveMergeSort for right array, right index:7, left index:4
            recusrsiveMergeSort for left array, right index:5, left index:4
            recusrsiveMergeSort for left array, right index:4, left index:4
            recusrsiveMergeSort for right array, right index:5, left index:5
            inside : mergeLeftAndRight
            left array: [2]
            right array: [1]
            Temporary array after merging:[5, 6, 7, 8, 1, 2, 0, 0]
            recusrsiveMergeSort for right array, right index:7, left index:6
            recusrsiveMergeSort for left array, right index:6, left index:6
            recusrsiveMergeSort for right array, right index:7, left index:7
            inside : mergeLeftAndRight
            left array: [3]
            right array: [4]
            Temporary array after merging:[5, 6, 7, 8, 1, 2, 3, 4]
            inside : mergeLeftAndRight
            left array: [1, 2]
            right array: [3, 4]
            Temporary array after merging:[5, 6, 7, 8, 1, 2, 3, 4]
            inside : mergeLeftAndRight
            left array: [5, 6, 7, 8]
            right array: [1, 2, 3, 4]
            Temporary array after merging:[1, 2, 3, 4, 5, 6, 7, 8]
            Sorted array: [1, 2, 3, 4, 5, 6, 7, 8]

            Flow would be something like this

            To be sorted array: [8, 5, 6, 7, 2, 1, 3, 4]
            recusrsiveMergeSort([8, 5, 6, 7, 2, 1, 3, 4])
            recusrsiveMergeSort([8, 5, 6, 7])
            recusrsiveMergeSort([8, 5])
            recusrsiveMergeSort([8])
            recusrsiveMergeSort([5])
            inside : mergeLeftAndRight
            recusrsiveMergeSort([6, 7])
            recusrsiveMergeSort([6])
            recusrsiveMergeSort([7])
            inside : mergeLeftAndRight
            inside : mergeLeftAndRight
            recusrsiveMergeSort([2, 1, 3, 4])
            recusrsiveMergeSort([2, 1])
            recusrsiveMergeSort([2])
            recusrsiveMergeSort([1])
            inside : mergeLeftAndRight
            recusrsiveMergeSort([3, 4])
            recusrsiveMergeSort([3])
            recusrsiveMergeSort([4])
            inside : mergeLeftAndRight
            inside : mergeLeftAndRight
            inside : mergeLeftAndRight
            Sorted array: [1, 2, 3, 4, 5, 6, 7, 8]

            mergeLeftAndRight would not be executed for the lowest level arrays that is arrays with only one element. That you can see from above flow

          • Amit Karkera

            i am sorry i am a slow learner. can you explain how

            recusrsiveMergeSort([6, 7])

            gets executed after inside : mergeLeftAndRight.

          • Tak

            You need to understand recursion in order to get the flow.

            recusrsiveMergeSort([8, 5, 6, 7])
            recusrsiveMergeSort([8, 5]) –> first call within 8, 5, 6, 7
            recusrsiveMergeSort([8]) — first call within 8,5
            recusrsiveMergeSort([5]) — second call within 8,5
            inside : mergeLeftAndRight — called inside 8,5
            Here the recusrsiveMergeSort([8, 5]) returns and the next line to be executed would be

            recusrsiveMergeSort([6, 7]) –> second call within 8, 5, 6, 7

          • Amit Karkera

            thank you for your patience, i think i have a better understanding now, but i have a question. what do you mean by “recusrsiveMergeSort([8, 5]) returns” . is it like recusrsiveMergeSort([6, 7]) is still waiting in the background to get executed?

          • Tak

            No, this is next line to be executed.
            Read some recursion tutorials and execute the examples, Only when you have the idea of recursion, you can understand mergesort code

Leave a Reply

Your email address will not be published. Required fields are marked *