/** * An implementation of the quicksort algorithm. There are actually 3 different * implementations here. * @author gtowell * Created: April 14, 2020 */ public class QuickSort extends SortBase { @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); } } /** * The heart of quicksort, the partition method. Will only partition the * portion of the array between begin and end * @param arr the array to be partitioned * @param begin the first index in the partitioned segment * @param end the last index. * @return */ public int partition(int arr[], int begin, int end) { 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; } }