diff --git a/.idea/misc.xml b/.idea/misc.xml index a29a496..baddb10 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ - - + + \ No newline at end of file diff --git a/app/src/main/java/de/uni_marburg/powersort/App.java b/app/src/main/java/de/uni_marburg/powersort/App.java index 23e9332..fc8aa9e 100644 --- a/app/src/main/java/de/uni_marburg/powersort/App.java +++ b/app/src/main/java/de/uni_marburg/powersort/App.java @@ -3,6 +3,11 @@ */ package de.uni_marburg.powersort; +import java.util.ArrayList; +import java.util.List; + +import static de.uni_marburg.powersort.PowerSort.extendRun; + public class App { public String getGreeting() { return "Let's bring Powersort to Java!"; @@ -10,5 +15,8 @@ public class App { public static void main(String[] args) { System.out.println(new App().getGreeting()); + List list = new ArrayList<>(List.of(5, 2, 8, 12, 1, 6)); + extendRun(list, 0); + System.out.println(list); } } diff --git a/app/src/main/java/de/uni_marburg/powersort/PowerSort.java b/app/src/main/java/de/uni_marburg/powersort/PowerSort.java index 7c7f5fc..2152d71 100644 --- a/app/src/main/java/de/uni_marburg/powersort/PowerSort.java +++ b/app/src/main/java/de/uni_marburg/powersort/PowerSort.java @@ -1,6 +1,8 @@ package de.uni_marburg.powersort; -import java.util.Comparator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; class PowerSort { /** @@ -19,8 +21,229 @@ class PowerSort { * @param workLen usable size of work array * @since 1.8 */ - static void sort(T[] a, int lo, int hi, Comparator c, + private static int MERGE_COST = 0; + + private static List merge(List run1, List run2) { + List result = new ArrayList<>(); + while (!run1.isEmpty() && !run2.isEmpty()) { + if (run1.get(0) < run2.get(0)) { + result.add(run1.remove(0)); + } else { + result.add(run2.remove(0)); + } + } + result.addAll(run1); + result.addAll(run2); + return result; + } + + private static void mergeInplace(List a, int i, int m, int j) { + System.out.printf("Merge(%d, %d, %d)%n", i, m, j); + MERGE_COST += j - i; + List sublist = merge( + new ArrayList<>(a.subList(i, m)), + new ArrayList<>(a.subList(m, j)) + ); + for (int k = 0; k < sublist.size(); k++) { + a.set(i + k, sublist.get(k)); + } + } + + static int extendRun(List a, int i) { + if (i == a.size() - 1) { + return i + 1; + } + int j = i + 1; + if (a.get(i) <= a.get(j)) { + while (j < a.size() && a.get(j - 1) <= a.get(j)) { + j++; + } + } else { + while (j < a.size() && a.get(j - 1) > a.get(j)) { + j++; + } + List sublist = a.subList(i, j); + Collections.reverse(sublist); + } + return j; + } + + private static int extendRunIncreasingOnly(List a, int i) { + if (i == a.size() - 1) { + return i + 1; + } + int j = i + 1; + while (j < a.size() && a.get(j - 1) <= a.get(j)) { + j++; + } + return j; + } + + public static int power(int[] run1, int[] run2, int n) { + int i1 = run1[0], n1 = run1[1]; + int i2 = run2[0], n2 = run2[1]; + + assert i1 >= 0; + assert i2 == i1 + n1; + assert n1 >= 1 && n2 >= 1; + assert i2 + n2 <= n; +// ask question about this whether it should be double or int + int a = (int) ((i1 + n1 / 2.0) / n); + int b = (int) ((i2 + n2 / 2.0) / n); + + int l = 0; + while (Math.floor(a * Math.pow(2, l)) == Math.floor(b * Math.pow(2, l))) { + l++; + } + return l; + } + + public static int powerFast(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) { + assert b >= a; + a -= n; + b -= n; + } else if (b >= n) { + break; + } + assert a < b && b < n; + a <<= 1; + b <<= 1; + } + return l; + } + + public static void mergeTopmost2(List a, List runs) { + assert runs.size() >= 2; +// is this right? + int[] Y = runs.get(runs.size() - 2); + int[] Z = runs.get(runs.size() - 1); + + assert Z[0] == Y[0] + Y[1]; + + mergeInplace(a, Y[0], Z[0], Z[0] + Z[1]); + + runs.set(runs.size() - 2, new int[]{Y[0], Y[1] + Z[1], Y[2]}); + runs.remove(runs.size() - 1); + } + + public static void powerSort(List a) { + int n = a.size(); + int i = 0; + List runs = new ArrayList<>(); + + int j = extendRun(a, i); + runs.add(new int[]{i, j - i, 0}); + i = j; + + while (i < n) { + j = extendRun(a, i); + int p = power(runs.get(runs.size() - 1), new int[]{i, j - i}, n); + + while (p <= runs.get(runs.size() - 1)[2]) { + mergeTopmost2(a, runs); + } + + runs.add(new int[]{i, j - i, p}); + i = j; + } + + while (runs.size() >= 2) { + mergeTopmost2(a, runs); + } + } + } + +// // Example usage +// public static void main(String[] args) { +// List list = new ArrayList<>(List.of(5, 2, 8, 12, 1, 6)); +// extendRun(list, 0); +// System.out.println(list); +// } + + + + /* static void sort(T[] a, int lo, int hi, Comparator c, T[] work, int workBase, int workLen) { assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length; + }*/ +/* + public static final int MIN_MERGE=24; + public int mergeCost=0; + private final T []sortedArray; + + public PowerSort(T[] sortedArray) { + super(); + this.sortedArray = sortedArray; } -} \ No newline at end of file + + ArrayList run1 = new ArrayList<>(); + ArrayList run2 = new ArrayList<>(); + + private AbstractList merge(ArrayList run1, ArrayList run2) { + ArrayList result = new ArrayList<>(); + + while(run1.size() > 0 && run2.size() >0) { + if (run1.getFirst()