142 lines
3.8 KiB
Java
142 lines
3.8 KiB
Java
package net.abhinavsarkar.algorist.sort;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.concurrent.ThreadLocalRandom;
|
|
import net.abhinavsarkar.algorist.Sorter;
|
|
|
|
public class QuickSorter<T> implements Sorter<T>
|
|
{
|
|
|
|
@Override
|
|
public T[] sort(T[] input, Comparator<T> 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<T> 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<T> 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<T> 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<T> 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<T> 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<T> 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<String> sorter = new QuickSorter<>();
|
|
String[] input = {"abhinav", "sarkar", "barista", "jordan", "data", "cata",
|
|
"meta", "dota", "best", "recursion"};
|
|
Comparator<String> 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)));
|
|
}
|
|
|
|
}
|