This commit is contained in:
Ambili Jacob 2025-03-13 11:29:15 +01:00
parent 691d7eb0ac
commit 89c0ca10c7

View File

@ -1,13 +1,12 @@
package de.uni_marburg.powersort.sort; package de.uni_marburg.powersort.sort;
import java.util.Comparator; import java.util.*;
import java.util.Stack; import java.util.stream.Collectors;
public class ASort { public class ASort {
private static class Run { private static class Run {
int start, end; int start, end, power;
int power;
Run(int start, int end, int power) { Run(int start, int end, int power) {
this.start = start; this.start = start;
@ -24,27 +23,21 @@ public class ASort {
int n = array.length; int n = array.length;
if (n < 2) return; if (n < 2) return;
Stack<Run> runs = new Stack<>(); Deque<Run> runs = new ArrayDeque<>();
int i = 0; int i = 0;
while (i < n) { while (i < n) {
// Find the next run
int j = extendRunRight(array, comparator, i, n); int j = extendRunRight(array, comparator, i, n);
// Compute the power of the run
int power = calculatePower(runs, i, j); int power = calculatePower(runs, i, j);
// Merge runs if needed based on power comparison while (!runs.isEmpty() && power <= runs.peekLast().power) {
while (!runs.isEmpty() && power <= runs.peek().power) {
mergeRuns(array, comparator, runs); mergeRuns(array, comparator, runs);
} }
// Push the current run runs.addLast(new Run(i, j, power));
runs.push(new Run(i, j, power));
i = j; i = j;
} }
// Merge remaining runs
while (runs.size() > 1) { while (runs.size() > 1) {
mergeRuns(array, comparator, runs); mergeRuns(array, comparator, runs);
} }
@ -55,20 +48,16 @@ public class ASort {
if (runEnd == end) return runEnd; if (runEnd == end) return runEnd;
// Check for ascending or descending order
if (comparator.compare(array[runEnd], array[start]) < 0) { if (comparator.compare(array[runEnd], array[start]) < 0) {
// Descending run
while (runEnd < end && comparator.compare(array[runEnd], array[runEnd - 1]) < 0) { while (runEnd < end && comparator.compare(array[runEnd], array[runEnd - 1]) < 0) {
runEnd++; runEnd++;
} }
reverseRange(array, start, runEnd); reverseRange(array, start, runEnd);
} else { } else {
// Ascending run
while (runEnd < end && comparator.compare(array[runEnd], array[runEnd - 1]) >= 0) { while (runEnd < end && comparator.compare(array[runEnd], array[runEnd - 1]) >= 0) {
runEnd++; runEnd++;
} }
} }
return runEnd; return runEnd;
} }
@ -81,58 +70,56 @@ public class ASort {
} }
} }
private static int calculatePower(Stack<Run> runs, int currentStart, int currentEnd) { private static int calculatePower(Deque<Run> runs, int currentStart, int currentEnd) {
if (runs.isEmpty()) { if (runs.isEmpty()) return 0;
return 0; // First run always has power 0
}
Run topRun = runs.peek(); Run topRun = runs.peekLast();
int size1 = topRun.end - topRun.start; int size1 = topRun.end - topRun.start;
int size2 = currentEnd - currentStart; int size2 = currentEnd - currentStart;
return Math.max(topRun.power, (int) (Math.log(size1 + size2) / Math.log(2))) + 1; return Math.max(topRun.power, Integer.highestOneBit(size1 + size2)) + 1;
} }
private static <T> void mergeRuns(T[] array, Comparator<? super T> comparator, Stack<Run> runs) { private static <T> void mergeRuns(T[] array, Comparator<? super T> comparator, Deque<Run> runs) {
while (runs.size() > 1) { if (runs.size() < 2) return;
Run run2 = runs.pop();
Run run1 = runs.pop();
// Merge runs and recalculate power Run run2 = runs.removeLast();
merge(array, comparator, run1.start, run1.end, run2.end); Run run1 = runs.removeLast();
int newPower = Math.max(run1.power, run2.power) + 1;
runs.push(new Run(run1.start, run2.end, newPower)); merge(array, comparator, run1.start, run1.end, run2.end);
} int newPower = Math.max(run1.power, run2.power) + 1;
runs.addLast(new Run(run1.start, run2.end, newPower));
} }
private static <T> void merge(T[] array, Comparator<? super T> comparator, int lo, int mid, int hi) { 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); List<T> merged = Arrays.stream(array, lo, mid)
.sorted(comparator)
.collect(Collectors.toList());
int i = 0, j = mid, k = lo; int i = 0, j = mid, k = lo;
while (i < left.length && j < hi) { while (i < merged.size() && j < hi) {
if (comparator.compare(left[i], array[j]) <= 0) { array[k++] = comparator.compare(merged.get(i), array[j]) <= 0 ? merged.get(i++) : array[j++];
array[k++] = left[i++];
} else {
array[k++] = array[j++];
}
} }
while (i < left.length) { while (i < merged.size()) {
array[k++] = left[i++]; array[k++] = merged.get(i++);
} }
} }
public static void main(String[] args) { public static void main(String[] args) {
Integer[] array = {0, 1, 2, 3, 4, 5, -5, -4, -3, -2, -1, -10, -9, -8, -7, -6}; Integer[] array = {0, 1, 2, 3, 4, 5, -5, -4, -3, -2, -1, -10, -9, -8, -7, -6};
System.out.println("Before sorting:"); System.out.println("Before sorting:");
java.util.Arrays.stream(array).forEach(e -> System.out.print(e + " ")); Arrays.stream(array).forEach(e -> System.out.print(e + " "));
sort(array, Integer::compareTo); sort(array, Integer::compareTo);
System.out.println("\nAfter sorting:"); System.out.println("\nAfter sorting:");
java.util.Arrays.stream(array).forEach(e -> System.out.print(e + " ")); Arrays.stream(array).forEach(e -> System.out.print(e + " "));
} }
} }