Notes on the merge sort algorithm

  • Merge sort is one of few algorithms that has O(nlog(n)) running time

    • O(nlog(n)) is also the theorectical low bound on running time of sorting algorithms

  • Some problems with the pure Merge Sort algorithm:

    1. There is a very high overhead to execute a recursive algorithm for tiny sublists

    2. Merge sort will merge even when the 2 halves are sorted

    3. Merge sort is not an in-place algorithm

      • Merge sort requires another array to perform the mereg operation

    The first 2 problems can be fixed...

Why is recursion with tiny sublists a problem in Merge Sort

  • Suppose the input array has 1,000,000 elements:

                     mergeSort(A, 0, 1000000, H)
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

     

Why is recursion with tiny sublists a problem in Merge Sort

  • The base case (= stop criteria) is n = 1:

                     mergeSort(A, 0, 1000000, H)
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
        mergeSort(A,0,0,H) ...       mergeSort(A,k,k,H) .....
    

    There will be 1,000,000 mergeSort(A,k,k,H) invocations !!!

Why is recursion with tiny sublists a problem in Merge Sort

  • Furthermore, the base case will simple return:

                     mergeSort(A, 0, 1000000, H)
    
    
    
    
    
           if ( n <= 1 )
              return;
    
    
    
    
    
    
    
    
    
    
        mergeSort(A,0,0,H) ...       mergeSort(A,k,k,H) .....
    

    All 1,000,000 method invocations do no work but cost time to execute !!!

The hybrid merge sort algorithm

Review:   merge sort algorithm

 // Merge sorts the array elements A[s] ... A[e-1] using helper array H

 public static <T extends Comparable<T>> void sort(T[] A, int s, int e, T[] H)
 {
     if ( e - s <= 1 )      // A[s]..A[e] has 0 or 1 element
     {


         return;            // No need to sort an array of 1 element...
     }


     int m = (e+s)/2;       // m = middle of s and e
   
     MergeSort.sort(A, s, m, H);

     MergeSort.sort(A, m, e, H);

     // Merge both sorted arrays

     merge(A, s, m, e, H); // We have discussed merge() previously !
 } 

The hybrid merge sort algorithm

The hybrid merge sort algorithm uses a different sort algorithm when input size is below some threshold:

 // Merge sorts the array elements A[s] ... A[e-1] using helper array H

 public static <T extends Comparable<T>> void sort(T[] A, int s, int e, T[] H)
 {
     if ( e - s <= CUTOFF ) // Use a different sort alg for small inputs
     {
         SelectionSort.sort(A, s, e);

         return;            
     }


     int m = (e+s)/2;       // m = middle of s and e
   
     MergeSort.sort(A, s, m, H);

     MergeSort.sort(A, m, e, H);

     // Merge both sorted arrays

     merge(A, s, m, e, H); // We have discussed merge() previously !
 } 

The hybrid merge sort algorithm is called TimSort

Merging 2 array halves that are already sorted

  • When you have 2 sorted arrays that are adjacent to each other, you do not need to merge them if the values are already sorted:

          1    2   4    5    6    7   8   9 
          <------------->    <------------>
             array 1            array 2
    
          <-------------------------------->
                  Already sorted
    

  • You will need to perform a merge operation when the values are not sorted:

          1    2   4    7    5    6   8   9 
          <------------->    <------------>
             array 1            array 2
    

  • You can use this simple test to check if the 2 sorted arrays are sorted in totality:

      A[last elem in 1st array ] ≤ A[first elem in 2nd array ]
    

Merging 2 array halves that are already sorted

Another improvement:   check if the 2 (sorted) array halves "overlap" before invocating merge( )

 // Merge sorts the array elements A[s] ... A[e-1] using helper array H

 public static <T extends Comparable<T>> void sort(T[] A, int s, int e, T[] H)
 {
     if ( e - s <= CUTOFF ) // Use a different sort alg for small inputs
     {
         SelectionSort.sort(A, s, e);

         return;            
     }


     int m = (e+s)/2;       // m = middle of s and e
   
     MergeSort.sort(A, s, m, H);

     MergeSort.sort(A, m, e, H);

     // Merge both sorted arrays only when values overlap
     if ( A[m-1] < A[m] )  return;         // Small optimization
     merge(A, s, m, e, H); // We have discussed merge() previously !
 }