mirror of
https://gitlab.uni-marburg.de/langbeid/powersort.git
synced 2025-01-21 19:50:35 +01:00
adjust QuickSort & add test case
This commit is contained in:
parent
fe7fe86dee
commit
cca298709f
@ -2,10 +2,12 @@ package de.uni_marburg.powersort.sort;
|
|||||||
|
|
||||||
import de.uni_marburg.powersort.FinnSort.FinnSort;
|
import de.uni_marburg.powersort.FinnSort.FinnSort;
|
||||||
import de.uni_marburg.powersort.benchmark.NaturalOrder;
|
import de.uni_marburg.powersort.benchmark.NaturalOrder;
|
||||||
|
import de.uni_marburg.powersort.sort.dpqs.DualPivotQuicksort;
|
||||||
|
|
||||||
public enum SortEnum {
|
public enum SortEnum {
|
||||||
BUBBLE_SORT,
|
BUBBLE_SORT,
|
||||||
QUICK_SORT,
|
QUICK_SORT,
|
||||||
|
DPQS,
|
||||||
MERGE_SORT,
|
MERGE_SORT,
|
||||||
TIM_SORT,
|
TIM_SORT,
|
||||||
FINN_SORT,
|
FINN_SORT,
|
||||||
@ -15,6 +17,7 @@ public enum SortEnum {
|
|||||||
return switch (this) {
|
return switch (this) {
|
||||||
case BUBBLE_SORT -> array -> BubbleSort.sort(array, NaturalOrder.INSTANCE);
|
case BUBBLE_SORT -> array -> BubbleSort.sort(array, NaturalOrder.INSTANCE);
|
||||||
case QUICK_SORT -> array -> QuickSort.sort(array, NaturalOrder.INSTANCE);
|
case QUICK_SORT -> array -> QuickSort.sort(array, NaturalOrder.INSTANCE);
|
||||||
|
case DPQS -> array -> DualPivotQuicksort.sort(array, 0, array.length);
|
||||||
case MERGE_SORT -> array -> MergeSort.legacyMergeSort(array, NaturalOrder.INSTANCE);
|
case MERGE_SORT -> array -> MergeSort.legacyMergeSort(array, NaturalOrder.INSTANCE);
|
||||||
case TIM_SORT -> array -> TimSort.sort(array, 0, array.length, NaturalOrder.INSTANCE, null, 0, 0);
|
case TIM_SORT -> array -> TimSort.sort(array, 0, array.length, NaturalOrder.INSTANCE, null, 0, 0);
|
||||||
case FINN_SORT -> array -> FinnSort.sort(array, NaturalOrder.INSTANCE);
|
case FINN_SORT -> array -> FinnSort.sort(array, NaturalOrder.INSTANCE);
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
// Imported from JDK23 DualPivotQuicksort.java
|
// Imported from JDK23 DualPivotQuicksort.java
|
||||||
|
// Removed parallel parts
|
||||||
|
// Changed from int[] to Object[]
|
||||||
|
|
||||||
package de.uni_marburg.powersort.sort.dpqs;
|
package de.uni_marburg.powersort.sort.dpqs;
|
||||||
|
|
||||||
@ -27,6 +29,8 @@ package de.uni_marburg.powersort.sort.dpqs;
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import de.uni_marburg.powersort.benchmark.NaturalOrder;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,35 +99,6 @@ public final class DualPivotQuicksort {
|
|||||||
*/
|
*/
|
||||||
private static final int MAX_RECURSION_DEPTH = 64 * DELTA;
|
private static final int MAX_RECURSION_DEPTH = 64 * DELTA;
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a function that accepts the array and sorts the specified range
|
|
||||||
* of the array into ascending order.
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
private interface SortOperation<A> {
|
|
||||||
/**
|
|
||||||
* Sorts the specified range of the array.
|
|
||||||
*
|
|
||||||
* @param a the array to be sorted
|
|
||||||
* @param low the index of the first element, inclusive, to be sorted
|
|
||||||
* @param high the index of the last element, exclusive, to be sorted
|
|
||||||
*/
|
|
||||||
void sort(A a, int low, int high);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sorts the specified range of the array into ascending numerical order.
|
|
||||||
*
|
|
||||||
* @param array the array to be sorted
|
|
||||||
* the array to sort, otherwise if the array is {@code null},an absolute
|
|
||||||
* address pointing to the first element to sort from.
|
|
||||||
* @param low the index of the first element, inclusive, to be sorted
|
|
||||||
* @param high the index of the last element, exclusive, to be sorted
|
|
||||||
* @param so the method reference for the fallback implementation
|
|
||||||
*/
|
|
||||||
private static <A> void sort(A array, int low, int high, SortOperation<A> so) {
|
|
||||||
so.sort(array, low, high);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a function that accepts the array and partitions the specified range
|
* Represents a function that accepts the array and partitions the specified range
|
||||||
@ -153,24 +128,17 @@ public final class DualPivotQuicksort {
|
|||||||
* @param po the method reference for the fallback implementation
|
* @param po the method reference for the fallback implementation
|
||||||
*/
|
*/
|
||||||
private static <A> int[] partition(A array, int high, int pivotIndex1, int pivotIndex2, PartitionOperation<A> po) {
|
private static <A> int[] partition(A array, int high, int pivotIndex1, int pivotIndex2, PartitionOperation<A> po) {
|
||||||
return po.partition(array, Unsafe.ARRAY_INT_BASE_OFFSET, high, pivotIndex1, pivotIndex2);
|
return po.partition(array, 0, high, pivotIndex1, pivotIndex2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorts the specified range of the array using parallel merge
|
* Sorts the specified range of the array Dual-Pivot Quicksort.
|
||||||
* sort and/or Dual-Pivot Quicksort.
|
|
||||||
* <p>
|
|
||||||
* To balance the faster splitting and parallelism of merge sort
|
|
||||||
* with the faster element partitioning of Quicksort, ranges are
|
|
||||||
* subdivided in tiers such that, if there is enough parallelism,
|
|
||||||
* the four-way parallel merge is started, still ensuring enough
|
|
||||||
* parallelism to process the partitions.
|
|
||||||
*
|
*
|
||||||
* @param a the array to be sorted
|
* @param a the array to be sorted
|
||||||
* @param low the index of the first element, inclusive, to be sorted
|
* @param low the index of the first element, inclusive, to be sorted
|
||||||
* @param high the index of the last element, exclusive, to be sorted
|
* @param high the index of the last element, exclusive, to be sorted
|
||||||
*/
|
*/
|
||||||
public static void sort(int[] a, int low, int high) {
|
public static void sort(Object[] a, int low, int high) {
|
||||||
sort(a, 0, low, high);
|
sort(a, 0, low, high);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,14 +152,14 @@ public final class DualPivotQuicksort {
|
|||||||
* @param low the index of the first element, inclusive, to be sorted
|
* @param low the index of the first element, inclusive, to be sorted
|
||||||
* @param high the index of the last element, exclusive, to be sorted
|
* @param high the index of the last element, exclusive, to be sorted
|
||||||
*/
|
*/
|
||||||
static void sort(int[] a, int bits, int low, int high) {
|
static void sort(Object[] a, int bits, int low, int high) {
|
||||||
while (true) {
|
while (true) {
|
||||||
int end = high - 1, size = high - low;
|
int end = high - 1, size = high - low;
|
||||||
/*
|
/*
|
||||||
* Run mixed insertion sort on small non-leftmost parts.
|
* Run mixed insertion sort on small non-leftmost parts.
|
||||||
*/
|
*/
|
||||||
if (size < MAX_MIXED_INSERTION_SORT_SIZE + bits && (bits & 1) > 0) {
|
if (size < MAX_MIXED_INSERTION_SORT_SIZE + bits && (bits & 1) > 0) {
|
||||||
sort(a, low, high, DualPivotQuicksort::mixedInsertionSort);
|
mixedInsertionSort(a, low, high);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +167,7 @@ public final class DualPivotQuicksort {
|
|||||||
* Invoke insertion sort on small leftmost part.
|
* Invoke insertion sort on small leftmost part.
|
||||||
*/
|
*/
|
||||||
if (size < MAX_INSERTION_SORT_SIZE) {
|
if (size < MAX_INSERTION_SORT_SIZE) {
|
||||||
sort(a, low, high, DualPivotQuicksort::insertionSort);
|
insertionSort(a, low, high);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,7 +206,7 @@ public final class DualPivotQuicksort {
|
|||||||
int e3 = (e1 + e5) >>> 1;
|
int e3 = (e1 + e5) >>> 1;
|
||||||
int e2 = (e1 + e3) >>> 1;
|
int e2 = (e1 + e3) >>> 1;
|
||||||
int e4 = (e3 + e5) >>> 1;
|
int e4 = (e3 + e5) >>> 1;
|
||||||
int a3 = a[e3];
|
Object a3 = a[e3];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sort these elements in place by the combination
|
* Sort these elements in place by the combination
|
||||||
@ -252,34 +220,34 @@ public final class DualPivotQuicksort {
|
|||||||
* | |
|
* | |
|
||||||
* 1 ------------o-----o------------
|
* 1 ------------o-----o------------
|
||||||
*/
|
*/
|
||||||
if (a[e5] < a[e2]) {
|
if (NaturalOrder.INSTANCE.compare(a[e5] , a[e2])<0) {
|
||||||
int t = a[e5];
|
Object t = a[e5];
|
||||||
a[e5] = a[e2];
|
a[e5] = a[e2];
|
||||||
a[e2] = t;
|
a[e2] = t;
|
||||||
}
|
}
|
||||||
if (a[e4] < a[e1]) {
|
if (NaturalOrder.INSTANCE.compare(a[e4] , a[e1])<0) {
|
||||||
int t = a[e4];
|
Object t = a[e4];
|
||||||
a[e4] = a[e1];
|
a[e4] = a[e1];
|
||||||
a[e1] = t;
|
a[e1] = t;
|
||||||
}
|
}
|
||||||
if (a[e5] < a[e4]) {
|
if (NaturalOrder.INSTANCE.compare(a[e5] , a[e4])<0) {
|
||||||
int t = a[e5];
|
Object t = a[e5];
|
||||||
a[e5] = a[e4];
|
a[e5] = a[e4];
|
||||||
a[e4] = t;
|
a[e4] = t;
|
||||||
}
|
}
|
||||||
if (a[e2] < a[e1]) {
|
if (NaturalOrder.INSTANCE.compare(a[e2] , a[e1])<0) {
|
||||||
int t = a[e2];
|
Object t = a[e2];
|
||||||
a[e2] = a[e1];
|
a[e2] = a[e1];
|
||||||
a[e1] = t;
|
a[e1] = t;
|
||||||
}
|
}
|
||||||
if (a[e4] < a[e2]) {
|
if (NaturalOrder.INSTANCE.compare(a[e4] , a[e2])<0) {
|
||||||
int t = a[e4];
|
Object t = a[e4];
|
||||||
a[e4] = a[e2];
|
a[e4] = a[e2];
|
||||||
a[e2] = t;
|
a[e2] = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a3 < a[e2]) {
|
if (NaturalOrder.INSTANCE.compare(a3 , a[e2])<0) {
|
||||||
if (a3 < a[e1]) {
|
if (NaturalOrder.INSTANCE.compare(a3 , a[e1])<0) {
|
||||||
a[e3] = a[e2];
|
a[e3] = a[e2];
|
||||||
a[e2] = a[e1];
|
a[e2] = a[e1];
|
||||||
a[e1] = a3;
|
a[e1] = a3;
|
||||||
@ -287,8 +255,8 @@ public final class DualPivotQuicksort {
|
|||||||
a[e3] = a[e2];
|
a[e3] = a[e2];
|
||||||
a[e2] = a3;
|
a[e2] = a3;
|
||||||
}
|
}
|
||||||
} else if (a3 > a[e4]) {
|
} else if (NaturalOrder.INSTANCE.compare(a3 , a[e4])>0) {
|
||||||
if (a3 > a[e5]) {
|
if (NaturalOrder.INSTANCE.compare(a3 , a[e5])>0) {
|
||||||
a[e3] = a[e4];
|
a[e3] = a[e4];
|
||||||
a[e4] = a[e5];
|
a[e4] = a[e5];
|
||||||
a[e5] = a3;
|
a[e5] = a3;
|
||||||
@ -305,7 +273,7 @@ public final class DualPivotQuicksort {
|
|||||||
/*
|
/*
|
||||||
* Partitioning with 2 pivots in case of different elements.
|
* Partitioning with 2 pivots in case of different elements.
|
||||||
*/
|
*/
|
||||||
if (a[e1] < a[e2] && a[e2] < a[e3] && a[e3] < a[e4] && a[e4] < a[e5]) {
|
if (NaturalOrder.INSTANCE.compare(a[e1] , a[e2])<0 && NaturalOrder.INSTANCE.compare(a[e2] , a[e3])<0 && NaturalOrder.INSTANCE.compare(a[e3] , a[e4])<0 && NaturalOrder.INSTANCE.compare(a[e4] , a[e5])<0) {
|
||||||
/*
|
/*
|
||||||
* Use the first and fifth of the five sorted elements as
|
* Use the first and fifth of the five sorted elements as
|
||||||
* the pivots. These values are inexpensive approximation
|
* the pivots. These values are inexpensive approximation
|
||||||
@ -353,15 +321,15 @@ public final class DualPivotQuicksort {
|
|||||||
* @param pivotIndex1 the index of pivot1, the first pivot
|
* @param pivotIndex1 the index of pivot1, the first pivot
|
||||||
* @param pivotIndex2 the index of pivot2, the second pivot
|
* @param pivotIndex2 the index of pivot2, the second pivot
|
||||||
*/
|
*/
|
||||||
private static int[] partitionDualPivot(int[] a, int low, int high, int pivotIndex1, int pivotIndex2) {
|
private static int[] partitionDualPivot(Object[] a, int low, int high, int pivotIndex1, int pivotIndex2) {
|
||||||
int end = high - 1;
|
int end = high - 1;
|
||||||
int lower = low;
|
int lower = low;
|
||||||
int upper = end;
|
int upper = end;
|
||||||
|
|
||||||
int e1 = pivotIndex1;
|
int e1 = pivotIndex1;
|
||||||
int e5 = pivotIndex2;
|
int e5 = pivotIndex2;
|
||||||
int pivot1 = a[e1];
|
Object pivot1 = a[e1];
|
||||||
int pivot2 = a[e5];
|
Object pivot2 = a[e5];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The first and the last elements to be sorted are moved
|
* The first and the last elements to be sorted are moved
|
||||||
@ -376,8 +344,8 @@ public final class DualPivotQuicksort {
|
|||||||
/*
|
/*
|
||||||
* Skip elements, which are less or greater than the pivots.
|
* Skip elements, which are less or greater than the pivots.
|
||||||
*/
|
*/
|
||||||
while (a[++lower] < pivot1) ;
|
while (NaturalOrder.INSTANCE.compare(a[++lower] , pivot1)<0) ;
|
||||||
while (a[--upper] > pivot2) ;
|
while (NaturalOrder.INSTANCE.compare(a[--upper] , pivot2)>0) ;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Backward 3-interval partitioning
|
* Backward 3-interval partitioning
|
||||||
@ -399,12 +367,12 @@ public final class DualPivotQuicksort {
|
|||||||
* Pointer k is the last index of ?-part
|
* Pointer k is the last index of ?-part
|
||||||
*/
|
*/
|
||||||
for (int unused = --lower, k = ++upper; --k > lower; ) {
|
for (int unused = --lower, k = ++upper; --k > lower; ) {
|
||||||
int ak = a[k];
|
Object ak = a[k];
|
||||||
|
|
||||||
if (ak < pivot1) { // Move a[k] to the left side
|
if (NaturalOrder.INSTANCE.compare(ak , pivot1)<0) { // Move a[k] to the left side
|
||||||
while (lower < k) {
|
while (lower < k) {
|
||||||
if (a[++lower] >= pivot1) {
|
if (NaturalOrder.INSTANCE.compare(a[++lower] , pivot1)>=0) {
|
||||||
if (a[lower] > pivot2) {
|
if (NaturalOrder.INSTANCE.compare(a[lower] , pivot2)>0) {
|
||||||
a[k] = a[--upper];
|
a[k] = a[--upper];
|
||||||
a[upper] = a[lower];
|
a[upper] = a[lower];
|
||||||
} else {
|
} else {
|
||||||
@ -414,7 +382,7 @@ public final class DualPivotQuicksort {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (ak > pivot2) { // Move a[k] to the right side
|
} else if (NaturalOrder.INSTANCE.compare(ak , pivot2)>0) { // Move a[k] to the right side
|
||||||
a[k] = a[--upper];
|
a[k] = a[--upper];
|
||||||
a[upper] = ak;
|
a[upper] = ak;
|
||||||
}
|
}
|
||||||
@ -440,13 +408,13 @@ public final class DualPivotQuicksort {
|
|||||||
* @param pivotIndex1 the index of pivot1, the first pivot
|
* @param pivotIndex1 the index of pivot1, the first pivot
|
||||||
* @param pivotIndex2 the index of pivot2, the second pivot
|
* @param pivotIndex2 the index of pivot2, the second pivot
|
||||||
*/
|
*/
|
||||||
private static int[] partitionSinglePivot(int[] a, int low, int high, int pivotIndex1, int pivotIndex2) {
|
private static int[] partitionSinglePivot(Object[] a, int low, int high, int pivotIndex1, int pivotIndex2) {
|
||||||
|
|
||||||
int end = high - 1;
|
int end = high - 1;
|
||||||
int lower = low;
|
int lower = low;
|
||||||
int upper = end;
|
int upper = end;
|
||||||
int e3 = pivotIndex1;
|
int e3 = pivotIndex1;
|
||||||
int pivot = a[e3];
|
Object pivot = a[e3];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The first element to be sorted is moved to the
|
* The first element to be sorted is moved to the
|
||||||
@ -477,15 +445,15 @@ public final class DualPivotQuicksort {
|
|||||||
* Pointer k is the last index of ?-part
|
* Pointer k is the last index of ?-part
|
||||||
*/
|
*/
|
||||||
for (int k = ++upper; --k > lower; ) {
|
for (int k = ++upper; --k > lower; ) {
|
||||||
int ak = a[k];
|
Object ak = a[k];
|
||||||
|
|
||||||
if (ak != pivot) {
|
if (NaturalOrder.INSTANCE.compare(ak , pivot)!=0) {
|
||||||
a[k] = pivot;
|
a[k] = pivot;
|
||||||
|
|
||||||
if (ak < pivot) { // Move a[k] to the left side
|
if (NaturalOrder.INSTANCE.compare(ak , pivot)<0) { // Move a[k] to the left side
|
||||||
while (a[++lower] < pivot) ;
|
while (NaturalOrder.INSTANCE.compare(a[++lower] , pivot)<0) ;
|
||||||
|
|
||||||
if (a[lower] > pivot) {
|
if (NaturalOrder.INSTANCE.compare(a[lower] , pivot)>0) {
|
||||||
a[--upper] = a[lower];
|
a[--upper] = a[lower];
|
||||||
}
|
}
|
||||||
a[lower] = ak;
|
a[lower] = ak;
|
||||||
@ -519,7 +487,7 @@ public final class DualPivotQuicksort {
|
|||||||
* @param low the index of the first element, inclusive, to be sorted
|
* @param low the index of the first element, inclusive, to be sorted
|
||||||
* @param high the index of the last element, exclusive, to be sorted
|
* @param high the index of the last element, exclusive, to be sorted
|
||||||
*/
|
*/
|
||||||
private static void mixedInsertionSort(int[] a, int low, int high) {
|
private static void mixedInsertionSort(Object[] a, int low, int high) {
|
||||||
int size = high - low;
|
int size = high - low;
|
||||||
int end = high - 3 * ((size >> 5) << 3);
|
int end = high - 3 * ((size >> 5) << 3);
|
||||||
if (end == high) {
|
if (end == high) {
|
||||||
@ -528,9 +496,9 @@ public final class DualPivotQuicksort {
|
|||||||
* Invoke simple insertion sort on tiny array.
|
* Invoke simple insertion sort on tiny array.
|
||||||
*/
|
*/
|
||||||
for (int i; ++low < end; ) {
|
for (int i; ++low < end; ) {
|
||||||
int ai = a[i = low];
|
Object ai = a[i = low];
|
||||||
|
|
||||||
while (ai < a[--i]) {
|
while (NaturalOrder.INSTANCE.compare(ai,a[--i])<0) {
|
||||||
a[i + 1] = a[i];
|
a[i + 1] = a[i];
|
||||||
}
|
}
|
||||||
a[i + 1] = ai;
|
a[i + 1] = ai;
|
||||||
@ -546,29 +514,29 @@ public final class DualPivotQuicksort {
|
|||||||
* proper area for such elements). It avoids expensive
|
* proper area for such elements). It avoids expensive
|
||||||
* movements of these elements through the whole array.
|
* movements of these elements through the whole array.
|
||||||
*/
|
*/
|
||||||
int pin = a[end];
|
Object pin = a[end];
|
||||||
|
|
||||||
for (int i, p = high; ++low < end; ) {
|
for (int i, p = high; ++low < end; ) {
|
||||||
int ai = a[i = low];
|
Object ai = a[i = low];
|
||||||
|
|
||||||
if (ai < a[i - 1]) { // Small element
|
if (NaturalOrder.INSTANCE.compare(ai,a[i - 1])<0) { // Small element
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert small element into sorted part.
|
* Insert small element into sorted part.
|
||||||
*/
|
*/
|
||||||
a[i] = a[--i];
|
a[i] = a[--i];
|
||||||
|
|
||||||
while (ai < a[--i]) {
|
while (NaturalOrder.INSTANCE.compare(ai,a[--i])<0) {
|
||||||
a[i + 1] = a[i];
|
a[i + 1] = a[i];
|
||||||
}
|
}
|
||||||
a[i + 1] = ai;
|
a[i + 1] = ai;
|
||||||
|
|
||||||
} else if (p > i && ai > pin) { // Large element
|
} else if (p > i && NaturalOrder.INSTANCE.compare(ai,pin)>0) { // Large element
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find element smaller than pin.
|
* Find element smaller than pin.
|
||||||
*/
|
*/
|
||||||
while (a[--p] > pin) ;
|
while (NaturalOrder.INSTANCE.compare(a[--p] , pin)>0) ;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Swap it with large element.
|
* Swap it with large element.
|
||||||
@ -581,7 +549,7 @@ public final class DualPivotQuicksort {
|
|||||||
/*
|
/*
|
||||||
* Insert small element into sorted part.
|
* Insert small element into sorted part.
|
||||||
*/
|
*/
|
||||||
while (ai < a[--i]) {
|
while (NaturalOrder.INSTANCE.compare(ai , a[--i])<0) {
|
||||||
a[i + 1] = a[i];
|
a[i + 1] = a[i];
|
||||||
}
|
}
|
||||||
a[i + 1] = ai;
|
a[i + 1] = ai;
|
||||||
@ -592,33 +560,33 @@ public final class DualPivotQuicksort {
|
|||||||
* Continue with pair insertion sort on remain part.
|
* Continue with pair insertion sort on remain part.
|
||||||
*/
|
*/
|
||||||
for (int i; low < high; ++low) {
|
for (int i; low < high; ++low) {
|
||||||
int a1 = a[i = low], a2 = a[++low];
|
Object a1 = a[i = low], a2 = a[++low];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert two elements per iteration: at first, insert the
|
* Insert two elements per iteration: at first, insert the
|
||||||
* larger element and then insert the smaller element, but
|
* larger element and then insert the smaller element, but
|
||||||
* from the position where the larger element was inserted.
|
* from the position where the larger element was inserted.
|
||||||
*/
|
*/
|
||||||
if (a1 > a2) {
|
if (NaturalOrder.INSTANCE.compare(a1 , a2)>0) {
|
||||||
|
|
||||||
while (a1 < a[--i]) {
|
while (NaturalOrder.INSTANCE.compare(a1 , a[--i])<0) {
|
||||||
a[i + 2] = a[i];
|
a[i + 2] = a[i];
|
||||||
}
|
}
|
||||||
a[++i + 1] = a1;
|
a[++i + 1] = a1;
|
||||||
|
|
||||||
while (a2 < a[--i]) {
|
while (NaturalOrder.INSTANCE.compare(a2 , a[--i])<0) {
|
||||||
a[i + 1] = a[i];
|
a[i + 1] = a[i];
|
||||||
}
|
}
|
||||||
a[i + 1] = a2;
|
a[i + 1] = a2;
|
||||||
|
|
||||||
} else if (a1 < a[i - 1]) {
|
} else if (NaturalOrder.INSTANCE.compare(a1 , a[i - 1])<0) {
|
||||||
|
|
||||||
while (a2 < a[--i]) {
|
while (NaturalOrder.INSTANCE.compare(a2 , a[--i])<0) {
|
||||||
a[i + 2] = a[i];
|
a[i + 2] = a[i];
|
||||||
}
|
}
|
||||||
a[++i + 1] = a2;
|
a[++i + 1] = a2;
|
||||||
|
|
||||||
while (a1 < a[--i]) {
|
while (NaturalOrder.INSTANCE.compare(a1 , a[--i])<0) {
|
||||||
a[i + 1] = a[i];
|
a[i + 1] = a[i];
|
||||||
}
|
}
|
||||||
a[i + 1] = a1;
|
a[i + 1] = a1;
|
||||||
@ -634,12 +602,12 @@ public final class DualPivotQuicksort {
|
|||||||
* @param low the index of the first element, inclusive, to be sorted
|
* @param low the index of the first element, inclusive, to be sorted
|
||||||
* @param high the index of the last element, exclusive, to be sorted
|
* @param high the index of the last element, exclusive, to be sorted
|
||||||
*/
|
*/
|
||||||
private static void insertionSort(int[] a, int low, int high) {
|
private static void insertionSort(Object[] a, int low, int high) {
|
||||||
for (int i, k = low; ++k < high; ) {
|
for (int i, k = low; ++k < high; ) {
|
||||||
int ai = a[i = k];
|
Object ai = a[i = k];
|
||||||
|
|
||||||
if (ai < a[i - 1]) {
|
if (NaturalOrder.INSTANCE.compare(ai , a[i - 1])<0) {
|
||||||
while (--i >= low && ai < a[i]) {
|
while (--i >= low && NaturalOrder.INSTANCE.compare(ai , a[i])<0) {
|
||||||
a[i + 1] = a[i];
|
a[i + 1] = a[i];
|
||||||
}
|
}
|
||||||
a[i + 1] = ai;
|
a[i + 1] = ai;
|
||||||
@ -654,12 +622,12 @@ public final class DualPivotQuicksort {
|
|||||||
* @param low the index of the first element, inclusive, to be sorted
|
* @param low the index of the first element, inclusive, to be sorted
|
||||||
* @param high the index of the last element, exclusive, to be sorted
|
* @param high the index of the last element, exclusive, to be sorted
|
||||||
*/
|
*/
|
||||||
private static void heapSort(int[] a, int low, int high) {
|
private static void heapSort(Object[] a, int low, int high) {
|
||||||
for (int k = (low + high) >>> 1; k > low; ) {
|
for (int k = (low + high) >>> 1; k > low; ) {
|
||||||
pushDown(a, --k, a[k], low, high);
|
pushDown(a, --k, a[k], low, high);
|
||||||
}
|
}
|
||||||
while (--high > low) {
|
while (--high > low) {
|
||||||
int max = a[low];
|
Object max = a[low];
|
||||||
pushDown(a, low, a[high], low, high);
|
pushDown(a, low, a[high], low, high);
|
||||||
a[high] = max;
|
a[high] = max;
|
||||||
}
|
}
|
||||||
@ -674,17 +642,17 @@ public final class DualPivotQuicksort {
|
|||||||
* @param low the index of the first element, inclusive, to be sorted
|
* @param low the index of the first element, inclusive, to be sorted
|
||||||
* @param high the index of the last element, exclusive, to be sorted
|
* @param high the index of the last element, exclusive, to be sorted
|
||||||
*/
|
*/
|
||||||
private static void pushDown(int[] a, int p, int value, int low, int high) {
|
private static void pushDown(Object[] a, int p, Object value, int low, int high) {
|
||||||
for (int k; ; a[p] = a[p = k]) {
|
for (int k; ; a[p] = a[p = k]) {
|
||||||
k = (p << 1) - low + 2; // Index of the right child
|
k = (p << 1) - low + 2; // Index of the right child
|
||||||
|
|
||||||
if (k > high) {
|
if (k > high) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (k == high || a[k] < a[k - 1]) {
|
if (k == high || NaturalOrder.INSTANCE.compare(a[k] , a[k - 1])<0) {
|
||||||
--k;
|
--k;
|
||||||
}
|
}
|
||||||
if (a[k] <= value) {
|
if (NaturalOrder.INSTANCE.compare(a[k] , value)<=0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -699,7 +667,7 @@ public final class DualPivotQuicksort {
|
|||||||
* @param size the array size
|
* @param size the array size
|
||||||
* @return true if finally sorted, false otherwise
|
* @return true if finally sorted, false otherwise
|
||||||
*/
|
*/
|
||||||
private static boolean tryMergeRuns(int[] a, int low, int size) {
|
private static boolean tryMergeRuns(Object[] a, int low, int size) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The run array is constructed only if initial runs are
|
* The run array is constructed only if initial runs are
|
||||||
@ -718,24 +686,24 @@ public final class DualPivotQuicksort {
|
|||||||
/*
|
/*
|
||||||
* Find the end index of the current run.
|
* Find the end index of the current run.
|
||||||
*/
|
*/
|
||||||
if (a[k - 1] < a[k]) {
|
if (NaturalOrder.INSTANCE.compare(a[k - 1] , a[k])<0) {
|
||||||
|
|
||||||
// Identify ascending sequence
|
// Identify ascending sequence
|
||||||
while (++k < high && a[k - 1] <= a[k]) ;
|
while (++k < high && NaturalOrder.INSTANCE.compare(a[k - 1] , a[k])<=0) ;
|
||||||
|
|
||||||
} else if (a[k - 1] > a[k]) {
|
} else if (NaturalOrder.INSTANCE.compare(a[k - 1] , a[k])>0) {
|
||||||
|
|
||||||
// Identify descending sequence
|
// Identify descending sequence
|
||||||
while (++k < high && a[k - 1] >= a[k]) ;
|
while (++k < high && NaturalOrder.INSTANCE.compare(a[k - 1] , a[k])>=0) ;
|
||||||
|
|
||||||
// Reverse into ascending order
|
// Reverse into ascending order
|
||||||
for (int i = last - 1, j = k; ++i < --j && a[i] > a[j]; ) {
|
for (int i = last - 1, j = k; ++i < --j && NaturalOrder.INSTANCE.compare(a[i] , a[j])>0; ) {
|
||||||
int ai = a[i];
|
Object ai = a[i];
|
||||||
a[i] = a[j];
|
a[i] = a[j];
|
||||||
a[j] = ai;
|
a[j] = ai;
|
||||||
}
|
}
|
||||||
} else { // Identify constant sequence
|
} else { // Identify constant sequence
|
||||||
for (int ak = a[k]; ++k < high && ak == a[k]; ) ;
|
for (Object ak = a[k]; ++k < high && NaturalOrder.INSTANCE.compare(ak , a[k])==0; ) ;
|
||||||
|
|
||||||
if (k < high) {
|
if (k < high) {
|
||||||
continue;
|
continue;
|
||||||
@ -767,7 +735,7 @@ public final class DualPivotQuicksort {
|
|||||||
run = new int[((size >> 10) | 0x7F) & 0x3FF];
|
run = new int[((size >> 10) | 0x7F) & 0x3FF];
|
||||||
run[0] = low;
|
run[0] = low;
|
||||||
|
|
||||||
} else if (a[last - 1] > a[last]) {
|
} else if (NaturalOrder.INSTANCE.compare(a[last - 1] , a[last])>0) {
|
||||||
|
|
||||||
if (count > (k - low) >> MIN_FIRST_RUNS_FACTOR) {
|
if (count > (k - low) >> MIN_FIRST_RUNS_FACTOR) {
|
||||||
|
|
||||||
@ -801,10 +769,10 @@ public final class DualPivotQuicksort {
|
|||||||
* Merge runs of highly structured array.
|
* Merge runs of highly structured array.
|
||||||
*/
|
*/
|
||||||
if (count > 1) {
|
if (count > 1) {
|
||||||
int[] b;
|
Object[] b;
|
||||||
int offset = low;
|
int offset = low;
|
||||||
|
|
||||||
b = new int[size];
|
b = new Object[size];
|
||||||
mergeRuns(a, b, offset, 1, run, 0, count);
|
mergeRuns(a, b, offset, 1, run, 0, count);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -822,7 +790,7 @@ public final class DualPivotQuicksort {
|
|||||||
* @param hi the start index of the last run, inclusive
|
* @param hi the start index of the last run, inclusive
|
||||||
* @return the destination where runs are merged
|
* @return the destination where runs are merged
|
||||||
*/
|
*/
|
||||||
private static int[] mergeRuns(int[] a, int[] b, int offset,
|
private static Object[] mergeRuns(Object[] a, Object[] b, int offset,
|
||||||
int aim, int[] run, int lo, int hi) {
|
int aim, int[] run, int lo, int hi) {
|
||||||
|
|
||||||
if (hi - lo == 1) {
|
if (hi - lo == 1) {
|
||||||
@ -845,18 +813,18 @@ public final class DualPivotQuicksort {
|
|||||||
/*
|
/*
|
||||||
* Merge the left and right parts.
|
* Merge the left and right parts.
|
||||||
*/
|
*/
|
||||||
int[] a1, a2;
|
Object[] a1, a2;
|
||||||
|
|
||||||
a1 = mergeRuns(a, b, offset, -aim, run, lo, mi);
|
a1 = mergeRuns(a, b, offset, -aim, run, lo, mi);
|
||||||
a2 = mergeRuns(a, b, offset, 0, run, mi, hi);
|
a2 = mergeRuns(a, b, offset, 0, run, mi, hi);
|
||||||
|
|
||||||
int[] dst = a1 == a ? b : a;
|
Object[] dst = NaturalOrder.INSTANCE.compare(a1, a) == 0 ? b : a;
|
||||||
|
|
||||||
int k = a1 == a ? run[lo] - offset : run[lo];
|
int k = NaturalOrder.INSTANCE.compare(a1 , a)==0 ? run[lo] - offset : run[lo];
|
||||||
int lo1 = a1 == b ? run[lo] - offset : run[lo];
|
int lo1 = NaturalOrder.INSTANCE.compare(a1 , b)==0 ? run[lo] - offset : run[lo];
|
||||||
int hi1 = a1 == b ? run[mi] - offset : run[mi];
|
int hi1 = NaturalOrder.INSTANCE.compare(a1 , b)==0 ? run[mi] - offset : run[mi];
|
||||||
int lo2 = a2 == b ? run[mi] - offset : run[mi];
|
int lo2 = NaturalOrder.INSTANCE.compare(a2 , b)==0 ? run[mi] - offset : run[mi];
|
||||||
int hi2 = a2 == b ? run[hi] - offset : run[hi];
|
int hi2 = NaturalOrder.INSTANCE.compare(a2 , b)==0 ? run[hi] - offset : run[hi];
|
||||||
|
|
||||||
mergeParts(dst, k, a1, lo1, hi1, a2, lo2, hi2);
|
mergeParts(dst, k, a1, lo1, hi1, a2, lo2, hi2);
|
||||||
return dst;
|
return dst;
|
||||||
@ -874,15 +842,15 @@ public final class DualPivotQuicksort {
|
|||||||
* @param lo2 the start index of the second part, inclusive
|
* @param lo2 the start index of the second part, inclusive
|
||||||
* @param hi2 the end index of the second part, exclusive
|
* @param hi2 the end index of the second part, exclusive
|
||||||
*/
|
*/
|
||||||
private static void mergeParts(int[] dst, int k,
|
private static void mergeParts(Object[] dst, int k,
|
||||||
int[] a1, int lo1, int hi1, int[] a2, int lo2, int hi2) {
|
Object[] a1, int lo1, int hi1, Object[] a2, int lo2, int hi2) {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Merge small parts sequentially.
|
* Merge small parts sequentially.
|
||||||
*/
|
*/
|
||||||
while (lo1 < hi1 && lo2 < hi2) {
|
while (lo1 < hi1 && lo2 < hi2) {
|
||||||
dst[k++] = a1[lo1] < a2[lo2] ? a1[lo1++] : a2[lo2++];
|
dst[k++] = NaturalOrder.INSTANCE.compare(a1[lo1] , a2[lo2])<0 ? a1[lo1++] : a2[lo2++];
|
||||||
}
|
}
|
||||||
if (dst != a1 || k < lo1) {
|
if (dst != a1 || k < lo1) {
|
||||||
while (lo1 < hi1) {
|
while (lo1 < hi1) {
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
package de.uni_marburg.powersort.sort.dpqs;
|
|
||||||
|
|
||||||
public final class Unsafe {
|
|
||||||
private Unsafe() {
|
|
||||||
}
|
|
||||||
public static final int ARRAY_INT_BASE_OFFSET
|
|
||||||
= 16; // Taken from debugging JDK 23 Unsafe.ARRAY_INT_BASE_OFFSET
|
|
||||||
}
|
|
@ -30,6 +30,8 @@ public abstract class AbstractSortTest {
|
|||||||
@CsvSource({
|
@CsvSource({
|
||||||
"3,7,-13",
|
"3,7,-13",
|
||||||
"3,7,-3",
|
"3,7,-3",
|
||||||
|
"10,10,-5",
|
||||||
|
"17,17,-17",
|
||||||
})
|
})
|
||||||
void test2(int numOfRuns, int runLength, int decreaseBetweenRuns) {
|
void test2(int numOfRuns, int runLength, int decreaseBetweenRuns) {
|
||||||
Integer[] array = AscendingRuns.newAscendingRuns(numOfRuns, runLength, decreaseBetweenRuns).getCopy();
|
Integer[] array = AscendingRuns.newAscendingRuns(numOfRuns, runLength, decreaseBetweenRuns).getCopy();
|
||||||
@ -42,7 +44,7 @@ public abstract class AbstractSortTest {
|
|||||||
"13",
|
"13",
|
||||||
"1337",
|
"1337",
|
||||||
})
|
})
|
||||||
void test2(int size) {
|
void test3(int size) {
|
||||||
Integer[] array = new DescendingIntegers(size).getCopy();
|
Integer[] array = new DescendingIntegers(size).getCopy();
|
||||||
sortAndCheckResult(array);
|
sortAndCheckResult(array);
|
||||||
}
|
}
|
||||||
@ -52,6 +54,6 @@ public abstract class AbstractSortTest {
|
|||||||
Arrays.sort(expected);
|
Arrays.sort(expected);
|
||||||
|
|
||||||
sortAlg.getSortImpl().sort(array);
|
sortAlg.getSortImpl().sort(array);
|
||||||
assertArrayEquals(expected, array);
|
assertArrayEquals(expected, array, Arrays.toString(array) + "\n\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package de.uni_marburg.powersort.sort;
|
||||||
|
|
||||||
|
public class DualPivotQuicksort extends AbstractSortTest {
|
||||||
|
DualPivotQuicksort() {
|
||||||
|
sortAlg = SortEnum.DPQS;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user