CSC 103 Lecture Notes Week 8, Part 2
Sorting Code and Trace Output



  1. Here is some code for the sorting algorithms we're studying
    import java.util.Arrays;
    
    /**
     * A class that contains several sorting routines, implemented as static
     * methods.  Arrays are rearranged with smallest item first, using compares.
     *                                                                          <p>
     * Use the method tracingOn to enable or disable printed tracing information
     * as the methods run.
     *
     * @author Mark Allen Weiss (tracing additions by Gene Fisher)
     */
    public final class Sort
    {
        /**
         * Simple insertion sort.
         * @param a an array of Comparable items.
         */
        public static void insertionSort( Comparable [ ] a )
        {
            for( int p = 1; p < a.length; p++ )
            {
                Comparable tmp = a[ p ];
                int j = p;
    
                for( ; j > 0 && tmp.compareTo( a[ j - 1 ])<0 ; j-- )
                {
                    printTraceLine("    p=" + p + ",j=" + j + " ", a);
    
                    a[ j ] = a[ j - 1 ];
    
                }
                a[ j ] = tmp;
            }
        }
    
    
        /**
         * Shellsort, using a sequence suggested by Gonnet.
         * @param a an array of Comparable items.
         */
        public static void shellsort( Comparable [ ] a )
        {
            for( int gap = a.length / 2; gap > 0;
                         gap = gap == 2 ? 1 : (int) ( gap / 2.2 ) )
                for( int i = gap; i < a.length; i++ )
                {
                    Comparable tmp = a[ i ];
                    int j = i;
    
                    for( ; j >= gap && tmp.compareTo( a[ j - gap ] )<0; j -= gap )
                    {
                      printTraceLine("    i=" + i + ",j=" + j + " ", a);
    
                      a[ j ] = a[ j - gap ];
    
                    }
    
                    a[ j ] = tmp;
                }
        }
    
        /**
         * Standard heapsort.
         * @param a an array of Comparable items.
         */
        public static void heapsort( Comparable [ ] a )
        {
            for( int i = a.length / 2; i >= 0; i-- )  /* buildHeap */
                percDown( a, i, a.length );
    
            for( int i = a.length - 1; i > 0; i-- )
            {
                printTraceLine("    pre-swap, i=" + i + " ", a);
    
                swapReferences( a, 0, i );            /* deleteMax */
    
                printTraceLine("    pre-perc, i=" + i + " ", a);
    
                percDown( a, 0, i );
            }
        }
    
        /**
         * Internal method for heapsort.
         * @param i the index of an item in the heap.
         * @return the index of the left child.
         */
        private static int leftChild( int i )
        {
            return 2 * i + 1;
        }
    
        /**
         * Internal method for heapsort that is used in
         * deleteMax and buildHeap.
         * @param a an array of Comparable items.
         * @index i the position from which to percolate down.
         * @int n the logical size of the binary heap.
         */
        private static void percDown( Comparable [ ] a, int i, int n )
        {
            int child;
            Comparable tmp;
    
            for( tmp = a[ i ]; leftChild( i ) < n; i = child )
            {
                child = leftChild( i );
    
                if( child != n - 1 && a[ child ].compareTo( a[ child + 1 ] )<0 )
                     child++;
               if( tmp.compareTo( a[ child ] ) <0)
                    a[ i ] = a[ child ];
                else
                    break;
            }
            a[ i ] = tmp;
        }
    
        /**
         * Mergesort algorithm.
         * @param a an array of Comparable items.
         */
        public static void mergeSort( Comparable [ ] a )
        {
            Comparable [ ] tmpArray = new Comparable[ a.length ];
    
            mergeSort( a, tmpArray, 0, a.length - 1, 0 );
        }
    
        /**
         * Internal method that makes recursive calls.
         * @param a an array of Comparable items.
         * @param tmpArray an array to place the merged result.
         * @param left the left-most index of the subarray.
         * @param right the right-most index of the subarray.
         */
        private static void mergeSort( Comparable [ ] a, Comparable [ ] tmpArray,
                   int left, int right, int phase )
        {
            if( left < right )
            {
                int center = ( left + right ) / 2;
    
                mergeSort( a, tmpArray, left, center, 0 );
                mergeSort( a, tmpArray, center + 1, right, 1 );
                merge( a, tmpArray, left, center + 1, right );
            }
        }
    
        /**
         * Internal method that merges two sorted halves of a subarray.
         * @param a an array of Comparable items.
         * @param tmpArray an array to place the merged result.
         * @param leftPos the left-most index of the subarray.
         * @param rightPos the index of the start of the second half.
         * @param rightEnd the right-most index of the subarray.
         */
        private static void merge( Comparable [ ] a, Comparable [ ] tmpArray,
               int leftPos, int rightPos, int rightEnd )
        {
            int leftEnd = rightPos - 1;
            int tmpPos = leftPos;
            int numElements = rightEnd - leftPos + 1;
    
    //      if (tracingOn) {
                System.out.println(
                    "    merging " + leftPos + "," + rightPos + "," + rightEnd);
    //      }
    
            // Main loop
            while( leftPos <= leftEnd && rightPos <= rightEnd )
                if( a[ leftPos ].compareTo( a[ rightPos ] )<0 )
                    tmpArray[ tmpPos++ ] = a[ leftPos++ ];
                else
                    tmpArray[ tmpPos++ ] = a[ rightPos++ ];
    
            while( leftPos <= leftEnd )    // Copy rest of first half
                tmpArray[ tmpPos++ ] = a[ leftPos++ ];
    
            while( rightPos <= rightEnd )  // Copy rest of right half
                tmpArray[ tmpPos++ ] = a[ rightPos++ ];
    
            // Copy TmpArray back
            for( int i = 0; i < numElements; i++, rightEnd-- )
                a[ rightEnd ] = tmpArray[ rightEnd ];
    
            System.out.println("        " + Arrays.asList(a));
        }
    
        /**
         * Quicksort algorithm.
         * @param a an array of Comparable items.
         */
        public static void quicksort( Comparable [ ] a )
        {
            quicksort( a, 0, a.length - 1 );
        }
    
        private static final int CUTOFF = 10;
    
        /**
         * Method to swap to elements in an array.
         * @param a an array of objects.
         * @param index1 the index of the first object.
         * @param index2 the index of the second object.
         */
        public static void swapReferences( Object [ ] a, int index1, int index2 )
        {
            Object tmp = a[ index1 ];
            a[ index1 ] = a[ index2 ];
            a[ index2 ] = tmp;
        }
    
        /**
         * Internal quicksort method that makes recursive calls.
         * Uses median-of-three partitioning and a cutoff of 10.
         * @param a an array of Comparable items.
         * @param low the left-most index of the subarray.
         * @param high the right-most index of the subarray.
         */
        private static void quicksort( Comparable [ ] a, int low, int high )
        {
            if( low + CUTOFF > high )
                insertionSort( a, low, high );
            else
            {
    
                printTraceLine("    before pivot placement,   low=" + low +
                    ",high=" + high + " ", a);
    
                    // Sort low, middle, high
                int middle = ( low + high ) / 2;
                if( a[ middle ].compareTo( a[ low ] )<0 )
                    swapReferences( a, low, middle );
                if( a[ high ].compareTo( a[ low ] )<0 )
                    swapReferences( a, low, high );
                if( a[ high ].compareTo( a[ middle ] ) <0)
                    swapReferences( a, middle, high );
    
                    // Place pivot at position high - 1
                swapReferences( a, middle, high - 1 );
                Comparable pivot = a[ high - 1 ];
    
                printTraceLine("    before partioning,        low=" + low +
                    ",high=" + high + " ", a);
    
                    // Begin partitioning
                int i, j;
                for( i = low, j = high - 1; ; )
                {
                    while( a[ ++i ].compareTo( pivot )<0 )
                        ;
                    while( pivot.compareTo( a[ --j ] )<0 )
                        ;
                    if( i < j )
                        swapReferences( a, i, j );
                    else
                        break;
                }
    
                    // Restore pivot
                swapReferences( a, i, high - 1 );
    
                quicksort( a, low, i - 1 );    // Sort small elements
                quicksort( a, i + 1, high );   // Sort large elements
            }
        }
    
        /**
         * Internal insertion sort routine for subarrays
         * that is used by quicksort.
         * @param a an array of Comparable items.
         * @param low the left-most index of the subarray.
         * @param n the number of items to sort.
         */
        private static void insertionSort( Comparable [ ] a, int low, int high )
        {
            for( int p = low + 1; p <= high; p++ )
            {
                Comparable tmp = a[ p ];
                int j;
    
                for( j = p; j > low && tmp.compareTo( a[ j - 1 ] )<0; j-- )
                    a[ j ] = a[ j - 1 ];
                a[ j ] = tmp;
            }
        }
    
        /**
         * Quick selection algorithm.
         * Places the kth smallest item in a[k-1].
         * @param a an array of Comparable items.
         * @param k the desired rank (1 is minimum) in the entire array.
         */
        public static void quickSelect( Comparable [ ] a, int k )
        {
            quickSelect( a, 0, a.length - 1, k );
        }
    
        /**
         * Internal selection method that makes recursive calls.
         * Uses median-of-three partitioning and a cutoff of 10.
         * Places the kth smallest item in a[k-1].
         * @param a an array of Comparable items.
         * @param low the left-most index of the subarray.
         * @param high the right-most index of the subarray.
         * @param k the desired rank (1 is minimum) in the entire array.
         */
        private static void quickSelect( Comparable [ ] a, int low, int high, int k )
        {
            if( low + CUTOFF > high )
                insertionSort( a, low, high );
            else
            {
                    // Sort low, middle, high
                int middle = ( low + high ) / 2;
                  if( a[ middle ].compareTo( a[ low ] ) <0)
                    swapReferences( a, low, middle );
                  if( a[ high ].compareTo( a[ low ] ) <0)
                    swapReferences( a, low, high );
                  if( a[ high ].compareTo( a[ middle ] )<0 )
                    swapReferences( a, middle, high );
    
                    // Place pivot at position high - 1
                swapReferences( a, middle, high - 1 );
                Comparable pivot = a[ high - 1 ];
    
                    // Begin partitioning
                int i, j;
                for( i = low, j = high - 1; ; )
                {
                      while( a[ ++i ].compareTo( pivot )<0 )
                        ;
                      while( pivot.compareTo( a[ --j ] )<0 )
                        ;
                    if( i < j )
                        swapReferences( a, i, j );
                    else
                        break;
                }
    
                    // Restore pivot
                swapReferences( a, i, high - 1 );
    
                    // Recurse; only this part changes
                if( k <= i )
                    quickSelect( a, low, i - 1, k );
                else if( k > i + 1 )
                    quickSelect( a, i + 1, high, k );
            }
        }
    
        /**
         * Turn tracing on or off.
         */
        public static void setTracingOn(boolean on) {
            tracingOn = on;
        }
    
        /**
         * If this.tracingOn is true, print a line of tracing information to
         * stdout.  The inforation consists of the given string message followed by
         * a space-delimited list of the elements in the give array.  This method
         * is called from within the sorting methods to help trace the progress of
         * the sort.
         */
        protected static void printTraceLine(String message, Object[] array) {
    
            if (tracingOn) {
                System.out.println(message + Arrays.asList(array));
            }
    
        }
    
        /**
         * Like printTraceLine, but also prints a stack trace, for use in tracing
         * recursive sort algorithms.
         */
        protected static void printTraceLine2(String message, Object[] array) {
    
            if (tracingOn) {
                System.out.println(message + Arrays.asList(array));
                try {
                    throw (new Exception());
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
        }
    
        /** Method tracing is on if tracingOn == true. */
        protected static boolean tracingOn = false;
    
    }
    

  2. Here are some sorting execution traces on the randomly unsorted list [8,5,3,1,0,9,7,4,2,6]
    Insertion sort:
        [8, 5, 3, 1, 0, 9, 7, 4, 2, 6]
        p=1,j=1 [8, 5, 3, 1, 0, 9, 7, 4, 2, 6]
        p=2,j=2 [5, 8, 3, 1, 0, 9, 7, 4, 2, 6]
        p=2,j=1 [5, 8, 8, 1, 0, 9, 7, 4, 2, 6]
        p=3,j=3 [3, 5, 8, 1, 0, 9, 7, 4, 2, 6]
        p=3,j=2 [3, 5, 8, 8, 0, 9, 7, 4, 2, 6]
        p=3,j=1 [3, 5, 5, 8, 0, 9, 7, 4, 2, 6]
        p=4,j=4 [1, 3, 5, 8, 0, 9, 7, 4, 2, 6]
        p=4,j=3 [1, 3, 5, 8, 8, 9, 7, 4, 2, 6]
        p=4,j=2 [1, 3, 5, 5, 8, 9, 7, 4, 2, 6]
        p=4,j=1 [1, 3, 3, 5, 8, 9, 7, 4, 2, 6]
        p=6,j=6 [0, 1, 3, 5, 8, 9, 7, 4, 2, 6]
        p=6,j=5 [0, 1, 3, 5, 8, 9, 9, 4, 2, 6]
        p=7,j=7 [0, 1, 3, 5, 7, 8, 9, 4, 2, 6]
        p=7,j=6 [0, 1, 3, 5, 7, 8, 9, 9, 2, 6]
        p=7,j=5 [0, 1, 3, 5, 7, 8, 8, 9, 2, 6]
        p=7,j=4 [0, 1, 3, 5, 7, 7, 8, 9, 2, 6]
        p=8,j=8 [0, 1, 3, 4, 5, 7, 8, 9, 2, 6]
        p=8,j=7 [0, 1, 3, 4, 5, 7, 8, 9, 9, 6]
        p=8,j=6 [0, 1, 3, 4, 5, 7, 8, 8, 9, 6]
        p=8,j=5 [0, 1, 3, 4, 5, 7, 7, 8, 9, 6]
        p=8,j=4 [0, 1, 3, 4, 5, 5, 7, 8, 9, 6]
        p=8,j=3 [0, 1, 3, 4, 4, 5, 7, 8, 9, 6]
        p=9,j=9 [0, 1, 2, 3, 4, 5, 7, 8, 9, 6]
        p=9,j=8 [0, 1, 2, 3, 4, 5, 7, 8, 9, 9]
        p=9,j=7 [0, 1, 2, 3, 4, 5, 7, 8, 8, 9]
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    Shellsort:
        [8, 5, 3, 1, 0, 9, 7, 4, 2, 6]
        i=2,j=2 [8, 5, 3, 1, 0, 9, 7, 4, 2, 6]
        i=3,j=3 [3, 5, 8, 1, 0, 9, 7, 4, 2, 6]
        i=4,j=4 [3, 1, 8, 5, 0, 9, 7, 4, 2, 6]
        i=4,j=2 [3, 1, 8, 5, 8, 9, 7, 4, 2, 6]
        i=6,j=6 [0, 1, 3, 5, 8, 9, 7, 4, 2, 6]
        i=7,j=7 [0, 1, 3, 5, 7, 9, 8, 4, 2, 6]
        i=7,j=5 [0, 1, 3, 5, 7, 9, 8, 9, 2, 6]
        i=8,j=8 [0, 1, 3, 4, 7, 5, 8, 9, 2, 6]
        i=8,j=6 [0, 1, 3, 4, 7, 5, 8, 9, 8, 6]
        i=8,j=4 [0, 1, 3, 4, 7, 5, 7, 9, 8, 6]
        i=9,j=9 [0, 1, 2, 4, 3, 5, 7, 9, 8, 6]
        i=4,j=4 [0, 1, 2, 4, 3, 5, 7, 6, 8, 9]
        i=7,j=7 [0, 1, 2, 3, 4, 5, 7, 6, 8, 9]
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    Heapsort:
        [8, 5, 3, 1, 0, 9, 7, 4, 2, 6]
        pre-swap, i=9 [9, 6, 8, 4, 5, 3, 7, 1, 2, 0]
        pre-perc, i=9 [0, 6, 8, 4, 5, 3, 7, 1, 2, 9]
        pre-swap, i=8 [8, 6, 7, 4, 5, 3, 0, 1, 2, 9]
        pre-perc, i=8 [2, 6, 7, 4, 5, 3, 0, 1, 8, 9]
        pre-swap, i=7 [7, 6, 3, 4, 5, 2, 0, 1, 8, 9]
        pre-perc, i=7 [1, 6, 3, 4, 5, 2, 0, 7, 8, 9]
        pre-swap, i=6 [6, 5, 3, 4, 1, 2, 0, 7, 8, 9]
        pre-perc, i=6 [0, 5, 3, 4, 1, 2, 6, 7, 8, 9]
        pre-swap, i=5 [5, 4, 3, 0, 1, 2, 6, 7, 8, 9]
        pre-perc, i=5 [2, 4, 3, 0, 1, 5, 6, 7, 8, 9]
        pre-swap, i=4 [4, 2, 3, 0, 1, 5, 6, 7, 8, 9]
        pre-perc, i=4 [1, 2, 3, 0, 4, 5, 6, 7, 8, 9]
        pre-swap, i=3 [3, 2, 1, 0, 4, 5, 6, 7, 8, 9]
        pre-perc, i=3 [0, 2, 1, 3, 4, 5, 6, 7, 8, 9]
        pre-swap, i=2 [2, 0, 1, 3, 4, 5, 6, 7, 8, 9]
        pre-perc, i=2 [1, 0, 2, 3, 4, 5, 6, 7, 8, 9]
        pre-swap, i=1 [1, 0, 2, 3, 4, 5, 6, 7, 8, 9]
        pre-perc, i=1 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    Mergesort:
        [8, 5, 3, 1, 0, 9, 7, 4, 2, 6]
        before 1st merge,   left=0,right=9 [8, 5, 3, 1, 0, 9, 7, 4, 2, 6]
        before 1st merge,   left=0,right=4 [8, 5, 3, 1, 0, 9, 7, 4, 2, 6]
        before 1st merge,   left=0,right=2 [8, 5, 3, 1, 0, 9, 7, 4, 2, 6]
        before 1st merge,   left=0,right=1 [8, 5, 3, 1, 0, 9, 7, 4, 2, 6]
        before 2nd merge,   left=0,right=1 [8, 5, 3, 1, 0, 9, 7, 4, 2, 6]
        before final merge, left=0,right=1 [8, 5, 3, 1, 0, 9, 7, 4, 2, 6]
        before 2nd merge,   left=0,right=2 [5, 8, 3, 1, 0, 9, 7, 4, 2, 6]
        before final merge, left=0,right=2 [5, 8, 3, 1, 0, 9, 7, 4, 2, 6]
        before 2nd merge,   left=0,right=4 [3, 5, 8, 1, 0, 9, 7, 4, 2, 6]
        before 1st merge,   left=3,right=4 [3, 5, 8, 1, 0, 9, 7, 4, 2, 6]
        before 2nd merge,   left=3,right=4 [3, 5, 8, 1, 0, 9, 7, 4, 2, 6]
        before final merge, left=3,right=4 [3, 5, 8, 1, 0, 9, 7, 4, 2, 6]
        before final merge, left=0,right=4 [3, 5, 8, 0, 1, 9, 7, 4, 2, 6]
        before 2nd merge,   left=0,right=9 [0, 1, 3, 5, 8, 9, 7, 4, 2, 6]
        before 1st merge,   left=5,right=9 [0, 1, 3, 5, 8, 9, 7, 4, 2, 6]
        before 1st merge,   left=5,right=7 [0, 1, 3, 5, 8, 9, 7, 4, 2, 6]
        before 1st merge,   left=5,right=6 [0, 1, 3, 5, 8, 9, 7, 4, 2, 6]
        before 2nd merge,   left=5,right=6 [0, 1, 3, 5, 8, 9, 7, 4, 2, 6]
        before final merge, left=5,right=6 [0, 1, 3, 5, 8, 9, 7, 4, 2, 6]
        before 2nd merge,   left=5,right=7 [0, 1, 3, 5, 8, 7, 9, 4, 2, 6]
        before final merge, left=5,right=7 [0, 1, 3, 5, 8, 7, 9, 4, 2, 6]
        before 2nd merge,   left=5,right=9 [0, 1, 3, 5, 8, 4, 7, 9, 2, 6]
        before 1st merge,   left=8,right=9 [0, 1, 3, 5, 8, 4, 7, 9, 2, 6]
        before 2nd merge,   left=8,right=9 [0, 1, 3, 5, 8, 4, 7, 9, 2, 6]
        before final merge, left=8,right=9 [0, 1, 3, 5, 8, 4, 7, 9, 2, 6]
        before final merge, left=5,right=9 [0, 1, 3, 5, 8, 4, 7, 9, 2, 6]
        before final merge, left=0,right=9 [0, 1, 3, 5, 8, 2, 4, 6, 7, 9]
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    Quicksort:
        [8, 5, 3, 1, 0, 9, 7, 4, 2, 6]
        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    




index | lectures | labs | handouts | examples | assignments | solutions | doc | grades | help