diff --git a/app/src/main/java/de/uni_marburg/powersort/ASort.java b/app/src/main/java/de/uni_marburg/powersort/ASort.java new file mode 100644 index 0000000..20c1207 --- /dev/null +++ b/app/src/main/java/de/uni_marburg/powersort/ASort.java @@ -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 void sort(T[] array, Comparator 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 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 int extendRunRight(T[] array, Comparator 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 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 void mergeRuns(T[] array, Comparator comparator, Stack 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 void merge(T[] array, Comparator 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 + " ")); + } +}