// CSE 143, Winter 2009, Marty Stepp // This program compares the runtime of the selection and merge // sort algorithms. You can change the LENGTH constant to // run it with a different amount of elements. // // On Marty's computer, selection sort takes the following times: // // 240 ms to sort 10000 elements // 962 ms to sort 20000 elements // 3905 ms to sort 40000 elements // 15122 ms to sort 80000 elements // // (Notice that the runtime roughly quadruples when the input size doubles. // This shows that the runtime of selection sort is O(N^2), which is consistent // with the fact that the code has two nested for loops over the array.) // // On Marty's computer, merge sort takes the following times: // // 51 ms to sort 80000 elements // 101 ms to sort 160000 elements // 260 ms to sort 320000 elements // 451 ms to sort 640000 elements // 911 ms to sort 1250000 elements // 1882 ms to sort 2500000 elements // 5468 ms to sort 5000000 elements // 7881 ms to sort 10000000 elements // 19368 ms to sort 20000000 elements // // (Notice that the runtime slightly more than doubles when the input size // doubles. One might conclude that this is O(N), but it's actually O(N log N). // We will discuss why in a coming lecture. import java.util.*; // for Random public class Sorting { private static final Random RAND = new Random(); // random number generator private static final int LENGTH = 1000000; // length of array to sort public static void main(String[] args) { System.out.println("Creating the array...\n"); int[] a = createArray(LENGTH); System.out.println("Performing sorts...\n"); long startTime = System.currentTimeMillis(); // perform a sort and time how long it takes // selectionSort(a); // O(N^2) mergeSort(a); // O(N log N) long endTime = System.currentTimeMillis(); long elapsedTime = endTime - startTime; ensureSorted(a); System.out.println(elapsedTime + " ms to sort " + LENGTH + " elements"); } // Rearranges the elements of a into sorted order using the // merge sort algorithm. public static void mergeSort(int[] a) { if (a.length == 1) { // base case // do nothing; an array of 1 element is sorted by definition } else { // recursive case // divide list into two halves int[] left = new int[a.length / 2]; for (int i = 0; i < left.length; i++) { left[i] = a[i]; } // a.length / 2 + a.length % 2 int[] right = new int[a.length - left.length]; for (int i = 0; i < right.length; i++) { right[i] = a[left.length + i]; } // sort left half mergeSort(left); // sort right half mergeSort(right); // merge the two sorted halves into a sorted whole int i1 = 0; // index in left array int i2 = 0; // index in right array for (int i = 0; i < a.length; i++) { // index in a (result array) // compare left/right element; pick smaller one if (i2 >= right.length || (i1 < left.length && left[i1] < right[i2])) { a[i] = left[i1]; i1++; } else { a[i] = right[i2]; i2++; } } } } // Rearranges the elements of a into sorted order using // the selection sort algorithm. public static void selectionSort(int[] a) { for (int i = 0; i < a.length - 1; i++) { // look for smallest element int minIndex = i; for (int j = i + 1; j < a.length; j++) { if (a[j] < a[minIndex]) { minIndex = j; } } swap(a, minIndex, i); } } // Swaps a[i] with a[j]. public static void swap(int[] a, int i, int j) { if (i != j) { int temp = a[i]; a[i] = a[j]; a[j] = temp; } } // Creates an array of the given length, fills it with random data, // and returns it. public static int[] createArray(int length) { int[] a = new int[length]; for (int i = 0; i < a.length; i++) { a[i] = RAND.nextInt(1000000000); } return a; } // Checks whether the given array is in sorted order. // Throws an IllegalStateException if it is not. public static void ensureSorted(int[] a) { for (int i = 0; i < a.length - 1; i++) { if (a[i] > a[i + 1]) { throw new IllegalStateException("array not sorted at index " + i); } } } }