mirror of
https://gitlab.uni-marburg.de/langbeid/powersort.git
synced 2025-04-01 07:26:01 +02:00
refactor
This commit is contained in:
parent
691d7eb0ac
commit
89c0ca10c7
@ -1,13 +1,12 @@
|
||||
package de.uni_marburg.powersort.sort;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Stack;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ASort {
|
||||
|
||||
private static class Run {
|
||||
int start, end;
|
||||
int power;
|
||||
int start, end, power;
|
||||
|
||||
Run(int start, int end, int power) {
|
||||
this.start = start;
|
||||
@ -24,27 +23,21 @@ public class ASort {
|
||||
int n = array.length;
|
||||
if (n < 2) return;
|
||||
|
||||
Stack<Run> runs = new Stack<>();
|
||||
Deque<Run> runs = new ArrayDeque<>();
|
||||
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, i, j);
|
||||
|
||||
// Merge runs if needed based on power comparison
|
||||
while (!runs.isEmpty() && power <= runs.peek().power) {
|
||||
while (!runs.isEmpty() && power <= runs.peekLast().power) {
|
||||
mergeRuns(array, comparator, runs);
|
||||
}
|
||||
|
||||
// Push the current run
|
||||
runs.push(new Run(i, j, power));
|
||||
runs.addLast(new Run(i, j, power));
|
||||
i = j;
|
||||
}
|
||||
|
||||
// Merge remaining runs
|
||||
while (runs.size() > 1) {
|
||||
mergeRuns(array, comparator, runs);
|
||||
}
|
||||
@ -55,20 +48,16 @@ public class ASort {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -81,58 +70,56 @@ public class ASort {
|
||||
}
|
||||
}
|
||||
|
||||
private static int calculatePower(Stack<Run> runs, int currentStart, int currentEnd) {
|
||||
if (runs.isEmpty()) {
|
||||
return 0; // First run always has power 0
|
||||
}
|
||||
private static int calculatePower(Deque<Run> runs, int currentStart, int currentEnd) {
|
||||
if (runs.isEmpty()) return 0;
|
||||
|
||||
Run topRun = runs.peek();
|
||||
Run topRun = runs.peekLast();
|
||||
int size1 = topRun.end - topRun.start;
|
||||
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) {
|
||||
while (runs.size() > 1) {
|
||||
Run run2 = runs.pop();
|
||||
Run run1 = runs.pop();
|
||||
private static <T> void mergeRuns(T[] array, Comparator<? super T> comparator, Deque<Run> runs) {
|
||||
if (runs.size() < 2) return;
|
||||
|
||||
// Merge runs and recalculate power
|
||||
merge(array, comparator, run1.start, run1.end, run2.end);
|
||||
int newPower = Math.max(run1.power, run2.power) + 1;
|
||||
Run run2 = runs.removeLast();
|
||||
Run run1 = runs.removeLast();
|
||||
|
||||
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) {
|
||||
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;
|
||||
|
||||
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 < merged.size() && j < hi) {
|
||||
array[k++] = comparator.compare(merged.get(i), array[j]) <= 0 ? merged.get(i++) : array[j++];
|
||||
}
|
||||
|
||||
while (i < left.length) {
|
||||
array[k++] = left[i++];
|
||||
while (i < merged.size()) {
|
||||
array[k++] = merged.get(i++);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Integer[] array = {0, 1, 2, 3, 4, 5, -5, -4, -3, -2, -1, -10, -9, -8, -7, -6};
|
||||
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);
|
||||
|
||||
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 + " "));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user