mirror of
https://github.com/corda/corda.git
synced 2025-06-13 04:38:19 +00:00
Replace Arrays.sort() with an efficient sort algorithm
This change reuses the existing insertion sort (which was previously what Arrays.sort() executed) in a full intro sort pipeline. The implementation is based on the Musser paper on intro sort (Musser, David R. "Introspective sorting and selection algorithms." Softw., Pract. Exper. 27.8 (1997): 983-993.) and Wikipedia's current description of the heap sort: http://en.wikipedia.org/wiki/Heapsort. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
@ -148,8 +148,100 @@ public class Arrays {
|
||||
});
|
||||
}
|
||||
|
||||
private final static int SORT_SIZE_THRESHOLD = 16;
|
||||
|
||||
public static <T> void sort(T[] array, Comparator<? super T> comparator) {
|
||||
// insertion sort
|
||||
introSort(array, comparator, 0, array.length, array.length);
|
||||
insertionSort(array, comparator);
|
||||
}
|
||||
|
||||
private static <T > void introSort(T[] array,
|
||||
Comparator<? super T> comparator, int begin, int end, int limit)
|
||||
{
|
||||
while (end - begin > SORT_SIZE_THRESHOLD) {
|
||||
if (limit == 0) {
|
||||
heapSort(array, comparator, begin, end);
|
||||
return;
|
||||
}
|
||||
limit >>= 1;
|
||||
|
||||
// median of three
|
||||
T a = array[begin];
|
||||
T b = array[begin + (end - begin) / 2 + 1];
|
||||
T c = array[end - 1];
|
||||
T median;
|
||||
if (comparator.compare(a, b) < 0) {
|
||||
median = comparator.compare(b, c) < 0 ?
|
||||
b : (comparator.compare(a, c) < 0 ? c : a);
|
||||
} else {
|
||||
median = comparator.compare(b, c) > 0 ?
|
||||
b : (comparator.compare(a, c) > 0 ? c : a);
|
||||
}
|
||||
|
||||
// partition
|
||||
int pivot, i = begin, j = end;
|
||||
for (;;) {
|
||||
while (comparator.compare(array[i], median) < 0) {
|
||||
++i;
|
||||
}
|
||||
--j;
|
||||
while (comparator.compare(median, array[j]) < 0) {
|
||||
--j;
|
||||
}
|
||||
if (i >= j) {
|
||||
pivot = i;
|
||||
break;
|
||||
}
|
||||
T swap = array[i];
|
||||
array[i] = array[j];
|
||||
array[j] = swap;
|
||||
++i;
|
||||
}
|
||||
|
||||
introSort(array, comparator, pivot, end, limit);
|
||||
end = pivot;
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> void heapSort(T[] array, Comparator<? super T> comparator,
|
||||
int begin, int end)
|
||||
{
|
||||
int count = end - begin;
|
||||
for (int i = count / 2 - 1; i >= 0; --i) {
|
||||
siftDown(array, comparator, i, count, begin);
|
||||
}
|
||||
for (int i = count - 1; i > 0; --i) {
|
||||
// swap begin and begin + i
|
||||
T swap = array[begin + i];
|
||||
array[begin + i] = array[begin];
|
||||
array[begin] = swap;
|
||||
|
||||
siftDown(array, comparator, 0, i, begin);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> void siftDown(T[] array, Comparator<? super T> comparator,
|
||||
int i, int count, int offset)
|
||||
{
|
||||
T value = array[offset + i];
|
||||
while (i < count / 2) {
|
||||
int child = 2 * i + 1;
|
||||
if (child + 1 < count &&
|
||||
comparator.compare(array[child], array[child + 1]) < 0) {
|
||||
++child;
|
||||
}
|
||||
if (comparator.compare(value, array[child]) >= 0) {
|
||||
break;
|
||||
}
|
||||
array[offset + i] = array[offset + child];
|
||||
i = child;
|
||||
}
|
||||
array[offset + i] = value;
|
||||
}
|
||||
|
||||
private static <T> void insertionSort(T[] array,
|
||||
Comparator<? super T> comparator)
|
||||
{
|
||||
for (int j = 1; j < array.length; ++j) {
|
||||
T t = array[j];
|
||||
int i = j - 1;
|
||||
|
Reference in New Issue
Block a user