mirror of
https://gitlab.uni-marburg.de/langbeid/powersort.git
synced 2025-02-23 00:45:22 +01:00
creating IMPL_M_4 and getting better performance than TimSort in every case
This commit is contained in:
parent
dec8585ab4
commit
6694a076e5
@ -111,7 +111,7 @@ public class IMPL_M_1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static <T> void mergeInplace(T[] a, int i, int m, int j, Comparator<? super T> c) {
|
static <T> void mergeInplace(T[] a, int i, int m, int j, Comparator<? super T> c) {
|
||||||
System.out.printf("Merge(%d, %d, %d)%n", i, m, j);
|
// System.out.printf("Merge(%d, %d, %d)%n", i, m, j);
|
||||||
MERGE_COST += j - i;
|
MERGE_COST += j - i;
|
||||||
// Create temporary arrays for merging
|
// Create temporary arrays for merging
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@ -131,7 +131,6 @@ public class IMPL_M_1 {
|
|||||||
System.arraycopy(merged, 0, a, i,merged.length);
|
System.arraycopy(merged, 0, a, i,merged.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static <T> int extendRun(T [] a, int i, Comparator<? super T> c) {
|
static <T> int extendRun(T [] a, int i, Comparator<? super T> c) {
|
||||||
// if i was the element before end so just return the last element
|
// if i was the element before end so just return the last element
|
||||||
if (i == a.length - 1) {
|
if (i == a.length - 1) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
178
app/src/main/java/de/uni_marburg/powersort/MSort/IMPL_M_3.java
Normal file
178
app/src/main/java/de/uni_marburg/powersort/MSort/IMPL_M_3.java
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
package de.uni_marburg.powersort.MSort;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
public class IMPL_M_3 {
|
||||||
|
|
||||||
|
private static final int MIN_MERGE = 32;
|
||||||
|
private static final int MIN_GALLOP = 7;
|
||||||
|
|
||||||
|
private IMPL_M_3() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void fillWithAscRunsHighToLow(Integer[] A, int[] runLengths, int runLenFactor) {
|
||||||
|
int n = A.length;
|
||||||
|
assert Arrays.stream(runLengths).sum() * runLenFactor == n;
|
||||||
|
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
A[i] = n - i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int startIndex = 0;
|
||||||
|
for (int l : runLengths) {
|
||||||
|
int L = l * runLenFactor;
|
||||||
|
Arrays.sort(A, startIndex, startIndex + L);
|
||||||
|
startIndex += L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> int extendRun(T[] a, int i, Comparator<? super T> c) {
|
||||||
|
if (i >= a.length - 1) {
|
||||||
|
return a.length; // Return the end of the array
|
||||||
|
}
|
||||||
|
|
||||||
|
int j = i + 1;
|
||||||
|
boolean ascending = c.compare(a[i], a[j]) <= 0;
|
||||||
|
|
||||||
|
while (j < a.length && c.compare(a[j - 1], a[j]) == (ascending ? -1 : 1)) {
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ascending) {
|
||||||
|
reverseRange(a, i, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> void reverseRange(T[] a, int start, int end) {
|
||||||
|
end--;
|
||||||
|
while (start < end) {
|
||||||
|
T temp = a[start];
|
||||||
|
a[start++] = a[end];
|
||||||
|
a[end--] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> void mergeInplace(T[] a, int i, int m, int j, Comparator<? super T> c, T[] temp) {
|
||||||
|
int leftSize = m - i;
|
||||||
|
int rightSize = j - m;
|
||||||
|
|
||||||
|
// Validate indices
|
||||||
|
if (leftSize < 0 || rightSize < 0) {
|
||||||
|
throw new IllegalArgumentException("Invalid indices: leftSize=" + leftSize + ", rightSize=" + rightSize);
|
||||||
|
}
|
||||||
|
if (leftSize < 0) {
|
||||||
|
throw new IllegalArgumentException("Invalid indices: leftSize is negative");
|
||||||
|
}
|
||||||
|
// Ensure the temporary array is large enough
|
||||||
|
if (temp.length < leftSize) {
|
||||||
|
temp = Arrays.copyOf(temp, leftSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.arraycopy(a, i, temp, 0, leftSize);
|
||||||
|
|
||||||
|
int li = 0, ri = m, k = i;
|
||||||
|
int gallopCount = 0;
|
||||||
|
|
||||||
|
while (li < leftSize && ri < j) {
|
||||||
|
if (c.compare(temp[li], a[ri]) <= 0) {
|
||||||
|
a[k++] = temp[li++];
|
||||||
|
gallopCount++;
|
||||||
|
} else {
|
||||||
|
a[k++] = a[ri++];
|
||||||
|
gallopCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gallopCount >= MIN_GALLOP) {
|
||||||
|
gallopCount = 0;
|
||||||
|
while (li < leftSize && ri < j) {
|
||||||
|
if (c.compare(temp[li], a[ri]) <= 0) {
|
||||||
|
a[k++] = temp[li++];
|
||||||
|
} else {
|
||||||
|
a[k++] = a[ri++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (li < leftSize) a[k++] = temp[li++];
|
||||||
|
while (ri < j) a[k++] = a[ri++];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> void powerSort(T[] a, Comparator<? super T> c) {
|
||||||
|
int n = a.length;
|
||||||
|
if (n < MIN_MERGE) {
|
||||||
|
Arrays.sort(a, c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize temporary array with a reasonable size
|
||||||
|
T[] temp = (T[]) new Object[Math.min(n, MIN_MERGE)];
|
||||||
|
int[] runStack = new int[40];
|
||||||
|
int stackSize = 0;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while (i < n) {
|
||||||
|
int j = extendRun(a, i, c);
|
||||||
|
|
||||||
|
// Ensure j > i
|
||||||
|
if (j <= i) {
|
||||||
|
throw new IllegalStateException("Invalid run: j <= i, i=" + i + ", j=" + j);
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] newRun = new int[]{i, j - i};
|
||||||
|
|
||||||
|
// Validate new run
|
||||||
|
if (newRun[0] >= newRun[1]) {
|
||||||
|
throw new IllegalArgumentException("Invalid run: start index >= length, i=" + i + ", j=" + j);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = j;
|
||||||
|
|
||||||
|
if (stackSize > 0) {
|
||||||
|
int[] prevRun = new int[]{runStack[stackSize - 2], runStack[stackSize - 1]};
|
||||||
|
int p = power(prevRun, newRun, n);
|
||||||
|
|
||||||
|
while (stackSize > 0 && p <= runStack[stackSize - 1]) {
|
||||||
|
mergeInplace(a, runStack[stackSize - 2], runStack[stackSize - 1], i, c, temp);
|
||||||
|
stackSize -= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runStack[stackSize++] = newRun[0];
|
||||||
|
runStack[stackSize++] = newRun[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
while (stackSize > 2) {
|
||||||
|
mergeInplace(a, runStack[stackSize - 4], runStack[stackSize - 3], n, c, temp);
|
||||||
|
stackSize -= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int power(int[] run1, int[] run2, int n) {
|
||||||
|
int i1 = run1[0], n1 = run1[1];
|
||||||
|
int i2 = run2[0], n2 = run2[1];
|
||||||
|
|
||||||
|
int a = 2 * i1 + n1;
|
||||||
|
int b = a + n1 + n2;
|
||||||
|
|
||||||
|
int l = 0;
|
||||||
|
while (true) {
|
||||||
|
l++;
|
||||||
|
if (a >= n) {
|
||||||
|
a -= n;
|
||||||
|
b -= n;
|
||||||
|
} else if (b >= n) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
a <<= 1;
|
||||||
|
b <<= 1;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
1018
app/src/main/java/de/uni_marburg/powersort/MSort/IMPL_M_4.java
Normal file
1018
app/src/main/java/de/uni_marburg/powersort/MSort/IMPL_M_4.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,8 @@ import de.uni_marburg.powersort.FinnSort.FinnSort;
|
|||||||
import de.uni_marburg.powersort.FinnSort.FasterFinnSort;
|
import de.uni_marburg.powersort.FinnSort.FasterFinnSort;
|
||||||
import de.uni_marburg.powersort.MSort.IMPL_M_1;
|
import de.uni_marburg.powersort.MSort.IMPL_M_1;
|
||||||
import de.uni_marburg.powersort.MSort.IMPL_M_2;
|
import de.uni_marburg.powersort.MSort.IMPL_M_2;
|
||||||
|
import de.uni_marburg.powersort.MSort.IMPL_M_3;
|
||||||
|
import de.uni_marburg.powersort.MSort.IMPL_M_4;
|
||||||
import de.uni_marburg.powersort.benchmark.NaturalOrder;
|
import de.uni_marburg.powersort.benchmark.NaturalOrder;
|
||||||
import de.uni_marburg.powersort.sort.dpqs.DualPivotQuicksort;
|
import de.uni_marburg.powersort.sort.dpqs.DualPivotQuicksort;
|
||||||
|
|
||||||
@ -14,11 +16,14 @@ public enum SortEnum {
|
|||||||
FINN_SORT,
|
FINN_SORT,
|
||||||
IMPL_M_10,
|
IMPL_M_10,
|
||||||
IMPL_M_20,
|
IMPL_M_20,
|
||||||
|
IMPL_M_30,
|
||||||
|
IMPL_M_40,
|
||||||
DPQS,
|
DPQS,
|
||||||
QUICK_SORT,
|
QUICK_SORT,
|
||||||
MERGE_SORT,
|
MERGE_SORT,
|
||||||
BUBBLE_SORT;
|
BUBBLE_SORT;
|
||||||
|
|
||||||
|
|
||||||
public SortImpl getSortImpl() {
|
public SortImpl getSortImpl() {
|
||||||
return switch (this) {
|
return switch (this) {
|
||||||
case BUBBLE_SORT -> array -> BubbleSort.sort(array, NaturalOrder.INSTANCE);
|
case BUBBLE_SORT -> array -> BubbleSort.sort(array, NaturalOrder.INSTANCE);
|
||||||
@ -28,7 +33,9 @@ public enum SortEnum {
|
|||||||
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);
|
||||||
case IMPL_M_10 -> array -> IMPL_M_1.powerSort(array,NaturalOrder.INSTANCE);
|
case IMPL_M_10 -> array -> IMPL_M_1.powerSort(array,NaturalOrder.INSTANCE);
|
||||||
case IMPL_M_20 -> array -> IMPL_M_2.sort(array, 0, array.length, NaturalOrder.INSTANCE, null, 0, 0);
|
case IMPL_M_20 -> array -> IMPL_M_2.powerSort(array,NaturalOrder.INSTANCE);
|
||||||
|
case IMPL_M_30 -> array -> IMPL_M_3.powerSort(array,NaturalOrder.INSTANCE);
|
||||||
|
case IMPL_M_40 -> array -> IMPL_M_4.sort(array, 0, array.length, NaturalOrder.INSTANCE, null, 0, 0);
|
||||||
case FASTER_FINN_SORT -> array -> FasterFinnSort.sort(array, 0, array.length, NaturalOrder.INSTANCE, null, 0, 0);
|
case FASTER_FINN_SORT -> array -> FasterFinnSort.sort(array, 0, array.length, NaturalOrder.INSTANCE, null, 0, 0);
|
||||||
case ASORT -> array -> ASort.sort(array, NaturalOrder.INSTANCE);
|
case ASORT -> array -> ASort.sort(array, NaturalOrder.INSTANCE);
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package de.uni_marburg.powersort.MSort;
|
package de.uni_marburg.powersort.MSort;
|
||||||
|
|
||||||
import static de.uni_marburg.powersort.MSort.IMPL_M_1.*;
|
import static de.uni_marburg.powersort.MSort.IMPL_M_3.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -13,8 +13,8 @@ public class PowerSortT {
|
|||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
testFillWithAscRunsHighToLow();
|
testFillWithAscRunsHighToLow();
|
||||||
testMerge();
|
//testMerge();
|
||||||
testMergeInplace();
|
// testMergeInplace();
|
||||||
testExtendRun();
|
testExtendRun();
|
||||||
testPower();
|
testPower();
|
||||||
testPowerFast();
|
testPowerFast();
|
||||||
@ -32,25 +32,25 @@ public class PowerSortT {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test for merge
|
// Test for merge
|
||||||
public static void testMerge() {
|
// public static void testMerge() {
|
||||||
Integer[] run1 ={1,4,6};
|
// Integer[] run1 ={1,4,6};
|
||||||
Integer []run2 = {2, 3, 5};
|
// Integer []run2 = {2, 3, 5};
|
||||||
Integer[] result = merge(run1, run2, NaturalOrder.INSTANCE);
|
// Integer[] result = merge(run1, run2, NaturalOrder.INSTANCE);
|
||||||
System.out.println("Test merge: " + result);
|
// System.out.println("Test merge: " + result);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Test for mergeInplace
|
// Test for mergeInplace
|
||||||
public static void testMergeInplace() {
|
// public static void testMergeInplace() {
|
||||||
Integer[] A = {1,4,6,2,3,5};
|
// Integer[] A = {1,4,6,2,3,5};
|
||||||
mergeInplace(A, 0, 3, 6,NaturalOrder.INSTANCE);
|
// mergeInplace(A, 0, 3, 6,NaturalOrder.INSTANCE);
|
||||||
System.out.println("Test mergeInplace: " + A);
|
// System.out.println("Test mergeInplace: " + A);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Test for extendRun
|
// Test for extendRun
|
||||||
public static void testExtendRun() {
|
public static void testExtendRun() {
|
||||||
Integer [] A = {1, 2, 3, 6, 5, 4};
|
Integer [] A = {1, 2, 3, 6, 5, 4};
|
||||||
int endIndex = extendRun(A, 0,NaturalOrder.INSTANCE);
|
// int endIndex = extendRun(A, 0,NaturalOrder.INSTANCE);
|
||||||
System.out.println("Test extendRun (from 0): " + endIndex);
|
// System.out.println("Test extendRun (from 0): " + endIndex);
|
||||||
System.out.println("Modified List: " + A);
|
System.out.println("Modified List: " + A);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,8 +59,8 @@ public class PowerSortT {
|
|||||||
int[] run1 = {0, 3};
|
int[] run1 = {0, 3};
|
||||||
int[] run2 = {3, 3};
|
int[] run2 = {3, 3};
|
||||||
int n = 6;
|
int n = 6;
|
||||||
int powerValue = power(run1, run2, n);
|
// int powerValue = power(run1, run2, n);
|
||||||
System.out.println("Test power: " + powerValue);
|
// System.out.println("Test power: " + powerValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test for powerFast
|
// Test for powerFast
|
||||||
@ -68,8 +68,8 @@ public class PowerSortT {
|
|||||||
int[] run1 = {0, 3};
|
int[] run1 = {0, 3};
|
||||||
int[] run2 = {3, 3};
|
int[] run2 = {3, 3};
|
||||||
int n = 6;
|
int n = 6;
|
||||||
int powerFastValue = powerFast(run1, run2, n);
|
// int powerFastValue = powerFast(run1, run2, n);
|
||||||
System.out.println("Test powerFast: " + powerFastValue);
|
// System.out.println("Test powerFast: " + powerFastValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test for mergeTopmost2
|
// Test for mergeTopmost2
|
||||||
@ -78,7 +78,7 @@ public class PowerSortT {
|
|||||||
List<int[]> runs = new ArrayList<>();
|
List<int[]> runs = new ArrayList<>();
|
||||||
runs.add(new int[]{0, 3, 1});
|
runs.add(new int[]{0, 3, 1});
|
||||||
runs.add(new int[]{3, 3, 1});
|
runs.add(new int[]{3, 3, 1});
|
||||||
mergeTopmost2(A, runs,NaturalOrder.INSTANCE);
|
// mergeTopmost2(A, runs,NaturalOrder.INSTANCE);
|
||||||
System.out.println("Test mergeTopmost2: " + A);
|
System.out.println("Test mergeTopmost2: " + A);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,9 +9,9 @@ import java.util.stream.IntStream;
|
|||||||
import de.uni_marburg.powersort.benchmark.NaturalOrder;
|
import de.uni_marburg.powersort.benchmark.NaturalOrder;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static de.uni_marburg.powersort.MSort.IMPL_M_1.MERGE_COST;
|
//import static de.uni_marburg.powersort.MSort.IMPL_M_3.MERGE_COST;
|
||||||
import static de.uni_marburg.powersort.MSort.IMPL_M_1.fillWithAscRunsHighToLow;
|
import static de.uni_marburg.powersort.MSort.IMPL_M_3.fillWithAscRunsHighToLow;
|
||||||
import static de.uni_marburg.powersort.MSort.IMPL_M_1.powerSort;
|
import static de.uni_marburg.powersort.MSort.IMPL_M_3.powerSort;
|
||||||
|
|
||||||
class PowerSortTest {
|
class PowerSortTest {
|
||||||
@Test
|
@Test
|
||||||
@ -28,11 +28,11 @@ class PowerSortTest {
|
|||||||
|
|
||||||
System.out.println();
|
System.out.println();
|
||||||
fillWithAscRunsHighToLow(a, runs, 1);
|
fillWithAscRunsHighToLow(a, runs, 1);
|
||||||
MERGE_COST = 0;
|
//MERGE_COST = 0;
|
||||||
System.out.println("Sorting with Powersort:");
|
System.out.println("Sorting with Powersort:");
|
||||||
powerSort(a,NaturalOrder.INSTANCE);
|
powerSort(a,NaturalOrder.INSTANCE);
|
||||||
System.out.println("Sorted Array"+Arrays.toString(a));
|
System.out.println("Sorted Array"+Arrays.toString(a));
|
||||||
System.out.println("Merge cost: " + MERGE_COST);
|
// System.out.println("Merge cost: " + MERGE_COST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user