// Sorts.java // David Kosbie // Demonstrates various sorting algorithms, // along with timing and testing code. import java.util.*; import static java.lang.System.out; //////////////////////////////////////// // Sorts: Main method to test our sorts //////////////////////////////////////// class Sorts { public static void main(String[] args) { new SelectionSorter().testSort(); new InsertionSorter().testSort(); new BubbleSorter().testSort(); new FourLineSorter().testSort(); new MergeSorter().testSort(); new QuickSorter().testSort(); new RadixSorter().testSort(); new HexRadixSorter().testSort(); new BuiltInSorter().testSort(); } } //////////////////////////////////////// // SelectionSorter //////////////////////////////////////// class SelectionSorter extends Sorter { public void sort(Object[] x) { int n = x.length; for (int i=0; i<=n-2; i++) { int smallestValueIndex = i; for (int j=i+1; j0; j--) if (compare(x,j-1,j) > 0) swap(x,j-1,j); else break; } } //////////////////////////////////////// // BubbleSorter //////////////////////////////////////// class BubbleSorter extends Sorter { public void sort(Object[] x) { boolean didSwap; int n = x.length; do { didSwap = false; for (int i=0; i 0) { swap(x,i,i+1); didSwap = true; } } while (didSwap); } } //////////////////////////////////////// // FourLineSorter //////////////////////////////////////// class FourLineSorter extends Sorter { public void sort(Object[] x) { for (int i=0; i 0) swap(x,i,j); } } //////////////////////////////////////// // MergeSorter //////////////////////////////////////// class MergeSorter extends Sorter { public void sort(Object[] x) { Object[] mergeArray = new Object[x.length]; mergesort(x,0,x.length-1,mergeArray); } private void mergesort(Object[] x, int lo, int hi, Object[] mergeArray) { if (lo >= hi) // base case -- singleton or null array, so it is sorted return; // recursive case: sort left/right halves, then merge int mid = (lo + hi)/2; mergesort(x,lo,mid,mergeArray); mergesort(x,mid+1,hi,mergeArray); merge(x,lo,hi,mergeArray); } private void merge(Object[] x, int lo, int hi, Object[] mergeArray) { int mid = (lo + hi)/2; int i0 = lo; int hi0 = mid; int i1 = mid+1; int hi1 = hi; // copy into mergeArray for (int i=lo; i<=hi; i++) { if ((i0 > hi0) || ((i1 <= hi1) && (compare(x,i0,i1) > 0))) mergeArray[i] = x[i1++]; else mergeArray[i] = x[i0++]; } // copy back from mergeArray to original array for (int i=lo; i<=hi; i++) x[i] = mergeArray[i]; } } //////////////////////////////////////// // QuickSorter //////////////////////////////////////// class QuickSorter extends Sorter { public void sort(Object[] x) { quicksort(x,0,x.length-1); } private void quicksort(Object[] x, int lo, int hi) { if (lo >= hi) // base case -- singleton or null array, so it is sorted return; // recursive case: place pivot in place, then sort left/right halves int pivotIndex = lo; int left = lo+1; int right = hi; while (left < right) { while ((left < right) && (compare(x,left,pivotIndex) <= 0)) left++; while ((left < right) && (compare(x,right,pivotIndex) > 0)) right--; if (left < right) swap(x,left,right); } // now left == right. They either met on the rightmost element of the left // (which is what we want), or the leftmost element of the right (in which // case we'll decrease the pivotIndex by 1). if (compare(x,left,pivotIndex) > 0) pivotIndex = left-1; else pivotIndex = left; swap(x,lo,pivotIndex); // now recursively sort the left/right halves quicksort(x,lo,pivotIndex-1); quicksort(x,pivotIndex+1,hi); } } //////////////////////////////////////// // RadixSorter //////////////////////////////////////// @SuppressWarnings(value={"unchecked"}) class RadixSorter extends Sorter { public void sort(Object[] x) { initBuckets(x); int digits = findMaxDigits(x); for (int digit=0; digit max) max = i; } return max.toString().length(); } // returns the value of the kthDigit, where: // kthDigit(123,0) --> 3 // kthDigit(123,1) --> 2 // kthDigit(123,2) --> 1 // kthDigit(123,3) --> 0 // To find this, divide by 10 k times, then return remainder mod 10: protected int kthDigit(int n, int k) { n /= powersOf10[k]; return n % 10; } protected int kthDigit1(int n, int k) { while (k-- > 0) n /= 10; return n % 10; } protected int kthDigit2(Integer n, int k) { String s = n.toString(); int len = s.length(); if (len <= k) return 0; return (int)(s.charAt(len-1-k)) - '0'; } } //////////////////////////////////////// // HexRadixSorter //////////////////////////////////////// @SuppressWarnings(value={"unchecked"}) class HexRadixSorter extends RadixSorter { public HexRadixSorter() { radix = 16; } protected int findMaxDigits(Object[] x) { int i = super.findMaxDigits(x); if (i >= 0) i = 8; return i; } protected int kthDigit(int n, int k) { // 1. divide n by 16^k. But dividing by 16^k is // the same as right-shifting by 4*k. n = (n >>> (4*k)); // 2. Take n % 16, but that's just the bottom 4 bits: return n & 0xF; } } //////////////////////////////////////// // BuiltInSorter //////////////////////////////////////// class BuiltInSorter extends Sorter { public void sort(Object[] x) { Arrays.sort(x); } } //////////////////////////////////////// // Sorter //////////////////////////////////////// @SuppressWarnings(value={"unchecked"}) abstract class Sorter { abstract public void sort(Object[] x); private static Random random = new Random(); // creates and sorts a random array of Integers of size "size", // and returns the time in milliseconds required to sort public int runTrial(int size) { Object[] a = new Object[size]; for (int i=0; i