WIP power sort

This commit is contained in:
Ambili Jacob 2024-12-10 18:07:32 +01:00
parent b3f26f8abd
commit e92ecc309a

View File

@ -0,0 +1,129 @@
package de.uni_marburg.powersort;
import java.util.Comparator;
import java.util.Stack;
public class ASort {
private static class Run {
int start, end;
int power;
Run(int start, int end, int power) {
this.start = start;
this.end = end;
this.power = power;
}
}
public static <T> void sort(T[] array, Comparator<? super T> comparator) {
if (array == null || comparator == null) {
throw new IllegalArgumentException("Array and comparator must not be null");
}
int n = array.length;
if (n < 2) return;
Stack<Run> runs = new Stack<>();
int i = 0;
while (i < n) {
// Find the next run
int j = extendRunRight(array, comparator, i, n);
// Compute the power of the run
int power = calculatePower(runs.isEmpty() ? null : runs.peek(), i, j);
// Merge runs if needed based on power comparison
while (!runs.isEmpty() && power <= runs.peek().power) {
mergeRuns(array, comparator, runs);
}
// Push the current run
runs.push(new Run(i, j, power));
i = j;
}
// Merge remaining runs
while (runs.size() > 1) {
mergeRuns(array, comparator, runs);
}
}
private static <T> int extendRunRight(T[] array, Comparator<? super T> comparator, int start, int end) {
int runEnd = start + 1;
if (runEnd == end) return runEnd;
// Check for ascending or descending order
if (comparator.compare(array[runEnd], array[start]) < 0) {
// Descending run
while (runEnd < end && comparator.compare(array[runEnd], array[runEnd - 1]) < 0) {
runEnd++;
}
reverseRange(array, start, runEnd);
} else {
// Ascending run
while (runEnd < end && comparator.compare(array[runEnd], array[runEnd - 1]) >= 0) {
runEnd++;
}
}
return runEnd;
}
private static <T> void reverseRange(T[] array, int start, int end) {
end--;
while (start < end) {
T temp = array[start];
array[start++] = array[end];
array[end--] = temp;
}
}
private static int calculatePower(Run previousRun, int currentStart, int currentEnd) {
if (previousRun == null) {
return 0; // First run
}
int previousSize = previousRun.end - previousRun.start;
int currentSize = currentEnd - currentStart;
return (int) (Math.log(previousSize + currentSize) / Math.log(2));
}
private static <T> void mergeRuns(T[] array, Comparator<? super T> comparator, Stack<Run> runs) {
Run run2 = runs.pop();
Run run1 = runs.pop();
merge(array, comparator, run1.start, run1.end, run2.end);
runs.push(new Run(run1.start, run2.end, calculatePower(null, run1.start, run2.end)));
}
private static <T> void merge(T[] array, Comparator<? super T> comparator, int lo, int mid, int hi) {
T[] left = java.util.Arrays.copyOfRange(array, lo, mid);
int i = 0, j = mid, k = lo;
while (i < left.length && j < hi) {
if (comparator.compare(left[i], array[j]) <= 0) {
array[k++] = left[i++];
} else {
array[k++] = array[j++];
}
}
while (i < left.length) {
array[k++] = left[i++];
}
}
public static void main(String[] args) {
Integer[] array = {5, 2, 9, 1, 5, 6, 3, 7, 4, 8};
System.out.println("Before sorting:");
java.util.Arrays.stream(array).forEach(e -> System.out.print(e + " "));
sort(array, Integer::compareTo);
System.out.println("\nAfter sorting:");
java.util.Arrays.stream(array).forEach(e -> System.out.print(e + " "));
}
}