import java.util.Arrays; import java.util.Random; /** * This quicksort implementation has problems. Your job is to identify the * issues. * * @author Joanna Klukowska * */ public class QuickSortTester { //random number generator static private Random rand = new Random(0); public static void main(String[] args) { //set the size of the array for all tests int arraySize = 10000; Integer[] list; long start, end; System.out.printf ( "%15s", " " ); System.out.printf ( "\t%15s", "random" ); System.out.printf ( "\t%15s", "random-narrow" ); System.out.printf ( "\t%15s", "sorted-asc" ); for (int part = 0; part <=3; part++) { //for each partition function System.out.printf("\n%15s", "partition" + part); for (int type = 0; type <= 2; type++ ) { //for each type of array list = generateIntegerArray(arraySize, type); start = System.nanoTime(); sort(list, part); end = System.nanoTime(); if (!isSorted(list)) System.out.printf("\t%12d!!!", (end - start) / 1000); else System.out.printf("\t%15d", (end - start) / 1000); } System.out.println(); } System.out.println ( "NOTE: !!! next to the time indicates that the array was not sorted."); } /** * Test if the parameter array is sorted. * @param list the array to be tested * @return true/false indicating if the array is sorted or not */ public static > boolean isSorted(E[] list) { for (int i = 1; i < list.length; i++) { if (list[i - 1].compareTo(list[i]) > 0) { return false; } } return true; } /** * Generate and return an integer array given a size and type * @param size size of the array to be generated * @param type type of the array to be generated: * 0 - random values from an integer range * 1 - random values from a small range 0 - 9 * 2 - values from the integer range sorted in ascending order * @return the generated array */ public static Integer[] generateIntegerArray(int size, int type) { if ( type == 0 ) //generate random integer array return generateRandomIntegerArray (size); else if ( type == 1 ) //generate random integer array with small range of vals return generateRandomIntegerArrayWithRepeats(size); else if (type == 2 ) //generate a sorted array (ascendig order) return generateSortedIntegerArray (size); else return null; } /** * Generate and return an integer array given a size. The array has * is populated with random values in the range of int type. * @param size size of the array to be generated * @return the generated array */ public static Integer[] generateRandomIntegerArray(int size) { Integer list[] = new Integer[size]; for (int i = 0; i < list.length; i++) list[i] = rand.nextInt(); // full integer range return list; } /** * Generate and return an integer array given a size. The array has * is populated with random values in the range of 0-9. * @param size size of the array to be generated * @return the generated array */ public static Integer[] generateRandomIntegerArrayWithRepeats(int size) { Integer list[] = new Integer[size]; for (int i = 0; i < list.length; i++) list[i] = rand.nextInt(10); //range from zero to number - 1 return list; } /** * Generate and return an integer array given a size. The array has * is populated with values from the integer range sorted in ascending order. * @param size size of the array to be generated * @return the generated array */ public static Integer[] generateSortedIntegerArray(int size) { Integer list[] = generateRandomIntegerArray(size); Arrays.sort(list); return list; } /** * Sort method that implements a quicksort using different versions of * a partition method. * @param list the array to be sorted * @version version of the partition method (valid values 0-4), some * versions have bugs */ public static > void sort(E[] list, int version) { quickSort(list, 0, list.length - 1, version); } /** * Recursive quicksort implementation. * @param list the array to be sorted, * @param first index of the first element * @param last index of the last element */ private static > void quickSort(E[] list, int first, int last, int version) { if (last > first) { int pivotIndex; if (version == 0) pivotIndex = partition0(list, first, last); else if (version == 1) pivotIndex = partition1(list, first, last); else if (version == 2) pivotIndex = partition2(list, first, last); else pivotIndex = partition3(list, first, last); quickSort(list, first, pivotIndex - 1, version); quickSort(list, pivotIndex + 1, last, version); } } /** * Partition method used in quicksort (might be buggy). * @param list the array to be sorted, * @param first index of the first element * @param last index of the last element */ private static > int partition0(E[] list, int first, int last) { int pivotIndex = pickPivot( first, last ); E pivot = list[pivotIndex]; // Choose the first element as the pivot swap(list, last, pivotIndex); pivotIndex = last; last--; while (last >= first) { // Search forward from left while (first <= last && list[first].compareTo(pivot) <= 0) first++; // Search backward from right while (first <= last && list[last].compareTo(pivot) >= 0) last--; // Swap two elements in the list if (last > first) { swap(list, first, last); first++; last--; } } swap(list, pivotIndex, first); return first; } /** * Partition method used in quicksort (might be buggy). * @param list the array to be sorted, * @param first index of the first element * @param last index of the last element */ private static > int partition1(E[] list, int first, int last) { int pivotIndex = pickPivot( first, last ); E pivot = list[pivotIndex]; // Choose the first element as the pivot swap(list, last, pivotIndex); pivotIndex = last; last--; while (last >= first) { // Search forward from left while (first <= last && list[first].compareTo(pivot) < 0) first++; // Search backward from right while (first <= last && list[last].compareTo(pivot) >= 0) last--; // Swap two elements in the list if (last > first) { swap(list, first, last); first++; last--; } } swap(list, pivotIndex, first); return first; } /** * Partition method used in quicksort (might be buggy). * @param list the array to be sorted, * @param first index of the first element * @param last index of the last element */ private static > int partition2(E[] list, int first, int last) { int pivotIndex = pickPivot( first, last ); E pivot = list[pivotIndex]; // Choose the first element as the pivot swap(list, last, pivotIndex); pivotIndex = last; last--; while (last > first) { // Search forward from left while (first <= last && list[first].compareTo(pivot) < 0) first++; // Search backward from right while (first <= last && list[last].compareTo(pivot) > 0) last--; // Swap two elements in the list if (last > first) { swap(list, first, last); first++; last--; } } swap(list, pivotIndex, first); return first; } /** * Partition method used in quicksort (might be buggy). * @param list the array to be sorted, * @param first index of the first element * @param last index of the last element */ private static > int partition3(E[] list, int first, int last) { int pivotIndex = pickPivot( first, last ); E pivot = list[pivotIndex]; // Choose the first element as the pivot swap(list, last, pivotIndex); pivotIndex = last; last--; do { // Search forward from left while (first < last && list[first].compareTo(pivot) <= 0) first++; // Search backward from right while (first <= last && list[last].compareTo(pivot) > 0) last--; // Swap two elements in the list if (last >= first) { swap(list, first, last); first++; last--; } } while (last > first); swap(list, pivotIndex, first); return first; } /** * Swaps two elements in the array. * @param list array from with the elements are swapped * @param index1 index of the first element * @param index2 index of the second element */ private static void swap(E[] list, int index1, int index2) { E tmp = list[index1]; list[index1] = list[index2]; list[index2] = tmp; } /** * Pick a pivot index. * @param first index of the first element in the current partition * @param last index of the last element in the current partition */ private static int pickPivot ( int first, int last) { //return (first + last) / 2; return first; //return last; } }