import java.util.*; class Demo { public static void main (String[] args) { runSort(new SelectionSort(), "Selection Sort"); // runSort(new InsertionSort(), "Insertion Sort"); // runSort(new MergeSort(), "Merge Sort"); // runSort(new QuickSortBad(), "Not So Good Quick Sort"); // runSort(new BubbleSort(), "Bubble Sort"); // runSort(new BetterBubbleSort(), "Better Bubble Sort"); // runSort(new QuickSort(), "Better Quick Sort"); } static void runSort(Sort sorter, String sortName) { System.out.println("\n" + sortName + "\n"); // Use 25600 for Selection, Insertion and Bubble // Use 102400 for Mergesort and Quick Sort (fast) // Use 6400 for Bad Quick Sort for (int SIZE = 100; SIZE <= 25600; SIZE *= 2) { long start, end; long elapsed1 = 0, elapsed2 = 0, elapsed3 = 0; Comparable [ ] a = new Integer [ SIZE ]; // sorted input for( int i = 0; i < SIZE; i++ ) a[ i ] = new Integer( i ); start = System.currentTimeMillis(); sorter.sort( a ); end = System.currentTimeMillis(); elapsed1 = end - start; checkSort(a); // reverse sorted input for( int i = 0; i < SIZE; i++ ) a[ i ] = new Integer( SIZE - i ); start = System.currentTimeMillis(); sorter.sort( a ); end = System.currentTimeMillis(); elapsed2 = end - start; checkSort(a); // random input Random r = new Random(); for( int i = 0; i < SIZE; i++ ) a[ i ] = new Integer( r.nextInt(SIZE) ); start = System.currentTimeMillis(); sorter.sort( a ); end = System.currentTimeMillis(); elapsed3 = end - start; checkSort(a); System.out.println("size: " + SIZE + "\tsorted: " + elapsed1 + "\treverse: " + elapsed2 + "\trandom: " + elapsed3); } } static void checkSort(Comparable[] array) { for( int i = 0; i < array.length-1; i++ ) { if( array[i].compareTo(array[i+1]) > 0 ) { System.out.println( "array not sorted array["+i+"]=" + array[i] + " array["+ (i+1) + "]=" + array[i+1]); } } } } interface Sort { public void sort( Comparable [ ] a ); } class SelectionSort implements Sort { public void sort (Comparable[] a) { for (int i = 0; i < a.length-1; i++) { int min = i; for (int j = i+1; j < a.length; j++) if (a[j].compareTo(a[min]) < 0) min = j; Comparable tmp = a[min]; a[min] = a[i]; a[i] = tmp; } } } class InsertionSort implements Sort { public void sort( Comparable [ ] a ) { for( int p = 1; p < a.length; p++ ) { Comparable tmp = a[ p ]; int j; for(j = p ; j > 0 && tmp.compareTo( a[ j - 1 ] ) < 0; j-- ) a[ j ] = a[ j - 1 ]; a[ j ] = tmp; } } } class BubbleSort implements Sort { public void sort (Comparable[] a) { for (int i = 0; i < a.length; i++) { for (int j = 0; j < a.length-1; j++) { if (a[j].compareTo(a[j+1]) > 0) { Comparable tmp = a[j]; a[j] = a[j+1]; a[j+1] = tmp; } } } } } class BetterBubbleSort implements Sort { public void sort (Comparable[] a) { for (int i = 0; i < a.length; i++) { boolean swap = false; for (int j = 0; j < a.length-1-i; j++) { if (a[j].compareTo(a[j+1]) > 0) { Comparable tmp = a[j]; a[j] = a[j+1]; a[j+1] = tmp; swap = true; } } if (!swap) break; } } } class MergeSort implements Sort { public void sort (Comparable[] a) { mergeSort( a, 0, a.length - 1 ); } static void mergeSort( Comparable [ ] a, int left, int right ) { if( left < right ) { int center = ( left + right ) / 2; mergeSort( a, left, center ); mergeSort( a, center + 1, right ); merge( a, left, center, right ); } } static void merge( Comparable [ ] a, int left, int center, int right ) { int size = right - left + 1; Comparable [ ] tmp = new Comparable[ size ]; int i = 0; int leftPos = left; int rightPos = center+1; while( leftPos <= center && rightPos <= right ) if( a[ leftPos ].compareTo( a[ rightPos ] ) <= 0 ) tmp[ i++ ] = a[ leftPos++ ]; else tmp[ i++ ] = a[ rightPos++ ]; while( leftPos <= center ) tmp[ i++ ] = a[ leftPos++ ]; while( rightPos <= right ) tmp[ i++ ] = a[ rightPos++ ]; for( i = 0; i < size; i++ ) a[ left+i ] = tmp[ i ]; } } class QuickSort implements Sort { public void sort (Comparable[] a) { quicksort( a, 0, a.length - 1 ); } private static final int CUTOFF = 10; public static final void swapReferences( Object [ ] a, int index1, int index2 ) { Object tmp = a[ index1 ]; a[ index1 ] = a[ index2 ]; a[ index2 ] = tmp; } private static void quicksort( Comparable [ ] a, int low, int high ) { 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 ) break; swapReferences( a, i, j ); } // Restore pivot swapReferences( a, i, high - 1 ); quicksort( a, low, i - 1 ); // Sort small elements quicksort( a, i + 1, high ); // Sort large elements } } 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; } } } class QuickSortBad implements Sort { public void sort (Comparable[] a) { quicksortBad( a, 0, a.length - 1 ); } static void quicksortBad( Comparable [ ] a, int low, int high ) { if( low < high ) { int pivot = partition(a, low, high); quicksortBad( a, low, pivot - 1 ); quicksortBad( a, pivot + 1, high ); } } static int partition (Comparable[] a, int low, int high) { Comparable pivot = a[low]; int i = low; int j = high+1; while (i < j) { do i++; while(i < j && a[ i ].compareTo( pivot ) < 0 ); do j--; while(i <= j && a[ j ].compareTo( pivot ) > 0 ); if (i < j) { Comparable temp = a[i]; a[i] = a[j]; a[j] = temp; } } a[low] = a[j]; a[j] = pivot; return j; } }