/** * An implementation of the quicksort algorithm. There are actually 3 different * implementations here. * @author gtowell * Created: April 14, 2020 */ public class QuickSort extends SortBase { private final boolean USE_MEDIAN_OF_3; public QuickSort() { this(false); } public QuickSort(boolean doM3) { USE_MEDIAN_OF_3 = doM3; } @Override public void sortInPlace(int[] list) { quickSort(list, 0, list.length-1); } /** * The recursive quicksort implemention. Works in-place, so the order of the items * in the provided array will be changed. Will only sort the portion of the array * between begin and end * @param arr the array to be sorted * @param begin the first position in the portion of the array to be sorted * @param end the last position in the portion of the array to be sorted */ private void quickSort(int arr[], int begin, int end) { if (begin < end) { int partitionIndex = partition(arr, begin, end); quickSort(arr, begin, partitionIndex-1); quickSort(arr, partitionIndex+1, end); } } /** An instance of insertion sort to be used by quicksort 3i. Just saves * a bunch of passing of a param that never changes. */ private Insertion iSort; /** An improved version of Quicksort. A hybrid of insertion sort and QS in the * same way as for mergesort * @param inputArr the array to be sorted */ public int[] qs3i(int inputArr[]) { iSort = new Insertion(); doQS3i(inputArr, 0, inputArr.length-1); return inputArr; } /** * The recursive quicksort implemention. Works in-place, so the order of the items * in the provided array will be changed. Will only sort the portion of the array * between begin and end * @param arr the array to be sorted * @param begin the first position in the portion of the array to be sorted * @param end the last position in the portion of the array to be sorted */ private void doQS3i(int arr[], int begin, int end) { if ((end-begin) < 15 ) { iSort.insertionSortIP(arr, begin, end); } else { int partitionIndex = partition(arr, begin, end); doQS3i(arr, begin, partitionIndex-1); doQS3i(arr, partitionIndex+1, end); } } /** An further improved version of Quicksort. A hybrid of insertion sort and QS in the * in which insertion sort is applied after QS completes * @param inputArr the array to be sorted */ public int[] qs4i(int inputArr[]) { iSort = new Insertion(); doQS4i(inputArr, 0, inputArr.length-1); new Insertion().insertionSort2(inputArr); return inputArr; } /** * The recursive quicksort implemention. Works in-place, so the order of the items * in the provided array will be changed. Will only sort the portion of the array * between begin and end * @param arr the array to be sorted * @param begin the first position in the portion of the array to be sorted * @param end the last position in the portion of the array to be sorted */ private void doQS4i(int arr[], int begin, int end) { if ((end-begin) < 15 ) { // just let it drop } else { int partitionIndex = partition(arr, begin, end); doQS4i(arr, begin, partitionIndex-1); doQS4i(arr, partitionIndex+1, end); } } /** * A crude implementation of "median of 3". Assume that the distance between * begin and end is at least 3. * @param arr * @param begin * @param end * @return */ public int medianOf3(int[] arr, int begin, int end) { int lo=arr[end-2]; int mid=arr[end-1]; int hi=arr[end]; if (lo < mid) { if (lo>hi) return end-2; else { // lo is smallest if (hi>mid) return end-1; return end; } } else { if (lo3) { int medloc = medianOf3(arr, begin, end); if (medloc!=end) { int swapTemp = arr[medloc]; arr[medloc] = arr[end]; arr[end] = swapTemp; } } int pivot = arr[end]; int insertLoc = (begin-1); for (int j = begin; j < end; j++) { if (arr[j] <= pivot) { insertLoc++; int swapTemp = arr[insertLoc]; arr[insertLoc] = arr[j]; arr[j] = swapTemp; } } // Move the partioning element into place insertLoc++; int swapTemp = arr[insertLoc]; arr[insertLoc] = arr[end]; arr[end] = swapTemp; return insertLoc; } public static void main(String[] args) { int[] aa = {9,10,6}; QuickSort qs = new QuickSort(); System.out.println(qs.medianOf3(aa, 0, 2)); } }