Changed FasterFinnSort to use the PowerSort merge policy

This commit is contained in:
finnm 2025-01-05 14:26:07 +01:00
parent c8bed52bf6
commit 4268315f06

View File

@ -28,6 +28,8 @@ package de.uni_marburg.powersort.FinnSort;
import java.util.Comparator; import java.util.Comparator;
import static java.lang.Math.pow;
/** /**
* A stable, adaptive, iterative mergesort that requires far fewer than * A stable, adaptive, iterative mergesort that requires far fewer than
* n lg(n) comparisons when running on partially sorted arrays, while * n lg(n) comparisons when running on partially sorted arrays, while
@ -61,7 +63,7 @@ import java.util.Comparator;
* *
* @author Josh Bloch * @author Josh Bloch
*/ */
class FasterFinnSort<T> { public class FasterFinnSort<T> {
/** /**
* This is the minimum sized sequence that will be merged. Shorter * This is the minimum sized sequence that will be merged. Shorter
* sequences will be lengthened by calling binarySort. If the entire * sequences will be lengthened by calling binarySort. If the entire
@ -135,6 +137,7 @@ class FasterFinnSort<T> {
private int stackSize = 0; // Number of pending runs on stack private int stackSize = 0; // Number of pending runs on stack
private final int[] runBase; private final int[] runBase;
private final int[] runLen; private final int[] runLen;
private final int[] runPower;
/** /**
* Creates a TimSort instance to maintain the state of an ongoing sort. * Creates a TimSort instance to maintain the state of an ongoing sort.
@ -186,6 +189,7 @@ class FasterFinnSort<T> {
len < 119151 ? 24 : 49); len < 119151 ? 24 : 49);
runBase = new int[stackLen]; runBase = new int[stackLen];
runLen = new int[stackLen]; runLen = new int[stackLen];
runPower = new int[stackLen];
} }
/* /*
@ -209,7 +213,7 @@ class FasterFinnSort<T> {
* @param workLen usable size of work array * @param workLen usable size of work array
* @since 1.8 * @since 1.8
*/ */
static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c, public static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
T[] work, int workBase, int workLen) { T[] work, int workBase, int workLen) {
assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length; assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;
@ -243,7 +247,7 @@ class FasterFinnSort<T> {
} }
// Push run onto pending-run stack, and maybe merge // Push run onto pending-run stack, and maybe merge
ts.pushRun(lo, runLen); ts.pushRun(lo, runLen, hi - lo);
ts.mergeCollapse(); ts.mergeCollapse();
// Advance to find next run // Advance to find next run
@ -415,9 +419,10 @@ class FasterFinnSort<T> {
* @param runBase index of the first element in the run * @param runBase index of the first element in the run
* @param runLen the number of elements in the run * @param runLen the number of elements in the run
*/ */
private void pushRun(int runBase, int runLen) { private void pushRun(int runBase, int runLen, int rangeSize) {
this.runBase[stackSize] = runBase; this.runBase[stackSize] = runBase;
this.runLen[stackSize] = runLen; this.runLen[stackSize] = runLen;
this.runPower[stackSize] = power(stackSize, rangeSize);
stackSize++; stackSize++;
} }
@ -440,16 +445,29 @@ class FasterFinnSort<T> {
private void mergeCollapse() { private void mergeCollapse() {
while (stackSize > 1) { while (stackSize > 1) {
int n = stackSize - 2; int n = stackSize - 2;
if (n > 0 && runLen[n-1] <= runLen[n] + runLen[n+1] || if (n > 0 && runPower[n + 1] < runPower[n]) {
n > 1 && runLen[n-2] <= runLen[n] + runLen[n-1]) { mergeAt(n);
if (runLen[n - 1] < runLen[n + 1]) } else {
n--;
} else if (n < 0 || runLen[n] > runLen[n + 1]) {
break; // Invariant is established break; // Invariant is established
} }
mergeAt(n);
} }
} }
private int power(int stackSize, int rangeSize) {
if (stackSize == 0)
return 0;
int n_1 = this.runLen[stackSize - 1];
int n_2 = this.runLen[stackSize];
double a = ((double) this.runBase[stackSize - 1] + 0.5d * n_1 - 1d) / rangeSize;
double b = ((double) this.runBase[stackSize] + 0.5d * n_2 - 1d) / rangeSize;
int l = 0;
while ((int) (a * pow(2, l)) == (int) (b * pow(2 ,l))) {
l++;
}
return l;
}
/* /*
Backup mergeCollapse() von TimSort: Backup mergeCollapse() von TimSort: