Review:  
  the
  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
   
     /* ------------------------------------------------
        The actual merge sort:
             (1) sort the first half of the array using MergeSort
             (2) sort the 2nd half of the array using MergeSort
             (3) merge the 2 sorted portions
        ------------------------------------------------ */
     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 !
 } 
   |  
  
  
 
  
  
 
  
  
  
  
 
  
  
  
  
  
   Synopsis of
  the
  merge sort algorithm
 
  
  
  
  
  
 
   
  Summary of the
  merge sort
  algorithm
  
  
  
  
  
 
  
  
 
  
  
  
  
 
  
  
  
  
  
   Recurrence relation of
   the running time of
  the
  merge sort algorithm
 
  
  
  
  
  
  Suppose that
  the running time of 
  MergeSort.sort(A, n, H) is
   
  T(n):
  
  
  
  
  
 
  
  
  
  T(n) = 0
             
            
 for  n <= 1
 
  T(n) = 2 T(n/2) + 2n
       
  for  n >= 2
  
  
  
  
 
  
  
  
  
  
  
  Solving the
  recurrence relation 
 of
   the running time of
  the
  merge sort algorithm
  
  
  
  
  
  
  
  
  
  
  
  
  
   
  
  
  -  The recurrence relation that
   represents the
   running time of the
  Merge Sort algorithm:
 
 
 T(n) = # primitive operations performed by Merge Sort for input size n 
 T(n) = 2T(n/2) + cn              for n >= 2     (c = 2)
 T(n) = 0                         for n  = 1
 
 |   
 
     
  
   |  
  
  
  
  
  
  
  
  
  
  
 
  
  
  
  
  
  
  Solving the
  recurrence relation 
 of
   the running time of
  the
  merge sort algorithm
  
  
  
  
  
  
  
  
  
  
  
  
  
   
  
  
  -  We use the telescoping technique to
        solve T(n):
 
 
 T(n) = # primitive operations performed by Merge Sort for input size n 
 T(n) = 2T(n/2) + cn              for n >= 2     (c = 2)
 T(n) = 0                         for n  = 1
 T(n) = 2T(n/2) + cn              // T(n/2) = 2T(n/4) + c(n/2)
 
 |   
 
     
  
   |  
  
  
  
  
  
  
  
  
  
  
 
  
  
  
  
  
  
  Solving the
  recurrence relation 
 of
   the running time of
  the
  merge sort algorithm
  
  
  
  
  
  
  
  
  
  
  
  
  
   
  
  
  -  Substitute
      T(n/2):
 
 
 T(n) = # primitive operations performed by Merge Sort for input size n 
 T(n) = 2T(n/2) + cn              for n >= 2     (c = 2)
 T(n) = 0                         for n  = 1
 T(n) = 2T(n/2) + cn              // T(n/2) = 2T(n/4) + c(n/2)
 T(n) = 2( 2T(n/4) + c(n/2) ) + cn
      = 22T(n/4)   + 2cn/2 + cn
      = 22T(n/4)   + cn + cn
   
 |   
 
     
  
   |  
  
  
  
  
  
  
  
  
  
  
 
  
  
  
  
  
  
  Solving the
  recurrence relation 
 of
   the running time of
  the
  merge sort algorithm
  
  
  
  
  
  
  
  
  
  
  
  
  
   
  
  
  -  Use formula for
      T(n) to 
       obtain a formula for
       T(n/4)
 
 
 T(n) = # primitive operations performed by Merge Sort for input size n 
 T(n) = 2T(n/2) + cn              for n >= 2     (c = 2)
 T(n) = 0                         for n  = 1
 T(n) = 2T(n/2) + cn              // T(n/2) = 2T(n/4) + c(n/2)
 T(n) = 2( 2T(n/4) + c(n/2) ) + cn
      = 22T(n/4)   + 2cn/2 + cn
      = 22T(n/4)   + cn + cn      // T(n/4) = 2T(n/8) + c(n/8)
   
 |   
 
     
  
   |  
  
  
  
  
  
  
  
  
  
  
 
  
  
  
  
  
  
  Solving the
  recurrence relation 
 of
   the running time of
  the
  merge sort algorithm
  
  
  
  
  
  
  
  
  
  
  
  
  
   
  
  
  -  Substitute
       T(n/4):
 
 
 T(n) = # primitive operations performed by Merge Sort for input size n 
 T(n) = 2T(n/2) + cn              for n >= 2     (c = 2)
 T(n) = 0                         for n  = 1
 T(n) = 2T(n/2) + cn              // T(n/2) = 2T(n/4) + c(n/2)
 T(n) = 2( 2T(n/4) + c(n/2) ) + cn
      = 22T(n/4)   + 2cn/2 + cn
      = 22T(n/4)   + cn + cn      // T(n/4) = 2T(n/8) + c(n/8)
 T(n) = 22( 2T(n/8) + c(n/8) ) + cn + cn
      = 23T(n/8)    + 8cn/8    + cn + cn
      = 23T(n/8)    + cn + cn + cn
 |   
 
     
  
   |  
  
  
  
  
  
  
  
  
  
  
 
  
  
  
  
  
  
  Solving the
  recurrence relation 
 of
   the running time of
  the
  merge sort algorithm
  
  
  
  
  
  
  
  
  
  
  
  
  
   
  
  
  -  Keep on       
        substituting until
	we reach the
	base case:
   
 
 
 T(n) = # primitive operations performed by Merge Sort for input size n 
 T(n) = 2T(n/2) + cn              for n >= 2     (c = 2)
 T(n) = 0                         for n  = 1
 T(n) = 2T(n/2) + cn              // T(n/2) = 2T(n/4) + c(n/2)
 T(n) = 2( 2T(n/4) + c(n/2) ) + cn
      = 22T(n/4)   + 2cn/2 + cn
      = 22T(n/4)   + cn + cn      // T(n/4) = 2T(n/8) + c(n/8)
 T(n) = 22( 2T(n/8) + c(n/8) ) + cn + cn
      = 23T(n/8)    + 8cn/8    + cn + cn
      = 23T(n/8)    + cn + cn + cn
 ...
 T(n) = 2kT(n/(2k)=1)    + cn + cn + cn + cn + ... + cn
                           <-------------------------->
                                   k terms
      = 2k * 0 + k(cn) = kcn
 |   
 
     
  
   |  
  
  
  
  
  
  
  
  
  
  
 
  
  
  
  
  
  
  Solving the
  recurrence relation 
 of
   the running time of
  the
  merge sort algorithm
  
  
  
  
  
  
  
  
  
  
  
  
  
   
  
  
  -  Solve       
        k
       (= log(n)):
   
 
 
 T(n) = # primitive operations performed by Merge Sort for input size n 
 T(n) = 2T(n/2) + cn              for n >= 2     (c = 2)
 T(n) = 0                         for n  = 1
 T(n) = 2T(n/2) + cn              // T(n/2) = 2T(n/4) + c(n/2)
 T(n) = 2( 2T(n/4) + c(n/2) ) + cn
      = 22T(n/4)   + 2cn/2 + cn
      = 22T(n/4)   + cn + cn      // T(n/4) = 2T(n/8) + c(n/8)
 T(n) = 22( 2T(n/8) + c(n/8) ) + cn + cn
      = 23T(n/8)    + 8cn/8    + cn + cn
      = 23T(n/8)    + cn + cn + cn
 ...
 T(n) = 2kT(n/(2k)=1)    + cn + cn + cn + cn + ... + cn
                           <-------------------------->
                                   k terms
      = 2k * 0 + k(cn) = kcn
 n/(2k) = 1  <==>   2k = n   <==>  k = log(n)
 |   
 
     
  
   |  
  
  
  
  
  
  
  
  
  
  
 
  
  
  
  
  
  
  Solving the
  recurrence relation 
 of
   the running time of
  the
  merge sort algorithm
  
  
  
  
  
  
  
  
  
  
  
  
  
   
  
  
  -  We find that the
  running time of the
  Merge Sort algorithm is
  O(nlog(n):
   
 
 
 T(n) = # primitive operations performed by Merge Sort for input size n 
 T(n) = 2T(n/2) + cn              for n >= 2     (c = 2)
 T(n) = 0                         for n  = 1
 T(n) = 2T(n/2) + cn              // T(n/2) = 2T(n/4) + c(n/2)
 T(n) = 2( 2T(n/4) + c(n/2) ) + cn
      = 22T(n/4)   + 2cn/2 + cn
      = 22T(n/4)   + cn + cn      // T(n/4) = 2T(n/8) + c(n/8)
 T(n) = 22( 2T(n/8) + c(n/8) ) + cn + cn
      = 23T(n/8)    + 8cn/8    + cn + cn
      = 23T(n/8)    + cn + cn + cn
 ...
 T(n) = 2kT(n/(2k)=1)    + cn + cn + cn + cn + ... + cn
                           <-------------------------->
                                   k terms
      = 2k * 0 + k(cn) = kcn
 n/(2k) = 1  <==>   2k = n   <==>  k = log(n)
 Running time = kcn = cnlog(n) = 2nlog(n)   or  O(nlog(n))
 |   
 
     
  
   |  
  
  
  
  
  
  
  
  
  
  
 
  
  
  
  
  
  
  
  
  
  
  
 
  
  
       ❮
  
       ❯