package com.thealgorithms.sorts;
/**
* Dual Pivot Quick Sort Algorithm
*
* @author Debasish Biswas (https://github.com/debasishbsws) *
* @see SortAlgorithm
*/
public class DualPivotQuickSort implements SortAlgorithm {
/**
* Sorts an array using the Dual Pivot QuickSort algorithm.
*
* @param array The array to be sorted
* @param <T> The type of elements in the array, which must be comparable
* @return The sorted array
*/
@Override
public <T extends Comparable<T>> T[] sort(final T[] array) {
if (array.length <= 1) {
return array;
}
dualPivotQuicksort(array, 0, array.length - 1);
return array;
}
/**
* Recursively applies the Dual Pivot QuickSort algorithm to subarrays.
*
* @param array The array to be sorted
* @param left The starting index of the subarray
* @param right The ending index of the subarray
* @param <T> The type of elements in the array, which must be comparable
*/
private static <T extends Comparable<T>> void dualPivotQuicksort(final T[] array, final int left, final int right) {
if (left < right) {
final int[] pivots = partition(array, left, right);
dualPivotQuicksort(array, left, pivots[0] - 1);
dualPivotQuicksort(array, pivots[0] + 1, pivots[1] - 1);
dualPivotQuicksort(array, pivots[1] + 1, right);
}
}
/**
* Partitions the array into three parts using two pivots.
*
* @param array The array to be partitioned
* @param left The starting index for partitioning
* @param right The ending index for partitioning
* @param <T> The type of elements in the array, which must be comparable
* @return An array containing the indices of the two pivots
*/
private static <T extends Comparable<T>> int[] partition(final T[] array, int left, final int right) {
if (SortUtils.greater(array[left], array[right])) {
SortUtils.swap(array, left, right);
}
final T pivot1 = array[left];
final T pivot2 = array[right];
int pivot1End = left + 1;
int low = left + 1;
int high = right - 1;
while (low <= high) {
if (SortUtils.less(array[low], pivot1)) {
SortUtils.swap(array, low, pivot1End);
pivot1End++;
} else if (SortUtils.greaterOrEqual(array[low], pivot2)) {
while (low < high && SortUtils.greater(array[high], pivot2)) {
high--;
}
SortUtils.swap(array, low, high);
high--;
if (SortUtils.less(array[low], pivot1)) {
SortUtils.swap(array, low, pivot1End);
pivot1End++;
}
}
low++;
}
// Place the pivots in their correct positions
pivot1End--;
high++;
SortUtils.swap(array, left, pivot1End);
SortUtils.swap(array, right, high);
// Return the indices of the pivots
return new int[] {low, high};
}
}