package net.abhinavsarkar.algorist.sort; import java.util.Arrays; import java.util.concurrent.ThreadLocalRandom; import net.abhinavsarkar.algorist.Sorter; public class QuickSorter implements Sorter { @Override public T[] sort(T[] input, Comparator comparator) { if (input.length <= 1) { return input; } shuffle(input); return sort(input, 0, input.length, comparator); } private T[] sort(T[] input, int start, int end, Comparator comparator) { if (end - start <= 1) { return input; } int pivot = partition(input, start, end, comparator); sort(input, start, pivot, comparator); sort(input, pivot, end, comparator); return input; } @Override public T[] top(T[] input, int rank, Comparator comparator) { checkRank(input, rank); shuffle(input); return top(input, rank - 1, 0, input.length, comparator); } private T[] top(T[] input, int rank, int start, int end, Comparator comparator) { if (end - start <= 1) { return input; } int pivot = partition(input, start, end, comparator); sort(input, start, pivot, comparator); if (pivot <= rank) { top(input, rank, pivot, end, comparator); } return input; } @Override public T select(T[] input, int rank, Comparator comparator) { checkRank(input, rank); shuffle(input); return select(input, rank - 1, 0, input.length, comparator); } public void checkRank(T[] input, int rank) { if (rank < 1) { throw new IllegalArgumentException("rank is less than one"); } if (rank > input.length) { throw new IllegalArgumentException("rank is larger than input length"); } } private T select(T[] input, int rank, int start, int end, Comparator comparator) { if (end - start == 1) { if (rank == start) { return input[start]; } throw new IllegalStateException("Impossible"); } int pivot = partition(input, start, end, comparator); if (pivot == rank) { return input[pivot]; } else if (pivot > rank) { return select(input, rank, start, pivot, comparator); } else { return select(input, rank, pivot, end, comparator); } } private void shuffle(T[] input) { for (int i = input.length - 1; i > 0; i--) { int j = ThreadLocalRandom.current().nextInt(i + 1); swap(input, i, j); } } private int partition(T[] input, int start, int end, Comparator comparator) { int pivot = end - 1; int firstHigh = start; for (int i = start; i < pivot; i++) { if (comparator.compare(input[i], input[pivot]) < 0) { swap(input, i, firstHigh); firstHigh++; } } swap(input, pivot, firstHigh); return firstHigh; } private void swap(T[] input, int i, int j) { if (i == j) { return; } T temp = input[i]; input[i] = input[j]; input[j] = temp; } public static void main(String[] args) { Sorter sorter = new QuickSorter<>(); String[] input = {"abhinav", "sarkar", "barista", "jordan", "data", "cata", "meta", "dota", "best", "recursion"}; Comparator comparator = (s1, s2) -> s2.compareTo(s1); System.out.println(Arrays.toString(sorter.sort(input, comparator))); System.out.println(sorter.select(input, 1, comparator)); System.out.println(Arrays.toString(sorter.top(input, 3, comparator))); } }