diff --git a/.vscode/settings.json b/.vscode/settings.json index 215bcb13..1263ce89 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { - "java.configuration.updateBuildConfiguration": "interactive", + "java.configuration.updateBuildConfiguration": "automatic", "java.checkstyle.configuration": "${workspaceFolder}/checkstyle.xml", "java.checkstyle.version": "9.3", "java.completion.filteredTypes": [ @@ -9,4 +9,4 @@ "org.graalvm.*", "io.micrometer.shaded.*" ] -} +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index f790fcbb..d1168478 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,7 @@ - 4.0.0 @@ -14,8 +15,7 @@ UTF-8 - 1.8 - 1.8 + 17 @@ -176,7 +176,8 @@ maven-clean-plugin 3.1.0 - + maven-resources-plugin 3.0.2 @@ -197,7 +198,8 @@ maven-deploy-plugin 2.8.2 - + maven-site-plugin 3.7.1 @@ -209,4 +211,4 @@ - + \ No newline at end of file diff --git a/src/main/java/io/github/arrayv/sortdata/SortInfo.java b/src/main/java/io/github/arrayv/sortdata/SortInfo.java index bad5dbef..93275b01 100644 --- a/src/main/java/io/github/arrayv/sortdata/SortInfo.java +++ b/src/main/java/io/github/arrayv/sortdata/SortInfo.java @@ -1,17 +1,16 @@ package io.github.arrayv.sortdata; -import io.github.arrayv.main.ArrayVisualizer; -import io.github.arrayv.sorts.templates.Sort; - import java.util.Arrays; import java.util.HashSet; import java.util.Objects; import java.util.function.IntUnaryOperator; import java.util.function.Supplier; +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sorts.templates.Sort; + public final class SortInfo { - private static final String NAME_MUST_BE_SPECIFIED = - "name must be specified unless all three of listName, showcaseName, and runName are specified"; + private static final String NAME_MUST_BE_SPECIFIED = "name must be specified unless all three of listName, showcaseName, and runName are specified"; private final int id; private final String internalName; @@ -78,15 +77,16 @@ public SortInfo(int id, Class sortClass) { this.disabled = metaAnnotation.disabled(); this.unreasonableLimit = metaAnnotation.unreasonableLimit(); this.listName = metaAnnotation.listName().isEmpty() - ? requireName(name) - : metaAnnotation.listName(); + ? requireName(name) + : metaAnnotation.listName(); this.runName = metaAnnotation.runName().isEmpty() - ? requireName(name) + "sort" - : metaAnnotation.runName(); - this.runAllName = metaAnnotation.showcaseName().isEmpty() - ? requireName(name) + " Sort" - : metaAnnotation.showcaseName(); - this.category = metaAnnotation.category().isEmpty() ? findSortCategory(sortClass) : metaAnnotation.category(); + ? requireName(name) + " Sort" + : metaAnnotation.runName(); + this.runAllName = metaAnnotation.runName().isEmpty() + ? requireName(name) + " Sort" + : metaAnnotation.runName(); + this.category = metaAnnotation.category().isEmpty() ? findSortCategory(sortClass) + : metaAnnotation.category(); this.bogoSort = metaAnnotation.bogoSort(); this.radixSort = metaAnnotation.radixSort(); this.bucketSort = metaAnnotation.bucketSort(); @@ -124,15 +124,16 @@ public SortInfo(int id, Sort sort) { this.disabled = metaAnnotation.disabled(); this.unreasonableLimit = metaAnnotation.unreasonableLimit(); this.listName = metaAnnotation.listName().isEmpty() - ? requireName(name) - : metaAnnotation.listName(); + ? requireName(name) + : metaAnnotation.listName(); this.runName = metaAnnotation.runName().isEmpty() - ? requireName(name) + "sort" - : metaAnnotation.runName(); - this.runAllName = metaAnnotation.showcaseName().isEmpty() - ? requireName(name) + " Sort" - : metaAnnotation.showcaseName(); - this.category = metaAnnotation.category().isEmpty() ? findSortCategory(sort.getClass()) : metaAnnotation.category(); + ? requireName(name) + " Sort" + : metaAnnotation.runName(); + this.runAllName = metaAnnotation.runName().isEmpty() + ? requireName(name) + " Sort" + : metaAnnotation.runName(); + this.category = metaAnnotation.category().isEmpty() ? findSortCategory(sort.getClass()) + : metaAnnotation.category(); this.bogoSort = metaAnnotation.bogoSort(); this.radixSort = metaAnnotation.radixSort(); this.bucketSort = metaAnnotation.bucketSort(); @@ -143,23 +144,22 @@ public SortInfo(int id, Sort sort) { } private SortInfo( - int id, - String internalName, - Supplier instanceSupplier, - boolean disabled, - int unreasonableLimit, - String listName, - String runName, - String runAllName, - String category, - boolean slowSort, - boolean bogoSort, - boolean radixSort, - boolean bucketSort, - String question, - int defaultAnswer, - IntUnaryOperator answerValidator - ) { + int id, + String internalName, + Supplier instanceSupplier, + boolean disabled, + int unreasonableLimit, + String listName, + String runName, + String runAllName, + String category, + boolean slowSort, + boolean bogoSort, + boolean radixSort, + boolean bucketSort, + String question, + int defaultAnswer, + IntUnaryOperator answerValidator) { this.id = id; this.internalName = internalName; this.instanceSupplier = instanceSupplier; @@ -195,8 +195,8 @@ private static String findSortCategory(Class sortClass) { } } throw new NullPointerException( - "Sort " + sortClass.getSimpleName() + " does not declare a category, and neither do any of its packages" - ); + "Sort " + sortClass.getSimpleName() + + " does not declare a category, and neither do any of its packages"); } private static String requireName(String name) { @@ -211,7 +211,8 @@ private static String normalizeName(SortMeta meta) { if (name.endsWith("sort")) { return name.substring(0, name.length() - 4); } - // Cause an NPE if name isn't specified, and all three required names also aren't + // Cause an NPE if name isn't specified, and all three required names also + // aren't return name.isEmpty() ? null : name; } @@ -293,6 +294,7 @@ public boolean isFromExtra() { /** * Creates a copy of this info with a new ID + * * @param id The ID for the new instance * @return Copied info with new ID */ @@ -343,10 +345,9 @@ public boolean equals(Object obj) { if (this == obj) { return true; } - if (!(obj instanceof SortInfo)) { + if (!(obj instanceof SortInfo other)) { return false; } - SortInfo other = (SortInfo) obj; if (bogoSort != other.bogoSort) { return false; } @@ -438,23 +439,22 @@ private Builder() { public SortInfo build() { return new SortInfo( - id, - internalName, - Objects.requireNonNull(instanceSupplier, "instanceSupplier"), - disabled, - unreasonableLimit, - Objects.requireNonNull(listName, "listName"), - runName != null ? runName : (listName + "sort"), - runAllName != null ? runAllName : (listName + " Sort"), - Objects.requireNonNull(category, "category"), - slowSort, - bogoSort, - radixSort, - bucketSort, - question, - defaultAnswer, - answerValidator - ); + id, + internalName, + Objects.requireNonNull(instanceSupplier, "instanceSupplier"), + disabled, + unreasonableLimit, + Objects.requireNonNull(listName, "listName"), + runName != null ? runName : (listName + "sort"), + runAllName != null ? runAllName : (listName + " Sort"), + Objects.requireNonNull(category, "category"), + slowSort, + bogoSort, + radixSort, + bucketSort, + question, + defaultAnswer, + answerValidator); } public Builder id(int id) { diff --git a/src/main/java/io/github/arrayv/sortdata/SortMeta.java b/src/main/java/io/github/arrayv/sortdata/SortMeta.java index 1ff6632e..a3d9d158 100644 --- a/src/main/java/io/github/arrayv/sortdata/SortMeta.java +++ b/src/main/java/io/github/arrayv/sortdata/SortMeta.java @@ -3,7 +3,8 @@ import java.lang.annotation.*; /** - * Annotation to specify the sorting algorithm's metadata. This should only be applied to subclasses of + * Annotation to specify the sorting algorithm's metadata. This should only be + * applied to subclasses of * {@link io.github.arrayv.sorts.templates.Sort Sort}. */ @Documented @@ -11,83 +12,99 @@ @Target(ElementType.TYPE) public @interface SortMeta { /** - * The sort's name. This is generally of the form {@code "Something"} or {@code "Something Sort"}. If not - * specified, all three of {@link #listName()}, {@link #runName()}, and {@link #showcaseName()} must be specified. + * The sort's name. This is generally of the form {@code "Something"} or + * {@code "Something Sort"}. If not + * specified, all three of {@link #listName()}, {@link #runName()}, and + * {@link #showcaseName()} must be specified. + * * @return The sort's annotated name. */ String name() default ""; /** - * The sort's category. This may be specified on a package-level in package-info.java. Specifying it here will + * The sort's category. This may be specified on a package-level in + * package-info.java. Specifying it here will * override it for the package. - * @return The sort's category, or {@code ""} if you should look at the package level. + * + * @return The sort's category, or {@code ""} if you should look at the package + * level. */ String category() default ""; /** * Explicit sort list name. This is generated from {@link #name()} by default. + * * @return The sort's explicit list name, if it has one. {@code ""} otherwise. */ String listName() default ""; /** * Explicit Run Sort name. This is generated from {@link #name()} by default. - * @return The sort's explicit Run Sort name, if it has one. {@code ""} otherwise. + * + * @return The sort's explicit Run Sort name, if it has one. {@code ""} + * otherwise. */ String runName() default ""; - /** - * Explicit Showcase Sorts name (and scripting name). This is generated from {@link #name()} by default. - * @return The sort's explicit Showcase Sorts name, if it has one. {@code ""} otherwise. - */ - String showcaseName() default ""; - /** * Whether this sort is disabled. Disabled sorts won't be loaded. + * * @return Whether this sort is disabled. */ boolean disabled() default false; /** - * This sort's unreasonable limit. If the sort is run with lengths higher than this, a warning is displayed. + * This sort's unreasonable limit. If the sort is run with lengths higher than + * this, a warning is displayed. + * * @return This sort's unreasonable limit. */ int unreasonableLimit() default 0; /** * Whether to treat this sort as slow in Showcase Sorts and in sort scripts. + * * @return Whether to treat this sort as slow. */ boolean slowSort() default false; /** - * Whether this sort is a bogo sort (i.e. it has "bogo" in its name, and it's non-deterministic). + * Whether this sort is a bogo sort (i.e. it has "bogo" in its name, and it's + * non-deterministic). + * * @return Whether this sort is a bogo sort. */ boolean bogoSort() default false; /** * Whether this sort is a Radix Sort. + * * @return Whether this sort is a Radix Sort. */ boolean radixSort() default false; /** * Whether this sort uses buckets. + * * @return Whether this sort uses buckets. */ boolean bucketSort() default false; /** - * A question to ask the user when they choose this sort. You can perform response validation by creating a method + * A question to ask the user when they choose this sort. You can perform + * response validation by creating a method * that is {@code public static int validateAnswer(int answer)}. + * * @return The question to ask the user, or {@code ""} if there isn't one. */ String question() default ""; /** - * The default response to use for {@link #question()}. This is used when the user pressed "Use default". This - * value is ignored if there is no question. This value is not passed through {@code validatorAnswer}. + * The default response to use for {@link #question()}. This is used when the + * user pressed "Use default". This + * value is ignored if there is no question. This value is not passed + * through {@code validatorAnswer}. + * * @return The default answer response. */ int defaultAnswer() default 0; diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortIterative.java b/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortIterative.java index f112a5c9..c50dfccf 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortIterative.java @@ -12,11 +12,7 @@ * work for array lengths other than powers of two! */ -@SortMeta( - name = "Iterative Bitonic", - listName = "Bitonic (Iterative)", - runName = "Iterative Bitonic Sort" -) +@SortMeta(listName = "Bitonic (Iterative)", runName = "Iterative Bitonic Sorting Network") public final class BitonicSortIterative extends Sort { public BitonicSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -26,17 +22,17 @@ public BitonicSortIterative(ArrayVisualizer arrayVisualizer) { public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { int i, j, k; - for(k = 2; k < sortLength*2; k = 2 * k) { + for (k = 2; k < sortLength * 2; k = 2 * k) { boolean m = (((sortLength + (k - 1)) / k) % 2) != 0; - for(j = k >> 1; j > 0; j = j >> 1) { - for(i = 0; i < sortLength; i++) { + for (j = k >> 1; j > 0; j = j >> 1) { + for (i = 0; i < sortLength; i++) { int ij = i ^ j; - if((ij) > i && ij < sortLength) { - if((((i & k) == 0) == m) && Reads.compareIndices(array, i, ij, 0.5, true) > 0) + if ((ij) > i && ij < sortLength) { + if ((((i & k) == 0) == m) && Reads.compareIndices(array, i, ij, 0.5, true) > 0) Writes.swap(array, i, ij, 0.5, true, false); - if((((i & k) != 0) == m) && Reads.compareIndices(array, i, ij, 0.5, true) < 0) + if ((((i & k) != 0) == m) && Reads.compareIndices(array, i, ij, 0.5, true) < 0) Writes.swap(array, i, ij, 0.5, true, false); } } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortParallel.java b/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortParallel.java index e623db1e..fc340fba 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortParallel.java @@ -4,15 +4,11 @@ import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; -@SortMeta( - name = "Parallel Bitonic", - listName = "Bitonic (Parallel)", - runName = "Parallel Bitonic Sort", - unreasonableLimit = 4096 -) +@SortMeta(listName = "Bitonic (Parallel)", runName = "Parallel Bitonic Sorting Network", unreasonableLimit = 4096) public final class BitonicSortParallel extends Sort { private int[] arr; private final double DELAY = 1; + public BitonicSortParallel(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } @@ -20,11 +16,14 @@ public BitonicSortParallel(ArrayVisualizer arrayVisualizer) { private class SortThread extends Thread { private int start, stop; private boolean ascending; + SortThread(int start, int stop, boolean ascending) { this.start = start; this.stop = stop; this.ascending = ascending; } + + @Override public void run() { BitonicSortParallel.this.bitonicSort(this.start, this.stop, this.ascending); } @@ -32,6 +31,7 @@ public void run() { private class MergeThread extends Thread { private int start, mid, stop, gap, flag; + MergeThread(int start, int mid, int stop, int gap, int flag) { this.start = start; this.mid = mid; @@ -39,6 +39,8 @@ private class MergeThread extends Thread { this.gap = gap; this.flag = flag; } + + @Override public void run() { BitonicSortParallel.this.bitonicMerge(this.start, this.mid, this.stop, this.gap, this.flag); } @@ -50,10 +52,10 @@ private void bitonicMerge(int start, int mid, int stop, int gap, int flag) { if (Reads.compareIndices(arr, i, i + gap, DELAY, true) == flag) Writes.swap(arr, i, i + gap, DELAY, true, false); int newGap = gap / 2; - MergeThread left = new MergeThread(start, (mid - start) / 2 + start, mid, newGap, flag); - MergeThread right = new MergeThread(mid, (stop - mid) / 2 + mid, stop, newGap, flag); - left.start(); - right.start(); + MergeThread left = new MergeThread(start, (mid - start) / 2 + start, mid, newGap, flag); + MergeThread right = new MergeThread(mid, (stop - mid) / 2 + mid, stop, newGap, flag); + left.start(); + right.start(); try { left.join(); right.join(); @@ -68,10 +70,10 @@ private void bitonicSort(int start, int stop, boolean ascending) { if (length >= 2) { int gap = length / 2; int mid = gap + start; - SortThread left = new SortThread(start, mid, !ascending); - SortThread right = new SortThread(mid, stop, ascending); - left.start(); - right.start(); + SortThread left = new SortThread(start, mid, !ascending); + SortThread right = new SortThread(mid, stop, ascending); + left.start(); + right.start(); try { left.join(); right.join(); diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortRecursive.java b/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortRecursive.java index aced713d..5ac24b15 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/BitonicSortRecursive.java @@ -9,11 +9,7 @@ * http://www.inf.fh-flensburg.de/lang/algorithmen/sortieren/bitonic/oddn.htm */ -@SortMeta( - listName = "Bitonic (Recursive)", - showcaseName = "Batcher's Bitonic Sort", - runName = "Recursive Bitonic Sort" -) +@SortMeta(listName = "Bitonic (Recursive)", runName = "Recursive Bitonic Sorting Network") public final class BitonicSortRecursive extends Sort { private boolean direction = true; @@ -21,7 +17,7 @@ public BitonicSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - private static int greatestPowerOfTwoLessThan(int n){ + private static int greatestPowerOfTwoLessThan(int n) { int k = 1; while (k < n) { k = k << 1; @@ -29,21 +25,19 @@ private static int greatestPowerOfTwoLessThan(int n){ return k >> 1; } - private void compare(int[] A, int i, int j, boolean dir) - { + private void compare(int[] A, int i, int j, boolean dir) { int cmp = Reads.compareIndices(A, i, j, 0.5, true); - if (dir == (cmp == 1)) Writes.swap(A, i, j, 0.5, true, false); + if (dir == (cmp == 1)) + Writes.swap(A, i, j, 0.5, true, false); } - private void bitonicMerge(int[] A, int lo, int n, boolean dir) - { - if (n > 1) - { + private void bitonicMerge(int[] A, int lo, int n, boolean dir) { + if (n > 1) { int m = greatestPowerOfTwoLessThan(n); for (int i = lo; i < lo + n - m; i++) { - this.compare(A, i, i+m, dir); + this.compare(A, i, i + m, dir); } this.bitonicMerge(A, lo, m, dir); @@ -51,10 +45,8 @@ private void bitonicMerge(int[] A, int lo, int n, boolean dir) } } - private void bitonicSort(int[] A, int lo, int n, boolean dir) - { - if (n > 1) - { + private void bitonicSort(int[] A, int lo, int n, boolean dir) { + if (n > 1) { int m = n / 2; this.bitonicSort(A, lo, m, !dir); this.bitonicSort(A, lo + m, n - m, dir); @@ -63,9 +55,12 @@ private void bitonicSort(int[] A, int lo, int n, boolean dir) } public void changeDirection(String choice) throws Exception { - if(choice.equals("forward")) this.direction = true; - else if(choice.equals("backward")) this.direction = false; - else throw new Exception("Invalid direction for Bitonic Sort!"); + if (choice.equals("forward")) + this.direction = true; + else if (choice.equals("backward")) + this.direction = false; + else + throw new Exception("Invalid direction for Bitonic Sort!"); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortIterative.java b/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortIterative.java index 7ad3af00..f3f19712 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortIterative.java @@ -4,41 +4,39 @@ import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; -@SortMeta( - listName = "Bose-Nelson (Iterative)", - showcaseName = "Iterative Bose-Nelson Sorting Network", - runName = "Iterative Bose-Nelson Sort" -) +@SortMeta(listName = "Bose-Nelson (Iterative)", runName = "Iterative Bose-Nelson Sorting Network") public final class BoseNelsonSortIterative extends Sort { - public BoseNelsonSortIterative(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - } + public BoseNelsonSortIterative(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int end; private void compSwap(int[] array, int a, int b) { - if(b >= this.end) return; + if (b >= this.end) + return; - if(Reads.compareIndices(array, a, b, 0.25, true) == 1) + if (Reads.compareIndices(array, a, b, 0.25, true) == 1) Writes.swap(array, a, b, 0.5, false, false); } private void rangeComp(int[] array, int a, int b, int offset) { - int half = (b-a)/2, m = a+half; + int half = (b - a) / 2, m = a + half; a += offset; - for(int i = 0; i < half - offset; i++) - if((i & ~offset) == i) this.compSwap(array, a+i, m+i); + for (int i = 0; i < half - offset; i++) + if ((i & ~offset) == i) + this.compSwap(array, a + i, m + i); } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { + @Override + public void runSort(int[] array, int currentLength, int bucketCount) { this.end = currentLength; - currentLength = 1 << (int)(Math.ceil(Math.log(currentLength)/Math.log(2))); + currentLength = 1 << (int) (Math.ceil(Math.log(currentLength) / Math.log(2))); - for(int k = 2; k <= currentLength; k*=2) - for(int j = 0; j < k/2; j++) - for(int i = 0; i+j < this.end; i+=k) - this.rangeComp(array, i, i+k, j); - } + for (int k = 2; k <= currentLength; k *= 2) + for (int j = 0; j < k / 2; j++) + for (int i = 0; i + j < this.end; i += k) + this.rangeComp(array, i, i + k, j); + } } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortParallel.java b/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortParallel.java index 096632d5..ff50b4ef 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortParallel.java @@ -4,28 +4,26 @@ import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; -@SortMeta( - listName = "Bose-Nelson (Parallel)", - showcaseName = "Parallel Bose-Nelson Sorting Network", - runName = "Parallel Bose-Nelson Sort", - unreasonableLimit = 4096 -) +@SortMeta(listName = "Bose-Nelson (Parallel)", runName = "Parallel Bose-Nelson Sorting Network", unreasonableLimit = 4096) public final class BoseNelsonSortParallel extends Sort { - public BoseNelsonSortParallel(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - } + public BoseNelsonSortParallel(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int[] array; private class BoseNelson extends Thread { private int start, length; private double sleep; + BoseNelson(int start, int length, double sleep) { this.start = start; this.length = length; this.sleep = sleep; } + + @Override public void run() { BoseNelsonSortParallel.this.boseNelson(start, length, sleep); } @@ -34,6 +32,7 @@ public void run() { private class BoseNelsonMerge extends Thread { private int start1, len1, start2, len2; private double sleep; + BoseNelsonMerge(int start1, int len1, int start2, int len2, double sleep) { this.start1 = start1; this.len1 = len1; @@ -41,66 +40,68 @@ private class BoseNelsonMerge extends Thread { this.len2 = len2; this.sleep = sleep; } + + @Override public void run() { BoseNelsonSortParallel.this.boseNelsonMerge(start1, len1, start2, len2, sleep); } } - private void compareSwap(int start, int end, double sleep) { - if (Reads.compareIndices(array, start, end, sleep, true) == 1) { - Writes.swap(array, start, end, 2*sleep, true, false); - } - } - - private void boseNelson(int start, int length, double sleep) { - if (length > 1) { - int mid = length / 2; - BoseNelson left = new BoseNelson(start, mid, sleep); - BoseNelson right = new BoseNelson(start + mid, length - mid, sleep); + private void compareSwap(int start, int end, double sleep) { + if (Reads.compareIndices(array, start, end, sleep, true) == 1) { + Writes.swap(array, start, end, 2 * sleep, true, false); + } + } + + private void boseNelson(int start, int length, double sleep) { + if (length > 1) { + int mid = length / 2; + BoseNelson left = new BoseNelson(start, mid, sleep); + BoseNelson right = new BoseNelson(start + mid, length - mid, sleep); left.start(); right.start(); try { - left.join(); - right.join(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - boseNelsonMerge(start, mid, start + mid, length - mid, sleep); - } - } - - private void boseNelsonMerge(int start1, int len1, int start2, int len2, double sleep) { - if (len1 == 1 && len2 == 1) { - compareSwap(start1, start2, sleep); - } else if (len1 == 1 && len2 == 2) { - compareSwap(start1, start2 + 1, sleep); - compareSwap(start1, start2, sleep); - } else if (len1 == 2 && len2 == 1) { - compareSwap(start1, start2, sleep); - compareSwap(start1 + 1, start2, sleep); - } else { - int mid1 = len1 / 2; - int mid2 = len1 % 2 == 1 ? len2 / 2 : (len2 + 1) / 2; - - BoseNelsonMerge left = new BoseNelsonMerge(start1, mid1, start2, mid2, sleep); - BoseNelsonMerge right = new BoseNelsonMerge(start1 + mid1, len1 - mid1, start2 + mid2, len2 - mid2, sleep); + left.join(); + right.join(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + boseNelsonMerge(start, mid, start + mid, length - mid, sleep); + } + } + + private void boseNelsonMerge(int start1, int len1, int start2, int len2, double sleep) { + if (len1 == 1 && len2 == 1) { + compareSwap(start1, start2, sleep); + } else if (len1 == 1 && len2 == 2) { + compareSwap(start1, start2 + 1, sleep); + compareSwap(start1, start2, sleep); + } else if (len1 == 2 && len2 == 1) { + compareSwap(start1, start2, sleep); + compareSwap(start1 + 1, start2, sleep); + } else { + int mid1 = len1 / 2; + int mid2 = len1 % 2 == 1 ? len2 / 2 : (len2 + 1) / 2; + + BoseNelsonMerge left = new BoseNelsonMerge(start1, mid1, start2, mid2, sleep); + BoseNelsonMerge right = new BoseNelsonMerge(start1 + mid1, len1 - mid1, start2 + mid2, len2 - mid2, sleep); left.start(); right.start(); try { - left.join(); - right.join(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - boseNelsonMerge(start1 + mid1, len1 - mid1, start2, mid2, sleep); - } - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { + left.join(); + right.join(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + boseNelsonMerge(start1 + mid1, len1 - mid1, start2, mid2, sleep); + } + } + + @Override + public void runSort(int[] array, int length, int bucketCount) { this.array = array; - this.boseNelson(0, length, 0.25); - } + this.boseNelson(0, length, 0.25); + } } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortRecursive.java b/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortRecursive.java index 7dd0f7ce..4b11474e 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/BoseNelsonSortRecursive.java @@ -4,37 +4,33 @@ import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; -@SortMeta( - listName = "Bose-Nelson (Recursive)", - showcaseName = "Recursive Bose-Nelson Sorting Network", - runName = "Recursive Bose-Nelson Sort" -) +@SortMeta(listName = "Bose-Nelson (Recursive)", runName = "Recursive Bose-Nelson Sorting Network") public final class BoseNelsonSortRecursive extends Sort { public BoseNelsonSortRecursive(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); + super(arrayVisualizer); } private void compareSwap(int[] array, int start, int end, double sleep) { - if (Reads.compareIndices(array, start, end, sleep, true) == 1) { - Writes.swap(array, start, end, 2*sleep, true, false); + if (Reads.compareIndices(array, start, end, sleep, true) == 1) { + Writes.swap(array, start, end, 2 * sleep, true, false); } } private void boseNelson(int[] array, int start, int length, double sleep) { if (length > 1) { - int mid = length / 2; - boseNelson(array, start, mid, sleep); + int mid = length / 2; + boseNelson(array, start, mid, sleep); boseNelson(array, start + mid, length - mid, sleep); boseNelsonMerge(array, start, mid, start + mid, length - mid, sleep); } } private void boseNelsonMerge(int[] array, int start1, int len1, int start2, int len2, double sleep) { - if (len1 == 1 && len2 == 1) { - compareSwap(array, start1, start2, sleep); + if (len1 == 1 && len2 == 1) { + compareSwap(array, start1, start2, sleep); } else if (len1 == 1 && len2 == 2) { - compareSwap(array, start1, start2 + 1, sleep); + compareSwap(array, start1, start2 + 1, sleep); compareSwap(array, start1, start2, sleep); } else if (len1 == 2 && len2 == 1) { compareSwap(array, start1, start2, sleep); diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/CreaseSort.java b/src/main/java/io/github/arrayv/sorts/concurrent/CreaseSort.java index 1f319319..2a7de568 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/CreaseSort.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/CreaseSort.java @@ -30,36 +30,33 @@ of this software and associated documentation files (the "Software"), to deal * */ -@SortMeta( - name = "Crease", - showcaseName = "Crease Sorting Network", - runName = "Crease Sort" -) +@SortMeta(listName = "Crease", runName = "Crease Sorting Network") public final class CreaseSort extends Sort { - public CreaseSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - } + public CreaseSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private void compSwap(int[] array, int a, int b) { - if(Reads.compareIndices(array, a, b, 0.5, true) == 1) + if (Reads.compareIndices(array, a, b, 0.5, true) == 1) Writes.swap(array, a, b, 0.5, true, false); } - @Override - public void runSort(int[] array, int length, int bucketCount) { - int max = 1; - for(; max*2 < length; max*=2); + @Override + public void runSort(int[] array, int length, int bucketCount) { + int max = 1; + for (; max * 2 < length; max *= 2) + ; - int next = max; - while(next > 0) { - for(int i = 0; i+1 < length; i+=2) - this.compSwap(array, i, i+1); + int next = max; + while (next > 0) { + for (int i = 0; i + 1 < length; i += 2) + this.compSwap(array, i, i + 1); - for(int j = max; j >= next && j > 1; j/=2) - for(int i = 1; i+j-1 < length; i+=2) - this.compSwap(array, i, i+j-1); + for (int j = max; j >= next && j > 1; j /= 2) + for (int i = 1; i + j - 1 < length; i += 2) + this.compSwap(array, i, i + j - 1); - next /= 2; - } - } + next /= 2; + } + } } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/DiamondSortIterative.java b/src/main/java/io/github/arrayv/sorts/concurrent/DiamondSortIterative.java index 1981c6a0..0ee82ccc 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/DiamondSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/DiamondSortIterative.java @@ -30,38 +30,36 @@ of this software and associated documentation files (the "Software"), to deal * */ -@SortMeta( - name = "Iterative Diamond", - listName = "Diamond (Iterative)" -) +@SortMeta(runName = "Iterative Diamond Sorting Network", listName = "Diamond (Iterative)") public final class DiamondSortIterative extends Sort { - public DiamondSortIterative(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - } + public DiamondSortIterative(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private void compSwap(int[] array, int a, int b) { - if(Reads.compareIndices(array, a, b, 0.05, true) == 1) + if (Reads.compareIndices(array, a, b, 0.05, true) == 1) Writes.swap(array, a, b, 0.05, true, false); } - @Override - public void runSort(int[] array, int length, int bucketCount) throws Exception { - int n = 1; - for(; n < length; n *= 2); + @Override + public void runSort(int[] array, int length, int bucketCount) throws Exception { + int n = 1; + for (; n < length; n *= 2) + ; int m = 4; - for(; m <= n; m *= 2) { - for(int k = 0; k < m/2; k++) { - int cnt = k <= m/4 ? k : m/2-k; - for(int j = 0; j < length; j += m) - if(j+cnt+1 < length) - for(int i = j+cnt; i+1 < Math.min(length, j+m-cnt); i += 2) - this.compSwap(array, i, i+1); + for (; m <= n; m *= 2) { + for (int k = 0; k < m / 2; k++) { + int cnt = k <= m / 4 ? k : m / 2 - k; + for (int j = 0; j < length; j += m) + if (j + cnt + 1 < length) + for (int i = j + cnt; i + 1 < Math.min(length, j + m - cnt); i += 2) + this.compSwap(array, i, i + 1); } } m /= 2; - for(int k = 0; k <= m/2; k++) - for(int i = k; i+1 < Math.min(length, m-k); i += 2) - this.compSwap(array, i, i+1); - } + for (int k = 0; k <= m / 2; k++) + for (int i = k; i + 1 < Math.min(length, m - k); i += 2) + this.compSwap(array, i, i + 1); + } } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/DiamondSortRecursive.java b/src/main/java/io/github/arrayv/sorts/concurrent/DiamondSortRecursive.java index 34eafcad..61b07874 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/DiamondSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/DiamondSortRecursive.java @@ -4,12 +4,10 @@ import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; -@SortMeta( - name = "Recursive Diamond", - listName = "Diamond (Recursive)" -) +@SortMeta(runName = "Recursive Diamond Sorting Network", listName = "Diamond (Recursive)") public final class DiamondSortRecursive extends Sort { private final double DELAY = 0.05; + public DiamondSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/FoldSort.java b/src/main/java/io/github/arrayv/sorts/concurrent/FoldSort.java index 51aeff72..599389e0 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/FoldSort.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/FoldSort.java @@ -30,11 +30,7 @@ of this software and associated documentation files (the "Software"), to deal * */ -@SortMeta( - name = "Fold", - showcaseName = "Fold Sorting Network", - runName = "Fold Sort" -) +@SortMeta(listName = "Fold", runName = "Fold Sorting Network") public final class FoldSort extends Sort { public FoldSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -42,32 +38,31 @@ public FoldSort(ArrayVisualizer arrayVisualizer) { int end; - void compSwap(int[] array, int a, int b) { - if(b < end && Reads.compareIndices(array, a, b, 0.5, true) == 1) - Writes.swap(array, a, b, 0.5, true, false); - } + void compSwap(int[] array, int a, int b) { + if (b < end && Reads.compareIndices(array, a, b, 0.5, true) == 1) + Writes.swap(array, a, b, 0.5, true, false); + } - void halver(int[] array, int low, int high) - { - while (low < high) - { + void halver(int[] array, int low, int high) { + while (low < high) { this.compSwap(array, low++, high--); } } @Override public void runSort(int[] array, int size, int bucketCount) { - int ceilLog = 1; - for (; (1 << ceilLog) < size; ceilLog++); + int ceilLog = 1; + for (; (1 << ceilLog) < size; ceilLog++) + ; - end = size; - size = 1 << ceilLog; + end = size; + size = 1 << ceilLog; - for (int k = size >> 1; k > 0; k >>= 1) //log(N) + for (int k = size >> 1; k > 0; k >>= 1) // log(N) { - for (int i = size; i >= k; i >>= 1) //log(N) + for (int i = size; i >= k; i >>= 1) // log(N) { - for (int j = 0; j < end; j += i) //N + for (int j = 0; j < end; j += i) // N { halver(array, j, j + i - 1); } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/MatrixSort.java b/src/main/java/io/github/arrayv/sorts/concurrent/MatrixSort.java index 89b13a6d..ba4da613 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/MatrixSort.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/MatrixSort.java @@ -8,10 +8,7 @@ Idea made by Control#2866 in The Studio Discord Server (https://discord.com/invite/2xGkKC2) */ -@SortMeta( - name = "Matrix", - runName = "Matrix Sort" -) +@SortMeta(name = "Matrix") public final class MatrixSort extends Sort { private class MatrixShape { int width; @@ -59,11 +56,12 @@ private boolean insertLast(int[] array, int a, int b, int gap, boolean dir) { } private MatrixShape getMatrixDims(int len) { - int dim = (int)Math.sqrt(len); + int dim = (int) Math.sqrt(len); boolean insertLast = false; if (dim * dim == len - 1) insertLast = true; - for (; len % dim != 0; dim--); + for (; len % dim != 0; dim--) + ; return new MatrixShape(dim, len / dim, insertLast); } @@ -76,8 +74,7 @@ else if (length <= 16) { did = false; for (int i = start; i < end; i += gap) did = insertLast(array, start, i, gap, dir) | did; - } - else { + } else { boolean newdid; MatrixShape matShape = getMatrixDims(length); if (matShape.insertLast) { diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/MergeExchangeSortIterative.java b/src/main/java/io/github/arrayv/sorts/concurrent/MergeExchangeSortIterative.java index e05fd9b8..2daba57e 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/MergeExchangeSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/MergeExchangeSortIterative.java @@ -4,32 +4,29 @@ import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; -@SortMeta( - listName = "Merge-Exchange (Iterative)", - showcaseName = "Batcher's Merge-Exchange Sort", - runName = "Iterative Merge-Exchange Sort" -) +@SortMeta(listName = "Merge-Exchange", runName = "Batcher's Merge-Exchange Sorting Network") public final class MergeExchangeSortIterative extends Sort { - public MergeExchangeSortIterative(ArrayVisualizer arrayVisualizer) { + public MergeExchangeSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } @Override public void runSort(int[] array, int length, int bucketCount) { - int t = (int)(Math.log(length-1) / Math.log(2))+1; + int t = (int) (Math.log(length - 1) / Math.log(2)) + 1; int p0 = 1 << (t - 1); for (int p = p0; p > 0; p >>= 1) { - int q = p0; + int q = p0; int r = 0; int d = p; while (true) { - for (int i = 0; i < length - d; i++) { - if ((i & p) == r && Reads.compareIndices(array, i, i + d, 0.5, true) == 1) { - Writes.swap(array, i, i + d, 0.5, true, false); + for (int i = 0; i < length - d; i++) { + if ((i & p) == r && Reads.compareIndices(array, i, i + d, 0.5, true) == 1) { + Writes.swap(array, i, i + d, 0.5, true, false); } } - if (q == p) break; + if (q == p) + break; d = q - p; q >>= 1; r = p; diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortIterative.java b/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortIterative.java index 49e4b1bb..1b55b937 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortIterative.java @@ -12,11 +12,7 @@ * work for array lengths other than powers of two! */ -@SortMeta( - listName = "Odd-Even Merge (Iterative)", - showcaseName = "Iterative Odd-Even Merge Sort", - runName = "Iterative Odd-Even Mergesort" -) +@SortMeta(listName = "Odd-Even Merge (Iterative)", runName = "Iterative Odd-Even Merge Sorting Network") public final class OddEvenMergeSortIterative extends Sort { public OddEvenMergeSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -28,9 +24,9 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti for (int k = p; k > 0; k /= 2) for (int j = k % p; j + k < sortLength; j += k + k) for (int i = 0; i < k; i++) - if ((i + j)/(p + p) == (i + j + k)/(p + p)) - if(i + j + k < sortLength) - if(Reads.compareIndices(array, i + j, i + j + k, 0.5, true) > 0) + if ((i + j) / (p + p) == (i + j + k) / (p + p)) + if (i + j + k < sortLength) + if (Reads.compareIndices(array, i + j, i + j + k, 0.5, true) > 0) Writes.swap(array, i + j, i + j + k, 0.5, true, false); } } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortParallel.java b/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortParallel.java index 90d78dbc..9b0a41a5 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortParallel.java @@ -31,102 +31,99 @@ of this software and associated documentation files (the "Software"), to deal * */ -@SortMeta( - name = "Parallel Odd-Even Merge", - listName = "Odd-Even Merge (Parallel)", - unreasonableLimit = 4096 -) +@SortMeta(runName = "Parallel Odd-Even Merge Sorting Network", listName = "Odd-Even Merge (Parallel)", unreasonableLimit = 4096) public final class OddEvenMergeSortParallel extends Sort { public OddEvenMergeSortParallel(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - private int[] array; + private int[] array; - private class OddEvenMerge extends Thread { + private class OddEvenMerge extends Thread { private int lo, m2, n, r; OddEvenMerge(int lo, int m2, int n, int r) { this.lo = lo; - this.m2 = m2; - this.n = n; - this.r = r; + this.m2 = m2; + this.n = n; + this.r = r; } + + @Override public void run() { OddEvenMergeSortParallel.this.oddEvenMerge(lo, m2, n, r); } } - private class OddEvenMergeSort extends Thread { + private class OddEvenMergeSort extends Thread { private int lo, n; OddEvenMergeSort(int lo, int n) { this.lo = lo; - this.n = n; + this.n = n; } + + @Override public void run() { OddEvenMergeSortParallel.this.oddEvenMergeSort(lo, n); } } - private void compSwap(int a, int b) { - if(Reads.compareIndices(array, a, b, 1, true) == 1) - Writes.swap(array, a, b, 1, true, false); - } + private void compSwap(int a, int b) { + if (Reads.compareIndices(array, a, b, 1, true) == 1) + Writes.swap(array, a, b, 1, true, false); + } - private void oddEvenMerge(int lo, int m2, int n, int r) { + private void oddEvenMerge(int lo, int m2, int n, int r) { int m = r * 2; - if(m < n) { - OddEvenMerge left, right; - - if((n/r)%2 != 0) { - left = new OddEvenMerge(lo, (m2+1)/2, n+r, m); - right = new OddEvenMerge(lo+r, m2/2, n-r, m); - } - else { - left = new OddEvenMerge(lo, (m2+1)/2, n, m); - right = new OddEvenMerge(lo+r, m2/2, n, m); + if (m < n) { + OddEvenMerge left, right; + + if ((n / r) % 2 != 0) { + left = new OddEvenMerge(lo, (m2 + 1) / 2, n + r, m); + right = new OddEvenMerge(lo + r, m2 / 2, n - r, m); + } else { + left = new OddEvenMerge(lo, (m2 + 1) / 2, n, m); + right = new OddEvenMerge(lo + r, m2 / 2, n, m); } - left.start(); - right.start(); + left.start(); + right.start(); - try { + try { left.join(); right.join(); - } - catch(InterruptedException e) { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); - } + } - if(m2%2 != 0) - for(int i = lo; i + r < lo + n; i += m) + if (m2 % 2 != 0) + for (int i = lo; i + r < lo + n; i += m) this.compSwap(i, i + r); else - for(int i = lo + r; i + r < lo + n; i += m) + for (int i = lo + r; i + r < lo + n; i += m) this.compSwap(i, i + r); - } - else if(n > r) this.compSwap(lo, lo+r); + } else if (n > r) + this.compSwap(lo, lo + r); } private void oddEvenMergeSort(int lo, int n) { if (n > 1) { int m = n / 2; - OddEvenMergeSort left = new OddEvenMergeSort(lo, m); - OddEvenMergeSort right = new OddEvenMergeSort(lo + m, n-m); + OddEvenMergeSort left = new OddEvenMergeSort(lo, m); + OddEvenMergeSort right = new OddEvenMergeSort(lo + m, n - m); - left.start(); - right.start(); + left.start(); + right.start(); - try { + try { left.join(); right.join(); - } - catch(InterruptedException e) { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); - } + } this.oddEvenMerge(lo, m, n, 1); } @@ -134,7 +131,7 @@ private void oddEvenMergeSort(int lo, int n) { @Override public void runSort(int[] array, int length, int bucketCount) { - this.array = array; - this.oddEvenMergeSort(0, length); + this.array = array; + this.oddEvenMergeSort(0, length); } } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortRecursive.java b/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortRecursive.java index 43d88055..162ead83 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/OddEvenMergeSortRecursive.java @@ -12,11 +12,7 @@ * work for array lengths other than powers of two! */ -@SortMeta( - name = "Recursive Odd-Even Merge", - listName = "Odd-Even Merge (Recursive)", - showcaseName = "Batcher's Odd-Even Merge Sort" -) +@SortMeta(runName = "Recursive Odd-Even Merge Sorting Network", listName = "Odd-Even Merge (Recursive)") public final class OddEvenMergeSortRecursive extends Sort { public OddEvenMergeSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -27,37 +23,35 @@ private void oddEvenMergeCompare(int[] array, int i, int j) { Writes.swap(array, i, j, 0.5, true, false); } - /** lo is the starting position, - * m2 is the halfway point, and - * n is the length of the piece to be merged, - * r is the distance of the elements to be compared + /** + * lo is the starting position, + * m2 is the halfway point, and + * n is the length of the piece to be merged, + * r is the distance of the elements to be compared */ private void oddEvenMerge(int[] array, int lo, int m2, int n, int r) { int m = r * 2; if (m < n) { - if((n/r)%2 != 0){ - oddEvenMerge(array, lo, (m2+1)/2, n+r, m); // even subsequence - oddEvenMerge(array, lo+r, m2/2, n-r, m); // odd subsequence - } - else{ - oddEvenMerge(array, lo, (m2+1)/2, n, m); // even subsequence - oddEvenMerge(array, lo+r, m2/2, n, m); // odd subsequence + if ((n / r) % 2 != 0) { + oddEvenMerge(array, lo, (m2 + 1) / 2, n + r, m); // even subsequence + oddEvenMerge(array, lo + r, m2 / 2, n - r, m); // odd subsequence + } else { + oddEvenMerge(array, lo, (m2 + 1) / 2, n, m); // even subsequence + oddEvenMerge(array, lo + r, m2 / 2, n, m); // odd subsequence } - if(m2%2 != 0){ + if (m2 % 2 != 0) { for (int i = lo; i + r < lo + n; i += m) { oddEvenMergeCompare(array, i, i + r); } - } - else{ + } else { for (int i = lo + r; i + r < lo + n; i += m) { oddEvenMergeCompare(array, i, i + r); } } - } - else { - if(n > r){ - oddEvenMergeCompare(array, lo, lo+r); + } else { + if (n > r) { + oddEvenMergeCompare(array, lo, lo + r); } } } @@ -66,7 +60,7 @@ void oddEvenMergeSort(int[] array, int lo, int n) { if (n > 1) { int m = n / 2; oddEvenMergeSort(array, lo, m); - oddEvenMergeSort(array, lo + m, n-m); + oddEvenMergeSort(array, lo + m, n - m); oddEvenMerge(array, lo, m, n, 1); } } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseMergeSortIterative.java b/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseMergeSortIterative.java index 3f7242b7..b9fcef5e 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseMergeSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseMergeSortIterative.java @@ -30,38 +30,36 @@ of this software and associated documentation files (the "Software"), to deal * */ -@SortMeta( - name = "Iterative Pairwise Merge", - listName = "Pairwise Merge (Iterative)" -) +@SortMeta(runName = "Iterative Pairwise Merge Sorting Network", listName = "Pairwise Merge (Iterative)") public final class PairwiseMergeSortIterative extends Sort { - public PairwiseMergeSortIterative(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - } + public PairwiseMergeSortIterative(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int end; private void compSwap(int[] array, int a, int b) { - if(b < this.end && Reads.compareIndices(array, a, b, 0.5, true) == 1) + if (b < this.end && Reads.compareIndices(array, a, b, 0.5, true) == 1) Writes.swap(array, a, b, 0.5, true, false); } - @Override - public void runSort(int[] array, int length, int bucketCount) throws Exception { - this.end = length; - int n = 1; - for(; n < length; n <<= 1); + @Override + public void runSort(int[] array, int length, int bucketCount) throws Exception { + this.end = length; + int n = 1; + for (; n < length; n <<= 1) + ; - for(int k = n >> 1; k > 0; k >>= 1) - for(int j = 0; j < length; j += k << 1) - for(int i = 0; i < k; i++) - this.compSwap(array, j+i, j+k+i); + for (int k = n >> 1; k > 0; k >>= 1) + for (int j = 0; j < length; j += k << 1) + for (int i = 0; i < k; i++) + this.compSwap(array, j + i, j + k + i); - for(int k = 2; k < n; k <<= 1) - for(int m = k >> 1; m > 0; m >>= 1) - for(int j = 0; j < length; j += k<<1) - for(int p = m; p < ((k-m)<<1); p += m<<1) - for(int i = 0; i < m; i++) - this.compSwap(array, j+p+i, j+p+m+i); - } + for (int k = 2; k < n; k <<= 1) + for (int m = k >> 1; m > 0; m >>= 1) + for (int j = 0; j < length; j += k << 1) + for (int p = m; p < ((k - m) << 1); p += m << 1) + for (int i = 0; i < m; i++) + this.compSwap(array, j + p + i, j + p + m + i); + } } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseMergeSortRecursive.java b/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseMergeSortRecursive.java index 5b83d33b..2656cf9d 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseMergeSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseMergeSortRecursive.java @@ -30,51 +30,50 @@ of this software and associated documentation files (the "Software"), to deal * */ -@SortMeta( - name = "Recursive Pairwise Merge", - listName = "Pairwise Merge (Recursive)" -) +@SortMeta(runName = "Recursive Pairwise Merge Sorting Network", listName = "Pairwise Merge (Recursive)") public final class PairwiseMergeSortRecursive extends Sort { - public PairwiseMergeSortRecursive(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - } + public PairwiseMergeSortRecursive(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int end; private void compSwap(int[] array, int a, int b) { - if(b < this.end && Reads.compareIndices(array, a, b, 0.5, true) == 1) + if (b < this.end && Reads.compareIndices(array, a, b, 0.5, true) == 1) Writes.swap(array, a, b, 0.5, true, false); } private void pairwiseMerge(int[] array, int a, int b) { - int m = (a+b)/2, m1 = (a+m)/2, g = m-m1; + int m = (a + b) / 2, m1 = (a + m) / 2, g = m - m1; - for(int i = 0; m1+i < m; i++) - for(int j = m1, k = g; k > 0; k >>= 1, j -= k-(i&k)) - this.compSwap(array, j+i, j+i+k); + for (int i = 0; m1 + i < m; i++) + for (int j = m1, k = g; k > 0; k >>= 1, j -= k - (i & k)) + this.compSwap(array, j + i, j + i + k); - if(b-a > 4) this.pairwiseMerge(array, m, b); + if (b - a > 4) + this.pairwiseMerge(array, m, b); } private void pairwiseMergeSort(int[] array, int a, int b) { - int m = (a+b)/2; + int m = (a + b) / 2; - for(int i = a, j = m; i < m; i++, j++) + for (int i = a, j = m; i < m; i++, j++) this.compSwap(array, i, j); - if(b-a > 2) { + if (b - a > 2) { this.pairwiseMergeSort(array, a, m); this.pairwiseMergeSort(array, m, b); this.pairwiseMerge(array, a, b); } } - @Override - public void runSort(int[] array, int length, int bucketCount) throws Exception { - this.end = length; - int n = 1; - for(; n < length; n <<= 1); + @Override + public void runSort(int[] array, int length, int bucketCount) throws Exception { + this.end = length; + int n = 1; + for (; n < length; n <<= 1) + ; this.pairwiseMergeSort(array, 0, n); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseSortIterative.java b/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseSortIterative.java index 88e3be29..01f27292 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseSortIterative.java @@ -26,11 +26,7 @@ of this software and associated documentation files (the "Software"), to deal * */ -@SortMeta( - listName = "Pairwise (Iterative)", - showcaseName = "Iterative Pairwise Sorting Network", - runName = "Iterative Pairwise Sort" -) +@SortMeta(listName = "Pairwise (Iterative)", runName = "Iterative Pairwise Sorting Network") public final class PairwiseSortIterative extends Sort { public PairwiseSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -42,16 +38,16 @@ private void iterativepairwise(int[] array, int length, double sleep) { int c = 0; int d = 0; int e = 0; - while (a < length){ + while (a < length) { b = a; c = 0; - while (b < length){ - if(Reads.compareIndices(array, b - a, b, sleep, true) == 1) { + while (b < length) { + if (Reads.compareIndices(array, b - a, b, sleep, true) == 1) { Writes.swap(array, b - a, b, sleep, true, false); } c = (c + 1) % a; b++; - if (c == 0){ + if (c == 0) { b += a; } } @@ -59,18 +55,18 @@ private void iterativepairwise(int[] array, int length, double sleep) { } a /= 4; e = 1; - while (a > 0){ + while (a > 0) { d = e; - while (d > 0){ + while (d > 0) { b = ((d + 1) * a); c = 0; - while (b < length){ - if(Reads.compareIndices(array, b - (d * a), b, sleep, true) == 1) { + while (b < length) { + if (Reads.compareIndices(array, b - (d * a), b, sleep, true) == 1) { Writes.swap(array, b - (d * a), b, sleep, true, false); } c = (c + 1) % a; b++; - if (c == 0){ + if (c == 0) { b += a; } } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseSortRecursive.java b/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseSortRecursive.java index abea1eb3..ea84c8ea 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/PairwiseSortRecursive.java @@ -26,46 +26,41 @@ of this software and associated documentation files (the "Software"), to deal * */ -@SortMeta( - listName = "Pairwise (Recursive)", - showcaseName = "Recursive Pairwise Sorting Network", - runName = "Recursive Pairwise Sort" -) +@SortMeta(listName = "Pairwise (Recursive)", runName = "Recursive Pairwise Sorting Network") public final class PairwiseSortRecursive extends Sort { public PairwiseSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } private void pairwiserecursive(int[] array, int start, int end, int gap, double sleep) { - if (start == end - gap){ + if (start == end - gap) { return; } int b = start + gap; - while (b < end){ - if(Reads.compareIndices(array, b - gap, b, sleep, true) == 1) { + while (b < end) { + if (Reads.compareIndices(array, b - gap, b, sleep, true) == 1) { Writes.swap(array, b - gap, b, sleep, true, false); } b += (2 * gap); } - if (((end - start) / gap)%2 == 0){ + if (((end - start) / gap) % 2 == 0) { this.pairwiserecursive(array, start, end, gap * 2, sleep); this.pairwiserecursive(array, start + gap, end + gap, gap * 2, sleep); - } - else{ + } else { this.pairwiserecursive(array, start, end + gap, gap * 2, sleep); this.pairwiserecursive(array, start + gap, end, gap * 2, sleep); } int a = 1; - while (a < ((end - start) / gap)){ + while (a < ((end - start) / gap)) { a = (a * 2) + 1; } b = start + gap; - while (b + gap < end){ + while (b + gap < end) { int c = a; - while (c > 1){ + while (c > 1) { c /= 2; - if (b + (c * gap) < end){ - if(Reads.compareIndices(array, b, b + (c * gap), sleep, true) == 1) { + if (b + (c * gap) < end) { + if (Reads.compareIndices(array, b, b + (c * gap), sleep, true) == 1) { Writes.swap(array, b, b + (c * gap), sleep, true, false); } } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortIterative.java b/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortIterative.java index bd514602..19475fb5 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortIterative.java @@ -30,34 +30,31 @@ of this software and associated documentation files (the "Software"), to deal * */ -@SortMeta( - listName = "Weave (Iterative)", - showcaseName = "Iterative Weave Sorting Network", - runName = "Iterative Weave Sort" -) +@SortMeta(listName = "Weave (Iterative)", runName = "Iterative Weave Sorting Network") public final class WeaveSortIterative extends Sort { - public WeaveSortIterative(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - } + public WeaveSortIterative(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } - private int end; + private int end; private void compSwap(int[] array, int a, int b) { - if(b < this.end && Reads.compareIndices(array, a, b, 0.5, true) == 1) + if (b < this.end && Reads.compareIndices(array, a, b, 0.5, true) == 1) Writes.swap(array, a, b, 0.5, true, false); } - @Override - public void runSort(int[] array, int length, int bucketCount) { - this.end = length; - int n = 1; - for(; n < length; n*=2); - - for(int i = 1; i < n; i*=2) - for(int j = 1; j <= i; j*=2) - for(int k = 0; k < n; k += n/j) - for(int d = n/i/2, m = 0, l = n/j-d; l >= n/j/2; l-=d) - for(int p = 0; p < d; p++, m++) - this.compSwap(array, k+m, k+l+p); - } + @Override + public void runSort(int[] array, int length, int bucketCount) { + this.end = length; + int n = 1; + for (; n < length; n *= 2) + ; + + for (int i = 1; i < n; i *= 2) + for (int j = 1; j <= i; j *= 2) + for (int k = 0; k < n; k += n / j) + for (int d = n / i / 2, m = 0, l = n / j - d; l >= n / j / 2; l -= d) + for (int p = 0; p < d; p++, m++) + this.compSwap(array, k + m, k + l + p); + } } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortParallel.java b/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortParallel.java index 1d9b6243..2162968c 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortParallel.java @@ -4,26 +4,25 @@ import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; -@SortMeta( - name = "Parallel Weave", - listName = "Iterative Weave Sort", - runName = "Parallel Weave Sort", - unreasonableLimit = 4096 -) +@SortMeta(listName = "Weave (Parallel)", runName = "Parallel Weave Sorting Network", unreasonableLimit = 4096) public final class WeaveSortParallel extends Sort { private int[] arr; private int length; private double DELAY = 1; + public WeaveSortParallel(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } private class SortThread extends Thread { private int start, gap; + SortThread(int start, int gap) { this.start = start; this.gap = gap; } + + @Override public void run() { WeaveSortParallel.this.wrapper(this.start, this.gap); } @@ -31,11 +30,14 @@ public void run() { private class CircleThread extends Thread { private int start, stop, gap; + CircleThread(int start, int stop, int gap) { this.start = start; this.stop = stop; this.gap = gap; } + + @Override public void run() { WeaveSortParallel.this.circle(this.start, this.stop, this.gap); } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortRecursive.java b/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortRecursive.java index 5e3083f6..1cde7e56 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/WeaveSortRecursive.java @@ -30,48 +30,48 @@ of this software and associated documentation files (the "Software"), to deal * */ -@SortMeta( - listName = "Weave (Recursive)", - showcaseName = "Recursive Weave Sorting Network", - runName = "Recursive Weave Sort" -) +@SortMeta(listName = "Weave (Recursive)", runName = "Recursive Weave Sorting Network") public final class WeaveSortRecursive extends Sort { - public WeaveSortRecursive(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - } + public WeaveSortRecursive(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } - private int end; + private int end; private void compSwap(int[] array, int a, int b) { - if(b < this.end && Reads.compareIndices(array, a, b, 0.5, true) == 1) + if (b < this.end && Reads.compareIndices(array, a, b, 0.5, true) == 1) Writes.swap(array, a, b, 0.5, true, false); } private void circle(int[] array, int pos, int len, int gap) { - if(len < 2) return; + if (len < 2) + return; - for(int i = 0; 2*i < (len-1)*gap; i+=gap) - this.compSwap(array, pos+i, pos+(len-1)*gap-i); + for (int i = 0; 2 * i < (len - 1) * gap; i += gap) + this.compSwap(array, pos + i, pos + (len - 1) * gap - i); - this.circle(array, pos, len/2, gap); - if(pos+len*gap/2 < this.end) this.circle(array, pos+len*gap/2, len/2, gap); + this.circle(array, pos, len / 2, gap); + if (pos + len * gap / 2 < this.end) + this.circle(array, pos + len * gap / 2, len / 2, gap); } private void weaveCircle(int[] array, int pos, int len, int gap) { - if(len < 2) return; + if (len < 2) + return; - this.weaveCircle(array, pos, len/2, 2*gap); - this.weaveCircle(array, pos+gap, len/2, 2*gap); + this.weaveCircle(array, pos, len / 2, 2 * gap); + this.weaveCircle(array, pos + gap, len / 2, 2 * gap); this.circle(array, pos, len, gap); } - @Override - public void runSort(int[] array, int length, int bucketCount) { - this.end = length; - int n = 1; - for(; n < length; n*=2); + @Override + public void runSort(int[] array, int length, int bucketCount) { + this.end = length; + int n = 1; + for (; n < length; n *= 2) + ; this.weaveCircle(array, 0, n, 1); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/concurrent/package-info.java b/src/main/java/io/github/arrayv/sorts/concurrent/package-info.java index 953c9ea8..958d39a8 100644 --- a/src/main/java/io/github/arrayv/sorts/concurrent/package-info.java +++ b/src/main/java/io/github/arrayv/sorts/concurrent/package-info.java @@ -1,4 +1,2 @@ -@io.github.arrayv.sortdata.SortPackageMeta( - category = "Concurrent Sorts" -) +@io.github.arrayv.sortdata.SortPackageMeta(category = "Concurrent Sorts") package io.github.arrayv.sorts.concurrent; diff --git a/src/main/java/io/github/arrayv/sorts/distribute/AmericanFlagSort.java b/src/main/java/io/github/arrayv/sorts/distribute/AmericanFlagSort.java index 4d6c347e..05b5a12b 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/AmericanFlagSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/AmericanFlagSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -42,114 +43,105 @@ *
* @author Justin Wetherell */ - +@SortMeta(name = "American Flag", bucketSort = true, radixSort = true) public final class AmericanFlagSort extends Sort { - private int NUMBER_OF_BUCKETS = 128; // ex. 10 for base 10 numbers - - public AmericanFlagSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("American Flag"); - this.setRunAllSortsName("American Flag Sort, " + this.NUMBER_OF_BUCKETS + " Buckets"); - this.setRunSortName("American Flag Sort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(true); - this.setRadixSort(true); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - // Slightly different than Reads.analyzeMaxLog. - private int getMaxNumberOfDigits(int[] array, int length) { - int max = Integer.MIN_VALUE; - int temp = 0; - - for (int i = 0; i < length; i++) { - temp = (int) (Math.log(array[i]) / Math.log(this.NUMBER_OF_BUCKETS)) + 1; - - if (temp > max) - max = temp; - } - return max; - } + private int NUMBER_OF_BUCKETS = 128; // ex. 10 for base 10 numbers + + public AmericanFlagSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } - private int getDigit(int integer, int divisor) { - return (integer / divisor) % this.NUMBER_OF_BUCKETS; + // Slightly different than Reads.analyzeMaxLog. + private int getMaxNumberOfDigits(int[] array, int length) { + int max = Integer.MIN_VALUE; + int temp = 0; + + for (int i = 0; i < length; i++) { + temp = (int) (Math.log(array[i]) / Math.log(this.NUMBER_OF_BUCKETS)) + 1; + + if (temp > max) + max = temp; } + return max; + } - private void sort(int[] array, int start, int length, int divisor) { - // First pass - find counts - int[] count = new int[this.NUMBER_OF_BUCKETS]; - int[] offset = new int[this.NUMBER_OF_BUCKETS]; - Writes.changeAllocAmount(2 * this.NUMBER_OF_BUCKETS); - int digit = 0; + private int getDigit(int integer, int divisor) { + return (integer / divisor) % this.NUMBER_OF_BUCKETS; + } - for (int i = start; i < length; i++) { - Highlights.markArray(1, i); - Delays.sleep(0.75); + private void sort(int[] array, int start, int length, int divisor) { + // First pass - find counts + int[] count = new int[this.NUMBER_OF_BUCKETS]; + int[] offset = new int[this.NUMBER_OF_BUCKETS]; + Writes.changeAllocAmount(2 * this.NUMBER_OF_BUCKETS); + int digit = 0; - int d = array[i]; - digit = this.getDigit(d, divisor); + for (int i = start; i < length; i++) { + Highlights.markArray(1, i); + Delays.sleep(0.75); - Writes.write(count, digit, count[digit] + 1, 0, false, true); - } + int d = array[i]; + digit = this.getDigit(d, divisor); - Writes.write(offset, 0, start + 0, 0, false, true); + Writes.write(count, digit, count[digit] + 1, 0, false, true); + } - for (int i = 1; i < this.NUMBER_OF_BUCKETS; i++) { - Writes.write(offset, i, count[i - 1] + offset[i - 1], 0, false, true); - } + Writes.write(offset, 0, start + 0, 0, false, true); + + for (int i = 1; i < this.NUMBER_OF_BUCKETS; i++) { + Writes.write(offset, i, count[i - 1] + offset[i - 1], 0, false, true); + } - // Second pass - move into position - for (int b = 0; b < this.NUMBER_OF_BUCKETS; b++) { - while (count[b] > 0) { - int origin = offset[b]; - int from = origin; - int num = array[from]; + // Second pass - move into position + for (int b = 0; b < this.NUMBER_OF_BUCKETS; b++) { + while (count[b] > 0) { + int origin = offset[b]; + int from = origin; + int num = array[from]; - Writes.visualClear(array, from, 0.5); + Writes.visualClear(array, from, 0.5); - do { - digit = this.getDigit(num, divisor); - int to = offset[digit]; + do { + digit = this.getDigit(num, divisor); + int to = offset[digit]; - Writes.write(offset, digit, offset[digit] + 1, 0, false, true); - Writes.write(count, digit, count[digit] - 1, 0, false, true); + Writes.write(offset, digit, offset[digit] + 1, 0, false, true); + Writes.write(count, digit, count[digit] - 1, 0, false, true); - int temp = array[to]; - Writes.write(array, to, num, 0.75, true, false); + int temp = array[to]; + Writes.write(array, to, num, 0.75, true, false); - num = temp; - from = to; - } while (from != origin); - } + num = temp; + from = to; + } while (from != origin); } - if (divisor > 1) { - // Sort the buckets - for (int i = 0; i < this.NUMBER_OF_BUCKETS; i++) { - int begin = (i > 0) ? offset[i - 1] : start; - int end = offset[i]; - - if (end - begin > 1) - this.sort(array, begin, end, divisor / this.NUMBER_OF_BUCKETS); - } + } + if (divisor > 1) { + // Sort the buckets + for (int i = 0; i < this.NUMBER_OF_BUCKETS; i++) { + int begin = (i > 0) ? offset[i - 1] : start; + int end = offset[i]; + + if (end - begin > 1) + this.sort(array, begin, end, divisor / this.NUMBER_OF_BUCKETS); } - - Writes.changeAllocAmount(-2 * this.NUMBER_OF_BUCKETS); } - @Override - public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - this.NUMBER_OF_BUCKETS = bucketCount; - this.setRunAllSortsName("American Flag Sort, " + this.NUMBER_OF_BUCKETS + " Buckets"); + Writes.changeAllocAmount(-2 * this.NUMBER_OF_BUCKETS); + } - int numberOfDigits = this.getMaxNumberOfDigits(array, sortLength); // Max number of digits - int max = 1; + @Override + public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { + this.NUMBER_OF_BUCKETS = bucketCount; + this.setRunAllSortsName("American Flag Sort, " + this.NUMBER_OF_BUCKETS + " Buckets"); + this.setRunSortName("American Flag Sort, " + this.NUMBER_OF_BUCKETS + " Buckets"); - for (int i = 0; i < numberOfDigits - 1; i++) - max *= this.NUMBER_OF_BUCKETS; + int numberOfDigits = this.getMaxNumberOfDigits(array, sortLength); // Max number of digits + int max = 1; - this.sort(array, 0, sortLength, max); - } - } + for (int i = 0; i < numberOfDigits - 1; i++) + max *= this.NUMBER_OF_BUCKETS; + + this.sort(array, 0, sortLength, max); + } +} diff --git a/src/main/java/io/github/arrayv/sorts/distribute/BinaryQuickSortIterative.java b/src/main/java/io/github/arrayv/sorts/distribute/BinaryQuickSortIterative.java index d24ffa7d..5fef8e2c 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/BinaryQuickSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/BinaryQuickSortIterative.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BinaryQuickSorting; /** @@ -19,20 +20,10 @@ * * @author Skeen */ - +@SortMeta(listName = "Binary Quick (Iterative)", runName = "Iterative Binary Quick Sort") public final class BinaryQuickSortIterative extends BinaryQuickSorting { public BinaryQuickSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Binary Quick (Iterative with a Queue)"); - this.setRunAllSortsName("Iterative Binary Quick Sort"); - this.setRunSortName("Iterative Binary Quicksort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/distribute/BinaryQuickSortRecursive.java b/src/main/java/io/github/arrayv/sorts/distribute/BinaryQuickSortRecursive.java index be850059..0c790036 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/BinaryQuickSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/BinaryQuickSortRecursive.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BinaryQuickSorting; /** @@ -19,20 +20,10 @@ * * @author Skeen */ - +@SortMeta(listName = "Binary Quick (Recursive)", runName = "Recursive Binary Quick Sort") public final class BinaryQuickSortRecursive extends BinaryQuickSorting { public BinaryQuickSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Binary Quick (Recursive)"); - this.setRunAllSortsName("Recursive Binary Quick Sort"); - this.setRunSortName("Recursive Binary Quicksort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/distribute/ClassicGravitySort.java b/src/main/java/io/github/arrayv/sorts/distribute/ClassicGravitySort.java index 514d63f9..3e67843a 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/ClassicGravitySort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/ClassicGravitySort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,24 +29,14 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Classic Gravity (Bead)") public final class ClassicGravitySort extends Sort { - public ClassicGravitySort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Classic Gravity"); - this.setRunAllSortsName("Classic Gravity (Bead) Sort"); - this.setRunSortName("Classic Beadsort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public ClassicGravitySort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { int max = Reads.analyzeMax(array, length, 0.5, true); int[] transpose = Writes.createExternalArray(max); @@ -73,5 +64,5 @@ public void runSort(int[] array, int length, int bucketCount) { } Writes.deleteExternalArray(transpose); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/CountingSort.java b/src/main/java/io/github/arrayv/sorts/distribute/CountingSort.java index c083a785..2120d601 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/CountingSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/CountingSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,20 +29,10 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Counting") public final class CountingSort extends Sort { public CountingSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Counting"); - this.setRunAllSortsName("Counting Sort"); - this.setRunSortName("Counting Sort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/distribute/FlashSort.java b/src/main/java/io/github/arrayv/sorts/distribute/FlashSort.java index 47c1bb5b..067bc15c 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/FlashSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/FlashSort.java @@ -3,93 +3,73 @@ import java.util.Arrays; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.InsertionSort; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Flash") public final class FlashSort extends Sort { public FlashSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Flash"); - this.setRunAllSortsName("Flash Sort"); - this.setRunSortName("Flashsort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - // The flashsort algorithm is attributed to Karl-Dietrich Neubert - // The translation to C++ is provided by Clint Jed Casper - // Refactored in Java by MusicTheorist - // - // sorts an array in place in O(n) time using 20% of the - // memory used by the array for storing intermediate, - // temporary computations + // The flashsort algorithm is attributed to Karl-Dietrich Neubert + // The translation to C++ is provided by Clint Jed Casper + // Refactored in Java by MusicTheorist + // + // sorts an array in place in O(n) time using 20% of the + // memory used by the array for storing intermediate, + // temporary computations - @Override + @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - if(sortLength == 0) return; + if (sortLength == 0) + return; - //20% of the number of elements or 0.2n classes will - //be used to distribute the input data set into - //there must be at least 2 classes (hence the addition) - int m = (int)((0.2 * sortLength) + 2); + // 20% of the number of elements or 0.2n classes will + // be used to distribute the input data set into + // there must be at least 2 classes (hence the addition) + int m = (int) ((0.2 * sortLength) + 2); - //-------CLASS FORMATION------- + // -------CLASS FORMATION------- - //O(n) - //compute the max and min values of the input data + // O(n) + // compute the max and min values of the input data int min, max, maxIndex; min = max = array[0]; maxIndex = 0; - for(int i = 1; i < sortLength - 1; i += 2) - { + for (int i = 1; i < sortLength - 1; i += 2) { int small; int big; int bigIndex; - Highlights.markArray(1, i); - - //which is bigger A(i) or A(i+1) - if(Reads.compareValues(array[i], array[i + 1]) == -1) - { + // which is bigger A(i) or A(i+1) + if (Reads.compareIndices(array, i, i + 1, 1, true) == -1) { small = array[i]; big = array[i + 1]; bigIndex = i + 1; - } - else - { + } else { big = array[i]; bigIndex = i; small = array[i + 1]; } - if(big > max) - { + if (big > max) { max = big; maxIndex = bigIndex; } - if(small < min) - { + if (small < min) { min = small; } - - Delays.sleep(1); } - //do the last element + // do the last element Highlights.markArray(1, sortLength - 1); - if(Reads.compareValues(array[sortLength - 1], min) == -1) - { + if (Reads.compareValues(array[sortLength - 1], min) == -1) { min = array[sortLength - 1]; - } - else if(Reads.compareValues(array[sortLength - 1], max) == 1) - { + } else if (Reads.compareValues(array[sortLength - 1], max) == 1) { max = array[sortLength - 1]; maxIndex = sortLength - 1; } @@ -97,180 +77,171 @@ else if(Reads.compareValues(array[sortLength - 1], max) == 1) Delays.sleep(1); Highlights.clearMark(1); - if(max == min) - { - //all the elements are the same + if (max == min) { + // all the elements are the same return; } - //dynamically allocate the storage for L - //note that L is in the range 1...m (hence - //the extra 1) + // dynamically allocate the storage for L + // note that L is in the range 1...m (hence + // the extra 1) int[] L = Writes.createExternalArray(m + 1); - //O(m) - //initialize L to contain all zeros (L[0] is unused) - for(int t = 1; t <= m; t++) - { + // O(m) + // initialize L to contain all zeros (L[0] is unused) + for (int t = 1; t <= m; t++) { Writes.write(L, t, 0, 0, false, true); } - //O(n) - //use the function K(A(i)) = 1 + INT((m-1)(A(i)-Amin)/(Amax-Amin)) - //to classify each A(i) into a number from 1...m - //(note that this is mainly just a percentage calculation) - //and then store a count of each distinct class K in L(K) - //For instance, if there are 22 A(i) values that fall into class - //K == 5 then the count in L(5) would be 22 + // O(n) + // use the function K(A(i)) = 1 + INT((m-1)(A(i)-Amin)/(Amax-Amin)) + // to classify each A(i) into a number from 1...m + // (note that this is mainly just a percentage calculation) + // and then store a count of each distinct class K in L(K) + // For instance, if there are 22 A(i) values that fall into class + // K == 5 then the count in L(5) would be 22 - //IMPORTANT: note that the class K == m only has elements equal to Amax + // IMPORTANT: note that the class K == m only has elements equal to Amax - //precomputed constant + // precomputed constant double c = (m - 1.0) / (max - min); int K; - for(int h = 0; h < sortLength; h++) - { + for (int h = 0; h < sortLength; h++) { Highlights.markArray(1, h); - //classify the A(i) value - K = ((int)((array[h] - min) * c)) + 1; + // classify the A(i) value + K = ((int) ((array[h] - min) * c)) + 1; - //add one to the count for this class + // add one to the count for this class Writes.write(L, K, L[K] + 1, 1, false, true); } Highlights.clearMark(1); - //O(m) - //sum over each L(i) such that each L(i) contains - //the number of A(i) values that are in the ith - //class or lower (see counting sort for more details) - for(K = 2; K <= m; K++) - { + // O(m) + // sum over each L(i) such that each L(i) contains + // the number of A(i) values that are in the ith + // class or lower (see counting sort for more details) + for (K = 2; K <= m; K++) { Writes.write(L, K, L[K] + L[K - 1], 0, false, true); } - //-------PERMUTATION------- + // -------PERMUTATION------- - //swap the max value with the first value in the array + // swap the max value with the first value in the array Writes.swap(array, maxIndex, 0, 1, true, false); Highlights.clearMark(1); Highlights.clearMark(2); - //Except when being iterated upwards, - //j always points to the first A(i) that starts - //a new class boundary && that class hasn't yet - //had all of its elements moved inside its borders; - - //This is called a cycle leader since you know - //that you can begin permuting again here. You know - //this because it is the lowest index of the class - //and as such A(j) must be out of place or else all - //the elements of this class have already been placed - //within the borders of the this class (which means - //j wouldn't be pointing to this A(i) in the first place) + // Except when being iterated upwards, + // j always points to the first A(i) that starts + // a new class boundary && that class hasn't yet + // had all of its elements moved inside its borders; + + // This is called a cycle leader since you know + // that you can begin permuting again here. You know + // this because it is the lowest index of the class + // and as such A(j) must be out of place or else all + // the elements of this class have already been placed + // within the borders of the this class (which means + // j wouldn't be pointing to this A(i) in the first place) int j = 0; - //K is the class of an A(i) value. It is always in the range 1..m + // K is the class of an A(i) value. It is always in the range 1..m K = m; - //the number of elements that have been moved - //into their correct class + // the number of elements that have been moved + // into their correct class int numMoves = 0; - //O(n) - //permute elements into their correct class; each - //time the class that j is pointing to fills up - //then iterate j to the next cycle leader + // O(n) + // permute elements into their correct class; each + // time the class that j is pointing to fills up + // then iterate j to the next cycle leader // - //do not use the n - 1 optimization because that last element - //will not have its count decreased (this causes trouble with - //determining the correct classSize in the last step) - while(numMoves < sortLength) - { - //if j does not point to the beginning of a class - //that has at least 1 element still needing to be - //moved to within the borders of the class then iterate - //j upward until such a class is found (such a class - //must exist). In other words, find the next cycle leader - while(j >= L[K]) - { + // do not use the n - 1 optimization because that last element + // will not have its count decreased (this causes trouble with + // determining the correct classSize in the last step) + while (numMoves < sortLength) { + // if j does not point to the beginning of a class + // that has at least 1 element still needing to be + // moved to within the borders of the class then iterate + // j upward until such a class is found (such a class + // must exist). In other words, find the next cycle leader + while (j >= L[K]) { j++; - //classify the A(j) value - K = ((int)((array[j] - min) * c)) + 1; + // classify the A(j) value + K = ((int) ((array[j] - min) * c)) + 1; } - //evicted always holds the value of an element whose location - //in the array is free to be written into //aka FLASH + // evicted always holds the value of an element whose location + // in the array is free to be written into //aka FLASH int evicted = array[j]; - //while j continues to meet the condition that it is - //pointing to the start of a class that has at least one - //element still outside its borders (the class isn't full) - while(j < L[K]) - { - //compute the class of the evicted value - K = ((int)((evicted - min) * c)) + 1; + // while j continues to meet the condition that it is + // pointing to the start of a class that has at least one + // element still outside its borders (the class isn't full) + while (j < L[K]) { + // compute the class of the evicted value + K = ((int) ((evicted - min) * c)) + 1; - //get a location that is inside the evicted - //element's class boundaries + // get a location that is inside the evicted + // element's class boundaries int location = L[K] - 1; - //swap the value currently residing at the new - //location with the evicted value + // swap the value currently residing at the new + // location with the evicted value int temp = array[location]; Writes.write(array, location, evicted, 1, false, false); Highlights.markArray(1, location); evicted = temp; - //decrease the count for this class - //see counting sort for why this is done + // decrease the count for this class + // see counting sort for why this is done Writes.write(L, K, L[K] - 1, 0, false, true); - //another element was moved + // another element was moved numMoves++; } } Highlights.clearMark(1); - //-------RECURSION or STRAIGHT INSERTION------- + // -------RECURSION or STRAIGHT INSERTION------- - //if the classes do not have the A(i) values uniformly distributed - //into each of them then insertion sort will not produce O(n) results; + // if the classes do not have the A(i) values uniformly distributed + // into each of them then insertion sort will not produce O(n) results; - //look for classes that have too many elements; ideally each class - //(except the topmost or K == m class) should have about n/m elements; - //look for classes that exceed n/m elements by some threshold AND have - //more than some minimum number of elements to flashsort recursively + // look for classes that have too many elements; ideally each class + // (except the topmost or K == m class) should have about n/m elements; + // look for classes that exceed n/m elements by some threshold AND have + // more than some minimum number of elements to flashsort recursively - //if the class has 25% more elements than it should - int threshold = (int)(1.25 * ((sortLength / m) + 1)); + // if the class has 25% more elements than it should + int threshold = (int) (1.25 * ((sortLength / m) + 1)); int minElements = 30; - //for each class decide whether to insertion sort its members - //or recursively flashsort its members; - //skip the K == m class because it is already sorted - //since all of the elements have the same value + // for each class decide whether to insertion sort its members + // or recursively flashsort its members; + // skip the K == m class because it is already sorted + // since all of the elements have the same value - for(K = m - 1; K >= 1; K--) - { - //determine the number of elments in the Kth class + for (K = m - 1; K >= 1; K--) { + // determine the number of elments in the Kth class int classSize = L[K + 1] - L[K]; - //if the class size is larger than expected but not - //so small that insertion sort could make quick work - //of it then... - if(classSize > threshold && classSize > minElements) - { - //...attempt to flashsort the class. This will work - //well if the elements inside the class are uniformly - //distributed throughout the class otherwise it will - //perform badly, O(n^2) worst case, since we will have - //performed another classification and permutation step - //and not succeeded in making the problem significantly - //smaller for the next level of recursion. However, - //progress is assured since at each level the elements - //with the maximum value will get sorted. + // if the class size is larger than expected but not + // so small that insertion sort could make quick work + // of it then... + if (classSize > threshold && classSize > minElements) { + // ...attempt to flashsort the class. This will work + // well if the elements inside the class are uniformly + // distributed throughout the class otherwise it will + // perform badly, O(n^2) worst case, since we will have + // performed another classification and permutation step + // and not succeeded in making the problem significantly + // smaller for the next level of recursion. However, + // progress is assured since at each level the elements + // with the maximum value will get sorted. int[] copiedRange = Arrays.copyOfRange(array, L[K], L[K + 1]); runSort(copiedRange, classSize, 0); } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/GravitySort.java b/src/main/java/io/github/arrayv/sorts/distribute/GravitySort.java index 98fa68b7..77f6ccb1 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/GravitySort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/GravitySort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,64 +29,57 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Gravity (Bead)") public final class GravitySort extends Sort { - public GravitySort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Gravity"); - this.setRunAllSortsName("Gravity (Bead) Sort"); - this.setRunSortName("Beadsort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - @Override - public void runSort(int[] array, int length, int bucketCount) { + public GravitySort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } + + @Override + public void runSort(int[] array, int length, int bucketCount) { int min = array[0], max = array[0]; - for(int i = 1; i < length; i++) { - if(array[i] < min) min = array[i]; - if(array[i] > max) max = array[i]; - } + for (int i = 1; i < length; i++) { + if (array[i] < min) + min = array[i]; + if (array[i] > max) + max = array[i]; + } int[] x = Writes.createExternalArray(length); - int[] y = Writes.createExternalArray(max - min + 1); + int[] y = Writes.createExternalArray(max - min + 1); double delay = Math.max(2d / length, 0.001); - //save a copy of array-min in x - //increase count of the array-min value in y - for(int i = 0; i < length; i++) { - Writes.write(x, i, array[i]-min, 0, true, true); - Writes.write(y, array[i]-min, y[array[i]-min]+1, 1, false, true); + // save a copy of array-min in x + // increase count of the array-min value in y + for (int i = 0; i < length; i++) { + Writes.write(x, i, array[i] - min, 0, true, true); + Writes.write(y, array[i] - min, y[array[i] - min] + 1, 1, false, true); } - //do a partial sum backwards to determine how many elements are greater than a value - for(int i = y.length-1; i > 0; i--) - Writes.write(y, i-1, y[i-1]+=y[i], 1, true, true); + // do a partial sum backwards to determine how many elements are greater than a + // value + for (int i = y.length - 1; i > 0; i--) + Writes.write(y, i - 1, y[i - 1] += y[i], 1, true, true); - //iterate for every integer value in the array range - for(int j = y.length-1; j >= 0; j--) { - Highlights.markArray(2, length-y[j]); + // iterate for every integer value in the array range + for (int j = y.length - 1; j >= 0; j--) { + Highlights.markArray(2, length - y[j]); - //iterate for every item in array and x - for(int i = 0; i < length; i++) { + // iterate for every item in array and x + for (int i = 0; i < length; i++) { Highlights.markArray(1, i); Delays.sleep(delay); - int inc = (i >= length-y[j] ? 1 : 0) - (x[i] >= j ? 1 : 0); + int inc = (i >= length - y[j] ? 1 : 0) - (x[i] >= j ? 1 : 0); - //update the main array - Writes.write(array, i, array[i]+inc, delay, true, false); - } + // update the main array + Writes.write(array, i, array[i] + inc, delay, true, false); + } } Writes.deleteExternalArray(x); Writes.deleteExternalArray(y); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/InPlaceLSDRadixSort.java b/src/main/java/io/github/arrayv/sorts/distribute/InPlaceLSDRadixSort.java index 7dec3c13..02c9fb4b 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/InPlaceLSDRadixSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/InPlaceLSDRadixSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,26 +29,16 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "In-Place LSD Radix", bucketSort = true, radixSort = true) public final class InPlaceLSDRadixSort extends Sort { public InPlaceLSDRadixSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("In-Place LSD Radix"); - //this.setRunAllID("In-Place LSD Radix Sort, Base 2"); - this.setRunAllSortsName("In-Place LSD Radix Sort, Base 10"); - this.setRunSortName("In-Place LSD Radix Sort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(true); - this.setRadixSort(true); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.setRunAllSortsName("In-Place LSD Radix Sort, Base " + bucketCount); + this.setRunSortName("In-Place LSD Radix Sort, Base " + bucketCount); int pos = 0; int[] vregs = new int[bucketCount - 1]; @@ -55,27 +46,26 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti int maxpower = Reads.analyzeMaxLog(array, sortLength, bucketCount, 0.5, true); - for(int p = 0; p <= maxpower; p++){ - for(int i = 0; i < vregs.length; i++) { + for (int p = 0; p <= maxpower; p++) { + for (int i = 0; i < vregs.length; i++) { Writes.write(vregs, i, sortLength - 1, 0, false, true); } pos = 0; - for(int i = 0; i < sortLength; i++){ + for (int i = 0; i < sortLength; i++) { int digit = Reads.getDigit(array[pos], p, bucketCount); - if(digit == 0) { + if (digit == 0) { pos++; Highlights.markArray(0, pos); - } - else { - for(int j = 0; j < vregs.length;j++) + } else { + for (int j = 0; j < vregs.length; j++) Highlights.markArray(j + 1, vregs[j]); Writes.multiSwap(array, pos, vregs[digit - 1], bucketCount / 10000d, false, false); - for(int j = digit - 1; j > 0; j--) { + for (int j = digit - 1; j > 0; j--) { Writes.write(vregs, j - 1, vregs[j - 1] - 1, 0, false, true); } } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/IndexSort.java b/src/main/java/io/github/arrayv/sorts/distribute/IndexSort.java index 8830852f..e6c4e454 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/IndexSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/IndexSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,20 +29,10 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Simple Static (Index)") public final class IndexSort extends Sort { public IndexSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Index"); - this.setRunAllSortsName("Simple Static Sort (Index Sort)"); - this.setRunSortName("Index Sort (Simple Static Sort)"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override @@ -55,7 +46,8 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti Writes.swap(array, i, array[i] - min, 0.5, true, false); cmpCount++; } - if (cmpCount >= sortLength - 1) break; + if (cmpCount >= sortLength - 1) + break; Highlights.clearMark(1); Highlights.clearMark(2); Delays.sleep(1); diff --git a/src/main/java/io/github/arrayv/sorts/distribute/LSDRadixSort.java b/src/main/java/io/github/arrayv/sorts/distribute/LSDRadixSort.java index d20bbc61..f01c6380 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/LSDRadixSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/LSDRadixSort.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -30,36 +31,27 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "LSD Radix", bucketSort = true, radixSort = true) public final class LSDRadixSort extends Sort { public LSDRadixSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("LSD Radix"); - this.setRunAllSortsName("Least Significant Digit Radix Sort, Base 4"); - this.setRunSortName("Least Significant Digit Radixsort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(true); - this.setRadixSort(true); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { this.setRunAllSortsName("Least Significant Digit Radix Sort, Base " + bucketCount); + this.setRunSortName("Least Significant Digit Radix Sort, Base " + bucketCount); int highestpower = Reads.analyzeMaxLog(array, sortLength, bucketCount, 0.5, true); @SuppressWarnings("unchecked") ArrayList[] registers = new ArrayList[bucketCount]; - for(int i = 0; i < bucketCount; i++) + for (int i = 0; i < bucketCount; i++) registers[i] = new ArrayList<>(); - for(int p = 0; p <= highestpower; p++){ - for(int i = 0; i < sortLength; i++){ + for (int p = 0; p <= highestpower; p++) { + for (int i = 0; i < sortLength; i++) { Highlights.markArray(1, i); int digit = Reads.getDigit(array[i], p, bucketCount); diff --git a/src/main/java/io/github/arrayv/sorts/distribute/MSDRadixSort.java b/src/main/java/io/github/arrayv/sorts/distribute/MSDRadixSort.java index 1ed627f1..2b66c55a 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/MSDRadixSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/MSDRadixSort.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -30,25 +31,14 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "MSD Radix", bucketSort = true, radixSort = true) public final class MSDRadixSort extends Sort { public MSDRadixSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("MSD Radix"); - //this.setRunAllID("Most Significant Digit Radix Sort"); - this.setRunAllSortsName("Most Significant Digit Radix Sort, Base 4"); - this.setRunSortName("Most Significant Digit Radixsort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(true); - this.setRadixSort(true); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void radixMSD(int[] array, int length, int min, int max, int radix, int pow) { - if(min >= max || pow < 0) + if (min >= max || pow < 0) return; Highlights.markArray(2, max - 1); @@ -57,10 +47,10 @@ private void radixMSD(int[] array, int length, int min, int max, int radix, int @SuppressWarnings("unchecked") ArrayList[] registers = new ArrayList[radix]; - for(int i = 0; i < radix; i++) + for (int i = 0; i < radix; i++) registers[i] = new ArrayList<>(); - for(int i = min; i < max; i++) { + for (int i = min; i < max; i++) { Highlights.markArray(1, i); int digit = Reads.getDigit(array[i], pow, radix); @@ -75,8 +65,8 @@ private void radixMSD(int[] array, int length, int min, int max, int radix, int Writes.transcribeMSD(array, registers, 0, min, 0.8, true, false); int sum = 0; - for(int i = 0; i < registers.length; i++) { - this.radixMSD(array, length, sum + min, sum + min + registers[i].size(), radix, pow-1); + for (int i = 0; i < registers.length; i++) { + this.radixMSD(array, length, sum + min, sum + min + registers[i].size(), radix, pow - 1); sum += registers[i].size(); Writes.arrayListClear(registers[i]); @@ -89,7 +79,8 @@ private void radixMSD(int[] array, int length, int min, int max, int radix, int @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { int highestpower = Reads.analyzeMaxLog(array, sortLength, bucketCount, 0.5, true); - + this.setRunAllSortsName("Most Significant Digit Radix Sort, Base " + bucketCount); + this.setRunSortName("Most Significant Digit Radix Sort, Base " + bucketCount); radixMSD(array, sortLength, 0, sortLength, bucketCount, highestpower); } } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/PigeonholeSort.java b/src/main/java/io/github/arrayv/sorts/distribute/PigeonholeSort.java index ff62afe1..57a41014 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/PigeonholeSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/PigeonholeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -14,20 +15,10 @@ */ // Code refactored from the Python implementation found here: https://en.wikipedia.org/wiki/Pigeonhole_sort - +@SortMeta(name = "Pigeonhole") public final class PigeonholeSort extends Sort { public PigeonholeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Pigeonhole"); - this.setRunAllSortsName("Pigeonhole Sort"); - this.setRunSortName("Pigeonhole Sort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override @@ -35,11 +26,11 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti int min = Integer.MAX_VALUE; int max = Integer.MIN_VALUE; - for(int i = 0; i < sortLength; i++) { - if(array[i] < min) { + for (int i = 0; i < sortLength; i++) { + if (array[i] < min) { min = array[i]; } - if(array[i] > max) { + if (array[i] > max) { max = array[i]; } } @@ -48,15 +39,15 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti int size = max - mi + 1; int[] holes = Writes.createExternalArray(size); - for(int x = 0; x < sortLength; x++) { + for (int x = 0; x < sortLength; x++) { Writes.write(holes, array[x] - mi, holes[array[x] - mi] + 1, 1, false, true); Highlights.markArray(1, x); } int j = 0; - for(int count = 0; count < size; count++) { - while(holes[count] > 0) { + for (int count = 0; count < size; count++) { + while (holes[count] > 0) { Writes.write(holes, count, holes[count] - 1, 0, false, true); Writes.write(array, j, count + mi, 1, false, false); diff --git a/src/main/java/io/github/arrayv/sorts/distribute/RotateLSDRadixSort.java b/src/main/java/io/github/arrayv/sorts/distribute/RotateLSDRadixSort.java index b09ce854..75b19b31 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/RotateLSDRadixSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/RotateLSDRadixSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,78 +29,70 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Rotate LSD Radix", bucketSort = true, radixSort = true) public final class RotateLSDRadixSort extends Sort { - public RotateLSDRadixSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Rotate LSD Radix"); - this.setRunAllSortsName("Rotate LSD Radix Sort, Base 4"); - this.setRunSortName("Rotate LSD Radixsort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(true); - this.setRadixSort(true); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public RotateLSDRadixSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int base; private void multiSwap(int[] array, int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(array, a+i, b+i, 0.5, true, false); + for (int i = 0; i < len; i++) + Writes.swap(array, a + i, b + i, 0.5, true, false); } - private void rotate(int[] array, int a, int m, int b) { - int l = m-a, r = b-m; + private void rotate(int[] array, int a, int m, int b) { + int l = m - a, r = b - m; - while(l > 0 && r > 0) { - if(r < l) { - this.multiSwap(array, m-r, m, r); + while (l > 0 && r > 0) { + if (r < l) { + this.multiSwap(array, m - r, m, r); b -= r; m -= r; l -= r; - } - else { + } else { this.multiSwap(array, a, m, l); a += l; m += l; r -= l; - } - } - } + } + } + } private int binSearch(int[] array, int a, int b, int d, int p) { - while(a < b) { - int m = (a+b)/2; + while (a < b) { + int m = (a + b) / 2; - if(Reads.getDigit(array[m], p, this.base) >= d) + if (Reads.getDigit(array[m], p, this.base) >= d) b = m; - else a = m+1; + else + a = m + 1; } return a; } private void merge(int[] array, int a, int m, int b, int da, int db, int p) { - if(b-a < 2 || db-da < 2) return; + if (b - a < 2 || db - da < 2) + return; - int dm = (da+db)/2; + int dm = (da + db) / 2; int m1 = this.binSearch(array, a, m, dm, p); int m2 = this.binSearch(array, m, b, dm, p); this.rotate(array, m1, m, m2); - m = m1+(m2-m); + m = m1 + (m2 - m); this.merge(array, m, m2, b, dm, db, p); this.merge(array, a, m1, m, da, dm, p); } private void mergeSort(int[] array, int a, int b, int p) { - if(b-a < 2) return; + if (b - a < 2) + return; - int m = (a+b)/2; + int m = (a + b) / 2; this.mergeSort(array, a, m, p); this.mergeSort(array, m, b, p); @@ -107,12 +100,14 @@ private void mergeSort(int[] array, int a, int b, int p) { this.merge(array, a, m, b, 0, this.base, p); } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { this.base = bucketCount; - int max = Reads.analyzeMaxLog(array, length, this.base, 0.5, true); + this.setRunAllSortsName("Rotate LSD Radix Sort, Base " + bucketCount); + this.setRunSortName("Rotate LSD Radix Sort, Base " + bucketCount); + int max = Reads.analyzeMaxLog(array, length, this.base, 0.5, true); - for(int i = 0; i <= max; i++) + for (int i = 0; i <= max; i++) this.mergeSort(array, 0, length, i); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/RotateMSDRadixSort.java b/src/main/java/io/github/arrayv/sorts/distribute/RotateMSDRadixSort.java index 82f04b91..021db63a 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/RotateMSDRadixSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/RotateMSDRadixSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,24 +29,14 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Rotate MSD Radix", bucketSort = true, radixSort = true) public final class RotateMSDRadixSort extends Sort { - public RotateMSDRadixSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Rotate MSD Radix"); - this.setRunAllSortsName("Rotate MSD Radix Sort, Base 4"); - this.setRunSortName("Rotate MSD Radixsort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(true); - this.setRadixSort(true); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public RotateMSDRadixSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int stabVal(int idx) { - if(arrayVisualizer.doingStabilityCheck()) + if (arrayVisualizer.doingStabilityCheck()) return arrayVisualizer.getStabilityValue(idx); else return idx; @@ -54,7 +45,7 @@ private int stabVal(int idx) { private int base; private int shift(int n, int q) { - while(q > 0) { + while (q > 0) { n /= this.base; q--; } @@ -62,59 +53,61 @@ private int shift(int n, int q) { } private void multiSwap(int[] array, int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(array, a+i, b+i, 0.5, true, false); + for (int i = 0; i < len; i++) + Writes.swap(array, a + i, b + i, 0.5, true, false); } - private void rotate(int[] array, int a, int m, int b) { - int l = m-a, r = b-m; + private void rotate(int[] array, int a, int m, int b) { + int l = m - a, r = b - m; - while(l > 0 && r > 0) { - if(r < l) { - this.multiSwap(array, m-r, m, r); + while (l > 0 && r > 0) { + if (r < l) { + this.multiSwap(array, m - r, m, r); b -= r; m -= r; l -= r; - } - else { + } else { this.multiSwap(array, a, m, l); a += l; m += l; r -= l; - } - } - } + } + } + } private int binSearch(int[] array, int a, int b, int d, int p) { - while(a < b) { - int m = (a+b)/2; + while (a < b) { + int m = (a + b) / 2; - if(Reads.getDigit(array[m], p, this.base) >= d) + if (Reads.getDigit(array[m], p, this.base) >= d) b = m; - else a = m+1; + else + a = m + 1; } return a; } private void merge(int[] array, int a, int m, int b, int da, int db, int p) { - if(b-a < 2 || db-da < 2) return; + if (b - a < 2 || db - da < 2) + return; - int dm = (da+db)/2; + int dm = (da + db) / 2; int m1 = this.binSearch(array, a, m, dm, p); int m2 = this.binSearch(array, m, b, dm, p); this.rotate(array, m1, m, m2); - m = m1+(m2-m); + m = m1 + (m2 - m); this.merge(array, m, m2, b, dm, db, p); this.merge(array, a, m1, m, da, dm, p); } private void mergeSort(int[] array, int a, int b, int p) { - if(b-a < 2) return; + if (b - a < 2) + return; - int m = (a+b)/2; + int m = (a + b) / 2; this.mergeSort(array, a, m, p); this.mergeSort(array, m, b, p); @@ -126,21 +119,23 @@ private int dist(int[] array, int a, int b, int p) { this.mergeSort(array, a, b, p); return this.binSearch(array, a, b, 1, p); - } + } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { this.base = bucketCount; + this.setRunAllSortsName("Rotate MSD Radix Sort, Base " + bucketCount); + this.setRunSortName("Rotate MSD Radix Sort, Base " + bucketCount); int q = Reads.analyzeMaxLog(array, length, this.base, 0.5, true); int m = 0, i = 0, b = length; - while(i < length) { - int p = b-i < 1 ? i : this.dist(array, i, b, q); + while (i < length) { + int p = b - i < 1 ? i : this.dist(array, i, b, q); - if(q == 0) { + if (q == 0) { m += this.base; - int t = m/this.base; - while(t%this.base == 0) { + int t = m / this.base; + while (t % this.base == 0) { t /= this.base; q++; } @@ -148,17 +143,16 @@ public void runSort(int[] array, int length, int bucketCount) { i = b; Highlights.clearMark(2); arrayVisualizer.toggleAnalysis(true); - while(b < length && this.shift(this.stabVal(array[b]), q+1) == this.shift(m, q+1)) { + while (b < length && this.shift(this.stabVal(array[b]), q + 1) == this.shift(m, q + 1)) { Highlights.markArray(1, b); Delays.sleep(0.5); b++; } arrayVisualizer.toggleAnalysis(false); - } - else { + } else { b = p; q--; } } - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/ShatterSort.java b/src/main/java/io/github/arrayv/sorts/distribute/ShatterSort.java index 45d11c7f..22d5a792 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/ShatterSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/ShatterSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.ShatterSorting; /* @@ -28,24 +29,16 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Shatter", bucketSort = true) public final class ShatterSort extends ShatterSorting { public ShatterSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Shatter"); - this.setRunAllSortsName("Shatter Sort"); - this.setRunSortName("Shatter Sort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(true); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { + this.setRunAllSortsName("Shatter Sort, " + bucketCount + " Buckets"); + this.setRunSortName("Shatter Sort, " + bucketCount + " Buckets"); this.shatterSort(array, sortLength, bucketCount); } } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/SimpleShatterSort.java b/src/main/java/io/github/arrayv/sorts/distribute/SimpleShatterSort.java index 4552815b..f29a5d91 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/SimpleShatterSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/SimpleShatterSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.ShatterSorting; /* @@ -28,24 +29,16 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Simple Shatter", bucketSort = true) public final class SimpleShatterSort extends ShatterSorting { public SimpleShatterSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Simple Shatter"); - this.setRunAllSortsName("Simple Shatter Sort"); - this.setRunSortName("Simple Shatter Sort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(true); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { + this.setRunAllSortsName("Simple Shatter Sort, " + bucketCount + " Buckets"); + this.setRunSortName("Simple Shatter Sort, " + bucketCount + " Buckets"); this.simpleShatterSort(array, sortLength, bucketCount, (int) (Math.log(sortLength) / Math.log(2)) / 2); } } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/SimplisticGravitySort.java b/src/main/java/io/github/arrayv/sorts/distribute/SimplisticGravitySort.java index bc8d2982..acd3bd9d 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/SimplisticGravitySort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/SimplisticGravitySort.java @@ -1,50 +1,42 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Simplistic Gravity") public final class SimplisticGravitySort extends Sort { - public SimplisticGravitySort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Simplistic Gravity"); - this.setRunAllSortsName("Simplistic Gravity Sort (By McDude_73)"); - this.setRunSortName("Simplistic Gravity Sort"); - this.setCategory("Distributive Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); + public SimplisticGravitySort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); } - int[] aux; - int min; + int[] aux; + int min; double sleep; - private void transferFrom(int[] array, int arrayLength, int index) { - for(int pointer = 0;pointer < arrayLength && this.aux[pointer] != 0;pointer++) { - Highlights.markArray(2, index); - Writes.write(array, index, ++array[index], 0, false, false); - Writes.write(this.aux, pointer, --this.aux[pointer], this.sleep, true, true); - } - } + private void transferFrom(int[] array, int arrayLength, int index) { + for (int pointer = 0; pointer < arrayLength && this.aux[pointer] != 0; pointer++) { + Highlights.markArray(2, index); + Writes.write(array, index, ++array[index], 0, false, false); + Writes.write(this.aux, pointer, --this.aux[pointer], this.sleep, true, true); + } + } - private void transferTo(int[] array, int arrayLength, int index) { - for(int pointer = 0;array[index] > this.min;pointer++) { - Highlights.markArray(2, index); - Writes.write(array, index, --array[index], 0, false, false); - Writes.write(this.aux, pointer, ++this.aux[pointer], this.sleep, true, true); - } - } + private void transferTo(int[] array, int arrayLength, int index) { + for (int pointer = 0; array[index] > this.min; pointer++) { + Highlights.markArray(2, index); + Writes.write(array, index, --array[index], 0, false, false); + Writes.write(this.aux, pointer, ++this.aux[pointer], this.sleep, true, true); + } + } - @Override - public void runSort(int[] array, int length, int bucketCount) { - this.sleep = 10d/length; - this.min = array[0]; - int max = min; - for(int mainPointer = 1;mainPointer < length;mainPointer++) { + @Override + public void runSort(int[] array, int length, int bucketCount) { + this.sleep = 10d / length; + this.min = array[0]; + int max = min; + for (int mainPointer = 1; mainPointer < length; mainPointer++) { Highlights.markArray(1, mainPointer); Writes.startLap(); this.min = Math.min(array[mainPointer], min); @@ -52,13 +44,13 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.stopLap(); Delays.sleep(0.5); } - this.aux = Writes.createExternalArray(max-this.min); - for(int mainPointer = 0;mainPointer < length;mainPointer++) { - transferTo(array, length, mainPointer); - } - for(int mainPointer = length - 1;mainPointer >= 0;mainPointer--) { - transferFrom(array, this.aux.length, mainPointer); - } - Writes.deleteExternalArray(this.aux); - } + this.aux = Writes.createExternalArray(max - this.min); + for (int mainPointer = 0; mainPointer < length; mainPointer++) { + transferTo(array, length, mainPointer); + } + for (int mainPointer = length - 1; mainPointer >= 0; mainPointer--) { + transferFrom(array, this.aux.length, mainPointer); + } + Writes.deleteExternalArray(this.aux); + } } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/StacklessAmericanFlagSort.java b/src/main/java/io/github/arrayv/sorts/distribute/StacklessAmericanFlagSort.java index 34da93b3..3cffbf0b 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/StacklessAmericanFlagSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/StacklessAmericanFlagSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,31 +29,21 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Stackless American Flag", bucketSort = true, radixSort = true) public final class StacklessAmericanFlagSort extends Sort { - public StacklessAmericanFlagSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Stackless American Flag"); - this.setRunAllSortsName("Stackless American Flag Sort"); - this.setRunSortName("Stackless American Flag Sort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(true); - this.setRadixSort(true); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public StacklessAmericanFlagSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int stabVal(int idx) { - if(arrayVisualizer.doingStabilityCheck()) + if (arrayVisualizer.doingStabilityCheck()) return arrayVisualizer.getStabilityValue(idx); else return idx; } private static int shift(int n, int q, int r) { - while(q > 0) { + while (q > 0) { n /= r; q--; } @@ -60,85 +51,84 @@ private static int shift(int n, int q, int r) { } private int dist(int[] array, int[] cnts, int[] offs, int a, int b, int q, int r) { - for(int i = 1; i < r; i++) { - Writes.write(cnts, i, cnts[i]+cnts[i-1], 0, false, true); - Writes.write(offs, i, cnts[i-1], 0, false, true); + for (int i = 1; i < r; i++) { + Writes.write(cnts, i, cnts[i] + cnts[i - 1], 0, false, true); + Writes.write(offs, i, cnts[i - 1], 0, false, true); } - for(int i = 0; i < r-1; i++) { - int pos = a+offs[i]; + for (int i = 0; i < r - 1; i++) { + int pos = a + offs[i]; - if(cnts[i] > offs[i]) { + if (cnts[i] > offs[i]) { Highlights.markArray(2, pos); int t = array[pos]; do { int digit = Reads.getDigit(t, q, r); - Writes.write(cnts, digit, cnts[digit]-1, 0, false, true); + Writes.write(cnts, digit, cnts[digit] - 1, 0, false, true); - int t1 = array[a+cnts[digit]]; - Writes.write(array, a+cnts[digit], t, 0.5, true, false); + int t1 = array[a + cnts[digit]]; + Writes.write(array, a + cnts[digit], t, 0.5, true, false); t = t1; - } - while(cnts[i] > offs[i]); + } while (cnts[i] > offs[i]); Highlights.clearMark(2); } } - int p = a+offs[1]; + int p = a + offs[1]; - for(int i = 0; i < r; i++) { + for (int i = 0; i < r; i++) { Writes.write(cnts, i, 0, 0, false, true); Writes.write(offs, i, 0, 0, false, true); } return p; - } + } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { int r = bucketCount, q = Reads.analyzeMaxLog(array, length, r, 0.5, true), m = 0, - i = 0, b = length; + i = 0, b = length; int[] cnts = new int[r], - offs = new int[r]; + offs = new int[r]; Writes.changeAllocAmount(2 * r); - - for(int j = i; j < b; j++) { + this.setRunAllSortsName("Stackless American Flag Sort, " + bucketCount + " Buckets"); + this.setRunSortName("Stackless American Flag Sort, " + bucketCount + " Buckets"); + for (int j = i; j < b; j++) { Highlights.markArray(1, j); int digit = Reads.getDigit(array[j], q, r); - Writes.write(cnts, digit, cnts[digit]+1, 0.5, false, true); + Writes.write(cnts, digit, cnts[digit] + 1, 0.5, false, true); } - while(i < length) { - int p = b-i < 1 ? i : this.dist(array, cnts, offs, i, b, q, r); + while (i < length) { + int p = b - i < 1 ? i : this.dist(array, cnts, offs, i, b, q, r); - if(q == 0) { + if (q == 0) { m += r; - int t = m/r; + int t = m / r; - while(t%r == 0) { + while (t % r == 0) { t /= r; q++; } i = b; - while(b < length && shift(this.stabVal(array[b]), q+1, r) == shift(m, q+1, r)) { + while (b < length && shift(this.stabVal(array[b]), q + 1, r) == shift(m, q + 1, r)) { Highlights.markArray(1, b); int digit = Reads.getDigit(array[b], q, r); - Writes.write(cnts, digit, cnts[digit]+1, 0.5, false, true); + Writes.write(cnts, digit, cnts[digit] + 1, 0.5, false, true); b++; } - } - else { + } else { b = p; q--; - for(int j = i; j < b; j++) { + for (int j = i; j < b; j++) { Highlights.markArray(1, j); int digit = Reads.getDigit(array[j], q, r); - Writes.write(cnts, digit, cnts[digit]+1, 0.5, false, true); + Writes.write(cnts, digit, cnts[digit] + 1, 0.5, false, true); } } } Writes.changeAllocAmount(-2 * r); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/StacklessBinaryQuickSort.java b/src/main/java/io/github/arrayv/sorts/distribute/StacklessBinaryQuickSort.java index 5d59b6a3..11cb29fa 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/StacklessBinaryQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/StacklessBinaryQuickSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,78 +29,68 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Stackless Binary Quick") public final class StacklessBinaryQuickSort extends Sort { - public StacklessBinaryQuickSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Stackless Binary Quick"); - this.setRunAllSortsName("Stackless Binary Quick Sort"); - this.setRunSortName("Stackless Binary Quicksort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public StacklessBinaryQuickSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int stabVal(int idx) { - if(arrayVisualizer.doingStabilityCheck()) + if (arrayVisualizer.doingStabilityCheck()) return arrayVisualizer.getStabilityValue(idx); else return idx; } private int partition(int[] array, int a, int b, int bit) { - int i = a-1, j = b; + int i = a - 1, j = b; - while(true) { + while (true) { do { - i++; - Highlights.markArray(1, i); - Delays.sleep(0.5); - } - while(i < j && !Reads.getBit(array[i], bit)); + i++; + Highlights.markArray(1, i); + Delays.sleep(0.5); + } while (i < j && !Reads.getBit(array[i], bit)); do { - j--; - Highlights.markArray(2, j); - Delays.sleep(0.5); - } - while(j > i && Reads.getBit(array[j], bit)); - - if(i < j) Writes.swap(array, i, j, 1, true, false); - else return i; - } - } + j--; + Highlights.markArray(2, j); + Delays.sleep(0.5); + } while (j > i && Reads.getBit(array[j], bit)); + + if (i < j) + Writes.swap(array, i, j, 1, true, false); + else + return i; + } + } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { int q = Reads.analyzeBit(array, length), m = 0, - i = 0, b = length; + i = 0, b = length; - while(i < length) { - int p = b-i < 1 ? i : this.partition(array, i, b, q); + while (i < length) { + int p = b - i < 1 ? i : this.partition(array, i, b, q); - if(q == 0) { + if (q == 0) { m += 2; - while(!Reads.getBit(m, q+1)) q++; + while (!Reads.getBit(m, q + 1)) + q++; i = b; Highlights.clearMark(2); arrayVisualizer.toggleAnalysis(true); - while(b < length && (this.stabVal(array[b]) >> (q+1)) == (m >> (q+1))) { + while (b < length && (this.stabVal(array[b]) >> (q + 1)) == (m >> (q + 1))) { Highlights.markArray(1, b); Delays.sleep(0.5); b++; } arrayVisualizer.toggleAnalysis(false); - } - else { + } else { b = p; q--; } } - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/StaticSort.java b/src/main/java/io/github/arrayv/sorts/distribute/StaticSort.java index 42552513..9341c8ea 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/StaticSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/StaticSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.distribute; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.InsertionSort; import io.github.arrayv.sorts.select.MaxHeapSort; import io.github.arrayv.sorts.templates.Sort; @@ -30,28 +31,18 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Static") public final class StaticSort extends Sort { MaxHeapSort heapSorter; InsertionSort insertSorter; public StaticSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Static"); - this.setRunAllSortsName("Static Sort"); - this.setRunSortName("Static Sort"); - this.setCategory("Distribution Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } public int[] findMinMax(int[] array, int a, int b) { int min = array[a], - max = min; + max = min; for (int i = a + 1; i < b; i++) { if (Reads.compareIndexValue(array, i, min, 0.5, true) < 0) @@ -60,15 +51,15 @@ else if (Reads.compareIndexValue(array, i, max, 0.5, true) > 0) max = array[i]; } - return new int[] {min, max}; + return new int[] { min, max }; } public void staticSort(int[] array, int a, int b) { int[] minMax = this.findMinMax(array, a, b); int auxLen = b - a; - int[] count = Writes.createExternalArray(auxLen + 1), - offset = Writes.createExternalArray(auxLen + 1); + int[] count = Writes.createExternalArray(auxLen + 1), + offset = Writes.createExternalArray(auxLen + 1); float CONST = (float) auxLen / (minMax[1] - minMax[0] + 1); @@ -76,7 +67,7 @@ public void staticSort(int[] array, int a, int b) { for (int i = a; i < b; i++) { Highlights.markArray(1, i); Delays.sleep(1); - idx = (int)((array[i] - minMax[0]) * CONST); + idx = (int) ((array[i] - minMax[0]) * CONST); Writes.write(count, idx, count[idx] + 1, 1, false, true); } @@ -95,7 +86,7 @@ public void staticSort(int[] array, int a, int b) { Writes.write(array, from, -1, 0.5, true, false); do { - idx = (int)((num - minMax[0]) * CONST); + idx = (int) ((num - minMax[0]) * CONST); int to = offset[idx]; Writes.write(offset, idx, offset[idx] + 1, 1, false, true); @@ -112,9 +103,10 @@ public void staticSort(int[] array, int a, int b) { for (int i = 0; i < auxLen; i++) { int s = (i > 1) ? offset[i - 1] : a, - e = offset[i]; + e = offset[i]; - if (e - s <= 1) continue; + if (e - s <= 1) + continue; if (e - s > 16) heapSorter.customHeapSort(array, s, e, 1); diff --git a/src/main/java/io/github/arrayv/sorts/distribute/TimeSort.java b/src/main/java/io/github/arrayv/sorts/distribute/TimeSort.java index c6f45cb6..30f66e4e 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/TimeSort.java +++ b/src/main/java/io/github/arrayv/sorts/distribute/TimeSort.java @@ -36,13 +36,7 @@ of this software and associated documentation files (the "Software"), to deal * */ -@SortMeta( - name = "Time", - category = "Distribution Sorts", - showcaseName = "Time Sort, Mul 10", - question = "Enter delay per number in milliseconds:", - defaultAnswer = 10 -) +@SortMeta(name = "Time", question = "Enter delay per number in milliseconds:", defaultAnswer = 10) public final class TimeSort extends Sort { private InsertionSort insertSorter; @@ -52,7 +46,7 @@ public TimeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } - private synchronized void report(int[] array, int a){ + private synchronized void report(int[] array, int a) { Writes.write(array, next, a, 0, true, false); next++; } @@ -60,7 +54,8 @@ private synchronized void report(int[] array, int a){ @Override public void runSort(int[] array, int sortLength, int magnitude) throws Exception { insertSorter = new InsertionSort(this.arrayVisualizer); - + this.setRunAllSortsName("Time Sort, Mul " + magnitude); + this.setRunSortName("Time Sort, Mul " + magnitude); final int A = magnitude; next = 0; @@ -68,14 +63,14 @@ public void runSort(int[] array, int sortLength, int magnitude) throws Exception final int[] tmp = Writes.createExternalArray(sortLength); - for(int i = 0; i < sortLength; i++) { + for (int i = 0; i < sortLength; i++) { Writes.write(tmp, i, array[i], 0.25, true, true); } double temp = Delays.getDisplayedDelay(); Delays.updateDelayForTimeSort(magnitude); - for(int i = 0; i < sortLength; i++){ + for (int i = 0; i < sortLength; i++) { final int index = i; threads.add(new Thread("TimeSort-" + i) { @Override @@ -83,13 +78,11 @@ public void run() { int a = tmp[index]; try { - Thread.sleep(a*A); + Thread.sleep(a * A); Writes.addTime(A); - } - catch (InterruptedException ex) { + } catch (InterruptedException ex) { Logger.getLogger(ArrayVisualizer.class.getName()).log(Level.SEVERE, null, ex); - } - catch (IllegalArgumentException ex) { + } catch (IllegalArgumentException ex) { JErrorPane.invokeErrorMessage(ex); } TimeSort.this.report(array, a); @@ -97,16 +90,14 @@ public void run() { }); } - for(Thread t : threads) + for (Thread t : threads) t.start(); try { Thread.sleep(sortLength * A); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { Logger.getLogger(ArrayVisualizer.class.getName()).log(Level.SEVERE, null, e); - } - catch (IllegalArgumentException ex) { + } catch (IllegalArgumentException ex) { JErrorPane.invokeErrorMessage(ex); } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/package-info.java b/src/main/java/io/github/arrayv/sorts/distribute/package-info.java new file mode 100644 index 00000000..5e296931 --- /dev/null +++ b/src/main/java/io/github/arrayv/sorts/distribute/package-info.java @@ -0,0 +1,2 @@ +@io.github.arrayv.sortdata.SortPackageMeta(category = "Distribution Sorts") +package io.github.arrayv.sorts.distribute; diff --git a/src/main/java/io/github/arrayv/sorts/exchange/BinaryGnomeSort.java b/src/main/java/io/github/arrayv/sorts/exchange/BinaryGnomeSort.java index b9bc015a..ef401017 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/BinaryGnomeSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/BinaryGnomeSort.java @@ -1,21 +1,13 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(listName = "Binary Gnome", runName = "Optimized Gnome Sort + Binary Search") public final class BinaryGnomeSort extends Sort { public BinaryGnomeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Binary Gnome"); - this.setRunAllSortsName("Optimized Gnome Sort + Binary Search"); - this.setRunSortName("Optimized Gnomesort + Binary Search"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override @@ -33,10 +25,10 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti Delays.sleep(1); - if (Reads.compareValues(num, array[mid]) < 0) { // do NOT shift equal elements past each other; this maintains stability! + if (Reads.compareValues(num, array[mid]) < 0) { // do NOT shift equal elements past each other; this + // maintains stability! hi = mid; - } - else { + } else { lo = mid + 1; } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/BubbleSort.java b/src/main/java/io/github/arrayv/sorts/exchange/BubbleSort.java index 0a7918e0..925e3664 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/BubbleSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/BubbleSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,37 +29,24 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Bubble") public final class BubbleSort extends Sort { public BubbleSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Bubble"); - this.setRunAllSortsName("Bubble Sort"); - this.setRunSortName("Bubblesort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override public void runSort(int[] array, int length, int bucketCount) { - for(int i = length - 1; i > 0; i--) { + for (int i = length - 1; i > 0; i--) { boolean sorted = true; - for(int j = 0; j < i; j++) { - if(Reads.compareValues(array[j], array[j + 1]) == 1){ + for (int j = 0; j < i; j++) { + if (Reads.compareIndices(array, j, j + 1, 0.025, true) == 1) { Writes.swap(array, j, j + 1, 0.075, true, false); sorted = false; } - - Highlights.markArray(1, j); - Highlights.markArray(2, j + 1); - Delays.sleep(0.025); } - if(sorted) break; + if (sorted) + break; } } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/CircleSortIterative.java b/src/main/java/io/github/arrayv/sorts/exchange/CircleSortIterative.java index 97806f83..a691e9b5 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/CircleSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/CircleSortIterative.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.IterativeCircleSorting; /* @@ -14,20 +15,10 @@ Free Documentation License". * */ - +@SortMeta(listName = "Circle (Iterative)", runName = "Iterative Circle Sort") public final class CircleSortIterative extends IterativeCircleSorting { public CircleSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Circle (Iterative)"); - this.setRunAllSortsName("Iterative Circle Sort"); - this.setRunSortName("Iterative Circlesort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } public void singleRoutine(int[] array, int length) { @@ -36,9 +27,10 @@ public void singleRoutine(int[] array, int length) { @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - this.end = sortLength; - int n = 1; - for(; n < sortLength; n*=2); + this.end = sortLength; + int n = 1; + for (; n < sortLength; n *= 2) + ; int numberOfSwaps = 0; do { diff --git a/src/main/java/io/github/arrayv/sorts/exchange/CircleSortRecursive.java b/src/main/java/io/github/arrayv/sorts/exchange/CircleSortRecursive.java index f83c76bf..7e9e77f1 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/CircleSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/CircleSortRecursive.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.CircleSorting; /* @@ -14,20 +15,10 @@ Free Documentation License". * */ - +@SortMeta(listName = "Circle (Recursive)", runName = "Recursive Circle Sort") public final class CircleSortRecursive extends CircleSorting { public CircleSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Circle (Recursive)"); - this.setRunAllSortsName("Recursive Circle Sort"); - this.setRunSortName("Circlesort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } public void singleRoutine(int[] array, int length) { @@ -36,9 +27,10 @@ public void singleRoutine(int[] array, int length) { @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - this.end = sortLength; - int n = 1; - for(; n < sortLength; n*=2); + this.end = sortLength; + int n = 1; + for (; n < sortLength; n *= 2) + ; int numberOfSwaps = 0; do { diff --git a/src/main/java/io/github/arrayv/sorts/exchange/CircloidSort.java b/src/main/java/io/github/arrayv/sorts/exchange/CircloidSort.java index a6e0fdbf..e5969190 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/CircloidSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/CircloidSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,50 +29,42 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Circloid") public final class CircloidSort extends Sort { public CircloidSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Circloid"); - this.setRunAllSortsName("Circloid Sort"); - this.setRunSortName("Circloid Sort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - private boolean circle(int[] array, int left, int right) { + private boolean circle(int[] array, int left, int right) { int a = left; int b = right; boolean swapped = false; - while(a < b) { - if(Reads.compareIndices(array, a, b, 0.25, true) == 1) { - Writes.swap(array, a, b, 1, true, false); - swapped = true; - } - a++; - b--; - if(a==b) { - b++; - } + while (a < b) { + if (Reads.compareIndices(array, a, b, 0.25, true) == 1) { + Writes.swap(array, a, b, 1, true, false); + swapped = true; + } + a++; + b--; + if (a == b) { + b++; + } } return swapped; } - private boolean circlePass(int[] array, int left, int right) { - if(left >= right) return false; - int mid = (left + right) / 2; - boolean l = this.circlePass(array, left, mid); - boolean r = this.circlePass(array, mid+1, right); - return this.circle(array, left, right) || l || r; + private boolean circlePass(int[] array, int left, int right) { + if (left >= right) + return false; + int mid = (left + right) / 2; + boolean l = this.circlePass(array, left, mid); + boolean r = this.circlePass(array, mid + 1, right); + return this.circle(array, left, right) || l || r; } @Override public void runSort(int[] array, int length, int bucketCount) { - while(this.circlePass(array, 0, length-1)); + while (this.circlePass(array, 0, length - 1)) + ; } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/ClassicThreeSmoothCombSort.java b/src/main/java/io/github/arrayv/sorts/exchange/ClassicThreeSmoothCombSort.java index b5dfe818..e592687e 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/ClassicThreeSmoothCombSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/ClassicThreeSmoothCombSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -25,36 +26,29 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Classic 3-Smooth Comb") public final class ClassicThreeSmoothCombSort extends Sort { public ClassicThreeSmoothCombSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Classic 3-Smooth Comb"); - this.setRunAllSortsName("Classic 3-Smooth Comb Sort"); - this.setRunSortName("Classic 3-Smooth Combsort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - private boolean is3Smooth(int n) { - while(n%6 == 0) n /= 6; - while(n%3 == 0) n /= 3; - while(n%2 == 0) n /= 2; + private boolean is3Smooth(int n) { + while (n % 6 == 0) + n /= 6; + while (n % 3 == 0) + n /= 3; + while (n % 2 == 0) + n /= 2; - return n == 1; - } + return n == 1; + } @Override public void runSort(int[] array, int length, int bucketCount) { - for(int g = length-1; g > 0; g--) - if(is3Smooth(g)) - for(int i = g; i < length; i++) - if(Reads.compareIndices(array, i-g, i, 0.5, true) == 1) - Writes.swap(array, i-g, i, 0.5, true, false); + for (int g = length - 1; g > 0; g--) + if (is3Smooth(g)) + for (int i = g; i < length; i++) + if (Reads.compareIndices(array, i - g, i, 0.5, true) == 1) + Writes.swap(array, i - g, i, 0.5, true, false); } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/CocktailShakerSort.java b/src/main/java/io/github/arrayv/sorts/exchange/CocktailShakerSort.java index 41ba91b7..b6960d2a 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/CocktailShakerSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/CocktailShakerSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,50 +29,32 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Cocktail Shaker") public final class CocktailShakerSort extends Sort { public CocktailShakerSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Cocktail"); - this.setRunAllSortsName("Cocktail Shaker Sort"); - this.setRunSortName("Cocktail Shaker Sort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void smartCocktailShaker(int[] array, int start, int end, double sleep) { int i = start; - while(i < ((end / 2) + start)) { + while (i < ((end / 2) + start)) { boolean sorted = true; - for(int j = i; j < end + start - i - 1; j++) { - if(Reads.compareValues(array[j], array[j + 1]) == 1) { + for (int j = i; j < end + start - i - 1; j++) { + if (Reads.compareIndices(array, j, j + 1, sleep / 2, true) == 1) { Writes.swap(array, j, j + 1, sleep, true, false); sorted = false; } - - Highlights.markArray(1, j); - Highlights.markArray(2, j + 1); - - Delays.sleep(sleep / 2); } - for(int j = end + start - i - 1; j > i; j--){ - if(Reads.compareValues(array[j], array[j - 1]) == -1) { + for (int j = end + start - i - 1; j > i; j--) { + if (Reads.compareIndices(array, j, j - 1, sleep / 2, true) == -1) { Writes.swap(array, j, j - 1, sleep, true, false); sorted = false; } - - Highlights.markArray(1, j); - Highlights.markArray(2, j - 1); - - Delays.sleep(sleep / 2); } - if(sorted) break; - else i++; + if (sorted) + break; + else + i++; } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/CombSort.java b/src/main/java/io/github/arrayv/sorts/exchange/CombSort.java index b45cf030..e6dbca32 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/CombSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/CombSort.java @@ -29,24 +29,20 @@ this software and associated documentation files (the "Software"), to deal in * */ -@SortMeta( - name = "Comb", - category = "Exchange Sorts", - question = "Enter shrink factor (input/100):", - defaultAnswer = 130 -) +@SortMeta(name = "Comb", question = "Enter shrink factor (input/100):", defaultAnswer = 130) public final class CombSort extends CombSorting { public CombSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } public static int validateAnswer(int answer) { - if (answer < 110) return 130; + if (answer < 110) + return 130; return answer; } @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - this.combSort(array, sortLength, bucketCount/100d, false); + this.combSort(array, sortLength, bucketCount / 100d, false); } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/CompleteGraphSort.java b/src/main/java/io/github/arrayv/sorts/exchange/CompleteGraphSort.java index f506912e..dc06cddd 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/CompleteGraphSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/CompleteGraphSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -27,76 +28,69 @@ this software and associated documentation files (the "Software"), to deal in CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ - +@SortMeta(listName = "Complete Graph", runName = "Complete Graph Sorting Network") public final class CompleteGraphSort extends Sort { - public CompleteGraphSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Complete Graph"); - this.setRunAllSortsName("Complete Graph Sorting Network"); - this.setRunSortName("Complete Graph Sorting Network"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public CompleteGraphSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private void compSwap(int[] array, int a, int b) { - if(Reads.compareIndices(array, a, b, 0.0125, true) > 0) + if (Reads.compareIndices(array, a, b, 0.0125, true) > 0) Writes.swap(array, a, b, 0.0875, true, false); } private void split(int[] array, int a, int m, int b) { - if(b-a < 2) return; + if (b - a < 2) + return; - int c = 0, len1 = (b-a)/2; - boolean odd = (b-a)%2 == 1; + int c = 0, len1 = (b - a) / 2; + boolean odd = (b - a) % 2 == 1; - if(odd) { - if(m-a > b-m) c = a++; - else c = --b; + if (odd) { + if (m - a > b - m) + c = a++; + else + c = --b; } - for(int s = 0; s < len1; s++) { + for (int s = 0; s < len1; s++) { int i = a; - for(int j = s; j < len1; j++) - this.compSwap(array, i++, m+j); + for (int j = s; j < len1; j++) + this.compSwap(array, i++, m + j); - for(int j = 0; j < s; j++) - this.compSwap(array, i++, m+j); + for (int j = 0; j < s; j++) + this.compSwap(array, i++, m + j); } - if(odd) { - if(c < m) - for(int j = 0; j < len1; j++) - this.compSwap(array, c, m+j); + if (odd) { + if (c < m) + for (int j = 0; j < len1; j++) + this.compSwap(array, c, m + j); else - for(int j = 0; j < len1; j++) - this.compSwap(array, a+j, c); + for (int j = 0; j < len1; j++) + this.compSwap(array, a + j, c); } } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { + @Override + public void runSort(int[] array, int currentLength, int bucketCount) { int n = currentLength; - int d = 2, end = 1 << (int)(Math.log(n-1)/Math.log(2) + 1); + int d = 2, end = 1 << (int) (Math.log(n - 1) / Math.log(2) + 1); - while(d <= end) { + while (d <= end) { int i = 0, dec = 0; - while(i < n) { + while (i < n) { int j = i; dec += n; - while(dec >= d) { + while (dec >= d) { dec -= d; j++; } int k = j; dec += n; - while(dec >= d) { + while (dec >= d) { dec -= d; k++; } @@ -105,5 +99,5 @@ public void runSort(int[] array, int currentLength, int bucketCount) { } d *= 2; } - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/DualPivotQuickSort.java b/src/main/java/io/github/arrayv/sorts/exchange/DualPivotQuickSort.java index b5c9e38e..f291848c 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/DualPivotQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/DualPivotQuickSort.java @@ -1,32 +1,28 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.InsertionSort; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Dual-Pivot Quick") public final class DualPivotQuickSort extends Sort { private InsertionSort insertSorter; public DualPivotQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Dual-Pivot Quick"); - this.setRunAllSortsName("Dual-Pivot Quick Sort"); - this.setRunSortName("Dual-Pivot Quicksort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } /* - * ArrayV's original example of a basic Dual-Pivot Quicksort may be found here, written by Sebastian Wild (Sebastian on StackOverflow): - * https://cs.stackexchange.com/questions/24092/dual-pivot-quicksort-reference-implementation + * ArrayV's original example of a basic Dual-Pivot Quicksort may be found here, + * written by Sebastian Wild (Sebastian on StackOverflow): + * https://cs.stackexchange.com/questions/24092/dual-pivot-quicksort-reference- + * implementation * - * Unfortunately, its O(n^2) worst-case behavior began to cause stack overflow exceptions with large array sizes. This new unoptimized - * version is a stripped-down copy of ArrayV's "Optimized Dual-Pivot Quicksort", written by Vladimir Yaroslavskiy. + * Unfortunately, its O(n^2) worst-case behavior began to cause stack overflow + * exceptions with large array sizes. This new unoptimized + * version is a stripped-down copy of ArrayV's "Optimized Dual-Pivot Quicksort", + * written by Vladimir Yaroslavskiy. * https://codeblab.com/wp-content/uploads/2009/09/DualPivotQuicksort.pdf */ @@ -34,7 +30,7 @@ private void dualPivot(int[] array, int left, int right, int divisor) { int length = right - left; // insertion sort for tiny array - if(length < 4) { + if (length < 4) { Highlights.clearMark(2); insertSorter.customInsertSort(array, left, right + 1, 1, false); return; @@ -43,22 +39,21 @@ private void dualPivot(int[] array, int left, int right, int divisor) { int third = length / divisor; // "medians" - int med1 = left + third; + int med1 = left + third; int med2 = right - third; - if(med1 <= left) { + if (med1 <= left) { med1 = left + 1; } - if(med2 >= right) { + if (med2 >= right) { med2 = right - 1; } - if(Reads.compareValues(array[med1], array[med2]) == -1) { - Writes.swap(array, med1, left, 1, true, false); + if (Reads.compareValues(array[med1], array[med2]) == -1) { + Writes.swap(array, med1, left, 1, true, false); Writes.swap(array, med2, right, 1, true, false); - } - else { + } else { Writes.swap(array, med1, right, 1, true, false); - Writes.swap(array, med2, left, 1, true, false); + Writes.swap(array, med2, left, 1, true, false); } // pivots @@ -66,16 +61,15 @@ private void dualPivot(int[] array, int left, int right, int divisor) { int pivot2 = array[right]; // pointers - int less = left + 1; + int less = left + 1; int great = right - 1; // sorting - for(int k = less; k <= great; k++) { - if(Reads.compareValues(array[k], pivot1) == -1) { + for (int k = less; k <= great; k++) { + if (Reads.compareValues(array[k], pivot1) == -1) { Writes.swap(array, k, less++, 1, true, false); - } - else if(Reads.compareValues(array[k], pivot2) == 1) { - while(k < great && Reads.compareValues(array[great], pivot2) == 1) { + } else if (Reads.compareValues(array[k], pivot2) == 1) { + while (k < great && Reads.compareValues(array[great], pivot2) == 1) { great--; Highlights.markArray(3, great); Delays.sleep(1); @@ -83,7 +77,7 @@ else if(Reads.compareValues(array[k], pivot2) == 1) { Writes.swap(array, k, great--, 1, true, false); Highlights.clearMark(3); - if(Reads.compareValues(array[k], pivot1) == -1) { + if (Reads.compareValues(array[k], pivot1) == -1) { Writes.swap(array, k, less++, 1, true, false); } } @@ -92,15 +86,15 @@ else if(Reads.compareValues(array[k], pivot2) == 1) { // swaps int dist = great - less; - if(dist < 13) { + if (dist < 13) { divisor++; } - Writes.swap(array, less - 1, left, 1, true, false); + Writes.swap(array, less - 1, left, 1, true, false); Writes.swap(array, great + 1, right, 1, true, false); // subarrays - this.dualPivot(array, left, less - 2, divisor); - if(pivot1 < pivot2) { + this.dualPivot(array, left, less - 2, divisor); + if (pivot1 < pivot2) { this.dualPivot(array, less, great, divisor); } this.dualPivot(array, great + 2, right, divisor); diff --git a/src/main/java/io/github/arrayv/sorts/exchange/ForcedStableQuickSort.java b/src/main/java/io/github/arrayv/sorts/exchange/ForcedStableQuickSort.java index 7276865d..584b54af 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/ForcedStableQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/ForcedStableQuickSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,32 +29,22 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Forced Stable Quick") public final class ForcedStableQuickSort extends Sort { - public ForcedStableQuickSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Forced Stable Quick"); - this.setRunAllSortsName("Forced Stable Quick Sort"); - this.setRunSortName("Forced Stable Quicksort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public ForcedStableQuickSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private void medianOfThree(int[] array, int[] key, int a, int b) { - int m = a+(b-1-a)/2; + int m = a + (b - 1 - a) / 2; - if(this.stableComp(array, key, a, m)) + if (this.stableComp(array, key, a, m)) this.stableSwap(array, key, a, m); - if(this.stableComp(array, key, m, b-1)) { - this.stableSwap(array, key, m, b-1); + if (this.stableComp(array, key, m, b - 1)) { + this.stableSwap(array, key, m, b - 1); - if(this.stableComp(array, key, a, m)) + if (this.stableComp(array, key, a, m)) return; } @@ -68,48 +59,52 @@ private boolean stableComp(int[] array, int[] key, int a, int b) { private void stableSwap(int[] array, int[] key, int a, int b) { Writes.swap(array, a, b, 0, true, false); - Writes.swap(key, a, b, 1, false, true); + Writes.swap(key, a, b, 1, false, true); } private int partition(int[] array, int[] key, int a, int b, int p) { - int i = a - 1, j = b; + int i = a - 1, j = b; Highlights.markArray(3, p); - while(true) { - do i++; - while(i < j && !this.stableComp(array, key, i, p)); + while (true) { + do + i++; + while (i < j && !this.stableComp(array, key, i, p)); - do j--; - while(j >= i && this.stableComp(array, key, j, p)); + do + j--; + while (j >= i && this.stableComp(array, key, j, p)); - if(i < j) this.stableSwap(array, key, i, j); - else return j; - } - } + if (i < j) + this.stableSwap(array, key, i, j); + else + return j; + } + } private void quickSort(int[] array, int[] key, int a, int b) { - if(b-a < 3) { - if(b-a == 2 && this.stableComp(array, key, a, a+1)) - this.stableSwap(array, key, a, a+1); + if (b - a < 3) { + if (b - a == 2 && this.stableComp(array, key, a, a + 1)) + this.stableSwap(array, key, a, a + 1); return; } this.medianOfThree(array, key, a, b); - int p = this.partition(array, key, a+1, b, a); + int p = this.partition(array, key, a + 1, b, a); this.stableSwap(array, key, a, p); this.quickSort(array, key, a, p); - this.quickSort(array, key, p+1, b); + this.quickSort(array, key, p + 1, b); } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { int[] key = Writes.createExternalArray(length); - for(int i = 0; i < length; i++) + for (int i = 0; i < length; i++) Writes.write(key, i, i, 0.5, true, true); this.quickSort(array, key, 0, length); Writes.deleteExternalArray(key); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/FunSort.java b/src/main/java/io/github/arrayv/sorts/exchange/FunSort.java index cf32cbc4..3adeb61d 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/FunSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/FunSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -24,40 +25,30 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Fun") public final class FunSort extends Sort { - public FunSort(ArrayVisualizer arrayVisualizer) { + public FunSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Fun"); - this.setRunAllSortsName("Fun Sort"); - this.setRunSortName("Fun Sort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } /* - Fun Sort - or the chaos of unordered binary search - https://www.sciencedirect.com/science/article/pii/S0166218X04001131 - Best Case: O(n log n) - Average/Worst Case: O(n^2 log n) - */ + * Fun Sort - or the chaos of unordered binary search + * https://www.sciencedirect.com/science/article/pii/S0166218X04001131 + * Best Case: O(n log n) + * Average/Worst Case: O(n^2 log n) + */ public int binarySearch(int[] array, int start, int end, int value) { - while (start < end) { - int mid = (start + end) >>> 1; + while (start < end) { + int mid = (start + end) >>> 1; Highlights.markArray(1, start); Highlights.markArray(2, mid); Highlights.markArray(3, end); if (Reads.compareValues(array[mid], value) < 0) { - start = mid + 1; + start = mid + 1; } else { - end = mid; + end = mid; } Delays.sleep(1); } @@ -72,13 +63,13 @@ public void runSort(int[] array, int length, int bucketCount) { for (int i = 1; i < length; i++) { boolean done = false; do { - done = true; + done = true; int pos = binarySearch(array, 0, length - 1, array[i]); if (Reads.compareIndices(array, pos, i, 0, false) != 0) { if (i < pos - 1) { - Writes.swap(array, i, pos - 1, 2, true, false); + Writes.swap(array, i, pos - 1, 2, true, false); } else if (i > pos) { - Writes.swap(array, i, pos, 2, true, false); + Writes.swap(array, i, pos, 2, true, false); } done = false; } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/GnomeSort.java b/src/main/java/io/github/arrayv/sorts/exchange/GnomeSort.java index 8dd32c44..68e8f9cc 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/GnomeSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/GnomeSort.java @@ -1,35 +1,23 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Gnome") public final class GnomeSort extends Sort { public GnomeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Gnome"); - this.setRunAllSortsName("Gnome Sort"); - this.setRunSortName("Gnomesort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } // Code retrieved from http://www.algostructure.com/sorting/gnomesort.php @Override public void runSort(int[] array, int length, int bucketCount) { - for (int i = 1; i < length;) - { - if (Reads.compareIndices(array, i, i - 1, 0.04, true) >= 0) - { + for (int i = 1; i < length;) { + if (Reads.compareIndices(array, i, i - 1, 0.04, true) >= 0) { i++; - } - else - { + } else { Writes.swap(array, i, i - 1, 0.02, true, false); if (i > 1) { diff --git a/src/main/java/io/github/arrayv/sorts/exchange/LLQuickSort.java b/src/main/java/io/github/arrayv/sorts/exchange/LLQuickSort.java index fd743197..dc0adf93 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/LLQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/LLQuickSort.java @@ -1,30 +1,22 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(listName = "Quick (Left/Left)", runName = "Quick Sort, Left/Left Pointers") public final class LLQuickSort extends Sort { public LLQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Left/Left Quick"); - this.setRunAllSortsName("Quick Sort, Left/Left Pointers"); - this.setRunSortName("Left/Left Quicksort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private int partition(int[] array, int lo, int hi) { int pivot = array[hi]; int i = lo; - for(int j = lo; j < hi; j++) { + for (int j = lo; j < hi; j++) { Highlights.markArray(1, j); - if(Reads.compareValues(array[j], pivot) < 0) { + if (Reads.compareValues(array[j], pivot) < 0) { Writes.swap(array, i, j, 1, true, false); i++; } @@ -35,7 +27,7 @@ private int partition(int[] array, int lo, int hi) { } private void quickSort(int[] array, int lo, int hi) { - if(lo < hi) { + if (lo < hi) { int p = this.partition(array, lo, hi); this.quickSort(array, lo, p - 1); this.quickSort(array, p + 1, hi); diff --git a/src/main/java/io/github/arrayv/sorts/exchange/LRQuickSort.java b/src/main/java/io/github/arrayv/sorts/exchange/LRQuickSort.java index 709f9cc3..ea2a6703 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/LRQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/LRQuickSort.java @@ -1,24 +1,17 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(listName = "Quick (Left/Right)", runName = "Quick Sort, Left/Right Pointers") public final class LRQuickSort extends Sort { public LRQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Left/Right Quick"); - this.setRunAllSortsName("Quick Sort, Left/Right Pointers"); - this.setRunSortName("Left/Right Quicksort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - // Thanks to Timo Bingmann for providing a good reference for Quick Sort w/ LR pointers. + // Thanks to Timo Bingmann for providing a good reference for Quick Sort w/ LR + // pointers. private void quickSort(int[] a, int p, int r) { int pivot = p + (r - p + 1) / 2; int x = a[pivot]; @@ -29,12 +22,12 @@ private void quickSort(int[] a, int p, int r) { Highlights.markArray(3, pivot); while (i <= j) { - while (Reads.compareValues(a[i], x) == -1){ + while (Reads.compareValues(a[i], x) == -1) { i++; Highlights.markArray(1, i); Delays.sleep(0.5); } - while (Reads.compareValues(a[j], x) == 1){ + while (Reads.compareValues(a[j], x) == 1) { j--; Highlights.markArray(2, j); Delays.sleep(0.5); @@ -42,10 +35,10 @@ private void quickSort(int[] a, int p, int r) { if (i <= j) { // Follow the pivot and highlight it. - if(i == pivot) { + if (i == pivot) { Highlights.markArray(3, j); } - if(j == pivot) { + if (j == pivot) { Highlights.markArray(3, i); } @@ -56,10 +49,10 @@ private void quickSort(int[] a, int p, int r) { } } - if(p < j) { + if (p < j) { this.quickSort(a, p, j); } - if(i < r) { + if (i < r) { this.quickSort(a, i, r); } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/LRQuickSortParallel.java b/src/main/java/io/github/arrayv/sorts/exchange/LRQuickSortParallel.java index 7981339c..03867bdf 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/LRQuickSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/LRQuickSortParallel.java @@ -1,39 +1,35 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(listName = "Quick (Parallel, Left/Right)", runName = "Parallel Quick Sort, Left/Right Pointers", unreasonableLimit = 4096) public final class LRQuickSortParallel extends Sort { - public LRQuickSortParallel(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Left/Right Quick (Parallel)"); - this.setRunAllSortsName("Parallel Quick Sort, Left/Right Pointers"); - this.setRunSortName("Parallel Left/Right Quicksort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public LRQuickSortParallel(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int[] a; private class QuickSort extends Thread { private int p, r; + QuickSort(int p, int r) { this.p = p; this.r = r; } + + @Override public void run() { LRQuickSortParallel.this.quickSort(p, r); } } - // Thanks to Timo Bingmann for providing a good reference for Quick Sort w/ LR pointers. - private void quickSort(int p, int r) { - if(p < r) { + // Thanks to Timo Bingmann for providing a good reference for Quick Sort w/ LR + // pointers. + private void quickSort(int p, int r) { + if (p < r) { int pivot = p + (r - p + 1) / 2; int x = this.a[pivot]; @@ -43,12 +39,12 @@ private void quickSort(int p, int r) { Highlights.markArray(3, pivot); while (i <= j) { - while (Reads.compareValues(this.a[i], x) == -1){ + while (Reads.compareValues(this.a[i], x) == -1) { i++; Highlights.markArray(1, i); Delays.sleep(0.5); } - while (Reads.compareValues(this.a[j], x) == 1){ + while (Reads.compareValues(this.a[j], x) == 1) { j--; Highlights.markArray(2, j); Delays.sleep(0.5); @@ -56,10 +52,10 @@ private void quickSort(int p, int r) { if (i <= j) { // Follow the pivot and highlight it. - if(i == pivot) { + if (i == pivot) { Highlights.markArray(3, j); } - if(j == pivot) { + if (j == pivot) { Highlights.markArray(3, i); } @@ -70,7 +66,7 @@ private void quickSort(int p, int r) { } } - QuickSort left = new QuickSort(p, j); + QuickSort left = new QuickSort(p, j); QuickSort right = new QuickSort(i, r); left.start(); right.start(); @@ -82,11 +78,11 @@ private void quickSort(int p, int r) { Thread.currentThread().interrupt(); } } - } + } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { + @Override + public void runSort(int[] array, int currentLength, int bucketCount) { this.a = array; - this.quickSort(0, currentLength - 1); - } + this.quickSort(0, currentLength - 1); + } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/OddEvenSort.java b/src/main/java/io/github/arrayv/sorts/exchange/OddEvenSort.java index 64b7f1f5..2b1c6e72 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/OddEvenSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/OddEvenSort.java @@ -1,26 +1,17 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* * This version of Odd-Even Sort was taken from here, written by Rachit Belwariar: * https://www.geeksforgeeks.org/odd-even-sort-brick-sort/ */ - +@SortMeta(name = "Odd-Even") public final class OddEvenSort extends Sort { public OddEvenSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Odd-Even"); - this.setRunAllSortsName("Odd-Even Sort"); - this.setRunSortName("Odd-Even Sort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override @@ -31,23 +22,17 @@ public void runSort(int[] array, int length, int bucketCount) { sorted = true; for (int i = 1; i < length - 1; i += 2) { - if(Reads.compareValues(array[i], array[i + 1]) == 1) { - Writes.swap(array, i, i + 1, 0.075, true, false); + if (Reads.compareIndices(array, i, i + 1, 0.05, true) == 1) { + Writes.swap(array, i, i + 1, 0, true, false); sorted = false; } - - Highlights.markArray(1, i); - Delays.sleep(0.025); } for (int i = 0; i < length - 1; i += 2) { - if(Reads.compareValues(array[i], array[i + 1]) == 1) { - Writes.swap(array, i, i + 1, 0.075, true, false); + if (Reads.compareIndices(array, i, i + 1, 0.05, true) == 1) { + Writes.swap(array, i, i + 1, 0, true, false); sorted = false; } - - Highlights.markArray(2, i); - Delays.sleep(0.025); } } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/OptimizedBubbleSort.java b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedBubbleSort.java index bc9af77c..e1d9bf95 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/OptimizedBubbleSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedBubbleSort.java @@ -1,33 +1,26 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Optimized Bubble") public final class OptimizedBubbleSort extends Sort { public OptimizedBubbleSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Optimized Bubble"); - this.setRunAllSortsName("Optimized Bubble Sort"); - this.setRunSortName("Optimized Bubblesort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override public void runSort(int[] array, int length, int bucketCount) { - int consecSorted; - for(int i = length - 1; i > 0; i -= consecSorted) { + int consecSorted; + for (int i = length - 1; i > 0; i -= consecSorted) { consecSorted = 1; - for(int j = 0; j < i; j++) { - if(Reads.compareIndices(array, j, j + 1, 0.025, true) > 0){ + for (int j = 0; j < i; j++) { + if (Reads.compareIndices(array, j, j + 1, 0.025, true) > 0) { Writes.swap(array, j, j + 1, 0.075, true, false); consecSorted = 1; - } else consecSorted++; + } else + consecSorted++; } } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/OptimizedCocktailShakerSort.java b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedCocktailShakerSort.java index 070ae302..bf56fd7b 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/OptimizedCocktailShakerSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedCocktailShakerSort.java @@ -1,41 +1,35 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Optimized Cocktail Shaker") public final class OptimizedCocktailShakerSort extends Sort { public OptimizedCocktailShakerSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Optimized Cocktail"); - this.setRunAllSortsName("Optimized Cocktail Shaker Sort"); - this.setRunSortName("Optimized Cocktailsort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override public void runSort(int[] array, int length, int bucketCount) { - for(int start = 0, end = length - 1; start < end; ) { + for (int start = 0, end = length - 1; start < end;) { int consecSorted = 1; - for(int i = start; i < end; i++) { - if(Reads.compareIndices(array, i, i + 1, 0.025, true) > 0){ + for (int i = start; i < end; i++) { + if (Reads.compareIndices(array, i, i + 1, 0.025, true) > 0) { Writes.swap(array, i, i + 1, 0.075, true, false); consecSorted = 1; - } else consecSorted++; + } else + consecSorted++; } end -= consecSorted; consecSorted = 1; - for(int i = end; i > start; i--) { - if(Reads.compareIndices(array, i - 1, i, 0.025, true) > 0){ + for (int i = end; i > start; i--) { + if (Reads.compareIndices(array, i - 1, i, 0.025, true) > 0) { Writes.swap(array, i - 1, i, 0.075, true, false); consecSorted = 1; - } else consecSorted++; + } else + consecSorted++; } start += consecSorted; } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/OptimizedGnomeSort.java b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedGnomeSort.java index 34de02c3..9d796931 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/OptimizedGnomeSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedGnomeSort.java @@ -1,42 +1,34 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Optimized Gnome") public final class OptimizedGnomeSort extends Sort { public OptimizedGnomeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Optimized Gnome"); - this.setRunAllSortsName("Optimized Gnome Sort"); - this.setRunSortName("Optimized Gnomesort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } // Taken from https://en.wikipedia.org/wiki/Gnome_sort private void smartGnomeSort(int[] array, int lowerBound, int upperBound, double sleep) { int pos = upperBound; - while(pos > lowerBound && Reads.compareValues(array[pos - 1], array[pos]) == 1) { - Writes.swap(array, pos - 1, pos, sleep, true, false); + while (pos > lowerBound && Reads.compareIndices(array, pos - 1, pos, sleep, true) == 1) { + Writes.swap(array, pos - 1, pos, 0, true, false); pos--; } } public void customSort(int[] array, int low, int high, double sleep) { - for(int i = low + 1; i < high; i++) { + for (int i = low + 1; i < high; i++) { smartGnomeSort(array, low, i, sleep); } } @Override public void runSort(int[] array, int length, int bucketCount) { - for(int i = 1; i < length; i++) { + for (int i = 1; i < length; i++) { smartGnomeSort(array, 0, i, 0.05); } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/OptimizedStoogeSort.java b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedStoogeSort.java index 1aee7211..f31d88e0 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/OptimizedStoogeSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedStoogeSort.java @@ -1,35 +1,23 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; // Code refactored from: https://www.ijitee.org/wp-content/uploads/papers/v8i12/L31671081219.pdf // Written by Professors Amit Kishor and Pankaj Pratap Singh +@SortMeta(listName = "Optimized Stooge (Kishor-Singh)", runName = "Optimized Stooge Sort (Kishor-Singh)") public final class OptimizedStoogeSort extends Sort { public OptimizedStoogeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Optimized Stooge"); - this.setRunAllSortsName("Optimized Stooge Sort"); - this.setRunSortName("Optimized Stoogesort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void forward(int[] array, int left, int right) { - while(left < right) { + while (left < right) { int index = right; - while(left < index) { - Highlights.markArray(1, left); - Highlights.markArray(2, index); - Delays.sleep(0.05); - - if(Reads.compareValues(array[left], array[index]) > 0) { + while (left < index) { + if (Reads.compareIndices(array, left, index, 0.05, true) > 0) { Writes.swap(array, left, index, 0.075, true, false); } left++; @@ -44,15 +32,11 @@ private void forward(int[] array, int left, int right) { private void backward(int[] array, int left, int right) { int length = right; - while(left < right) { + while (left < right) { int index = left; - while(index < right) { - Highlights.markArray(1, index); - Highlights.markArray(2, right); - Delays.sleep(0.05); - - if(Reads.compareValues(array[index], array[right]) > 0) { + while (index < right) { + if (Reads.compareIndices(array, index, right, 0.05, true) > 0) { Writes.swap(array, index, right, 0.075, true, false); } index++; @@ -64,25 +48,21 @@ private void backward(int[] array, int left, int right) { } } - private void exchange(int[] array, int length) { - int left = 0; - int right = length - 1; + private void exchange(int[] array, int length) { + int left = 0; + int right = length - 1; - while(left < right) { - Highlights.markArray(1, left); - Highlights.markArray(2, right); - Delays.sleep(0.05); - - if(Reads.compareValues(array[left], array[right]) > 0) { - Writes.swap(array, left, right, 0.075, true, false); - } - left++; - right--; - } + while (left < right) { + if (Reads.compareIndices(array, left, right, 0.05, true) > 0) { + Writes.swap(array, left, right, 0.075, true, false); + } + left++; + right--; + } - this.forward(array, 0, length - 2); - this.backward(array, 1, length - 1); - } + this.forward(array, 0, length - 2); + this.backward(array, 1, length - 1); + } @Override public void runSort(int[] array, int sortLength, int bucketCount) { diff --git a/src/main/java/io/github/arrayv/sorts/exchange/OptimizedStoogeSortStudio.java b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedStoogeSortStudio.java index 6b817228..525f6502 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/OptimizedStoogeSortStudio.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/OptimizedStoogeSortStudio.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /** @@ -10,27 +11,17 @@ * and O(n) best case for nearly sorted data * * @author Anonymous0726 - Range flagging optimizations - * @author aphitorite - Sorting network optimizations - * @author EilrahcF - Key ideas / concepts + * @author aphitorite - Sorting network optimizations + * @author EilrahcF - Key ideas / concepts */ - +@SortMeta(listName = "Optimized Stooge (The Studio Version)", runName = "Optimized Stooge Sort (The Studio Version)") public final class OptimizedStoogeSortStudio extends Sort { - public OptimizedStoogeSortStudio(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Optimized Stooge (The Studio version)"); - this.setRunAllSortsName("Optimized Stooge Sort"); - this.setRunSortName("Optistooge Sort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public OptimizedStoogeSortStudio(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private boolean compSwap(int[] array, int a, int b) { - if(Reads.compareIndices(array, a, b, 0.025, true) == 1) { + if (Reads.compareIndices(array, a, b, 0.025, true) == 1) { Writes.swap(array, a, b, 0.075, false, false); return true; } @@ -38,38 +29,39 @@ private boolean compSwap(int[] array, int a, int b) { } private boolean stoogeSort(int[] array, int a, int m, int b, boolean merge) { - if(a >= m) + if (a >= m) return false; - if(b-a == 2) + if (b - a == 2) return this.compSwap(array, a, m); boolean lChange = false; boolean rChange = false; - int a2 = (a+a+b)/3; - int b2 = (a+b+b+2)/3; + int a2 = (a + a + b) / 3; + int b2 = (a + b + b + 2) / 3; - if(m < b2) { + if (m < b2) { lChange = this.stoogeSort(array, a, m, b2, merge); - if(merge) { - rChange = this.stoogeSort(array, Math.max(a+b2-m, a2), b2, b, true); - if(rChange) this.stoogeSort(array, a+b2-m, a2, 2*a2-a, true); - } - else { + if (merge) { + rChange = this.stoogeSort(array, Math.max(a + b2 - m, a2), b2, b, true); + if (rChange) + this.stoogeSort(array, a + b2 - m, a2, 2 * a2 - a, true); + } else { rChange = this.stoogeSort(array, a2, b2, b, false); - if(rChange) this.stoogeSort(array, a, a2, 2*a2-a, true); + if (rChange) + this.stoogeSort(array, a, a2, 2 * a2 - a, true); } - } - else { + } else { rChange = this.stoogeSort(array, a2, m, b, merge); - if(rChange) this.stoogeSort(array, a, a2, a2+b-m, true); + if (rChange) + this.stoogeSort(array, a, a2, a2 + b - m, true); } return lChange || rChange; } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { + @Override + public void runSort(int[] array, int currentLength, int bucketCount) { this.stoogeSort(array, 0, 1, currentLength, false); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/SillySort.java b/src/main/java/io/github/arrayv/sorts/exchange/SillySort.java deleted file mode 100644 index f38b1a40..00000000 --- a/src/main/java/io/github/arrayv/sorts/exchange/SillySort.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.github.arrayv.sorts.exchange; - -import io.github.arrayv.main.ArrayVisualizer; -import io.github.arrayv.sorts.templates.Sort; - -// Written by Tom Duff, and found here: http://home.tiac.net/~cri_d/cri/2001/badsort.html -// from https://stackoverflow.com/questions/2609857/are-there-any-worse-sorting-algorithms-than-bogosort-a-k-a-monkey-sort/ - -public final class SillySort extends Sort { - public SillySort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Silly"); - this.setRunAllSortsName("Silly Sort"); - this.setRunSortName("Sillysort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(150); - this.setBogoSort(false); - } - - private void sillySort(int[] array, int i, int j) { - int m; - - if (i < j) { - /* find the middle of the array */ - m = i + ((j - i) / 2); - - /* - * use this function (recursively) to find put the minimum elements of - * each half into the first elements of each half - */ - this.sillySort(array, i, m); - this.sillySort(array, m + 1, j); - - /* - * Choose the smallest element of the two halves, and put that element in - * the first position - */ - if (Reads.compareValues(array[i], array[m + 1]) >= 0) { - Writes.swap(array, i, m + 1, 1, true, false); - } - - Highlights.markArray(1, i); - Highlights.markArray(2, m + 1); - - this.sillySort(array, i + 1, j); - } - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - this.sillySort(array, 0, currentLength - 1); - } -} diff --git a/src/main/java/io/github/arrayv/sorts/exchange/SlopeSort.java b/src/main/java/io/github/arrayv/sorts/exchange/SlopeSort.java index 908e3390..7968ca47 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/SlopeSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/SlopeSort.java @@ -4,6 +4,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /** @@ -11,6 +12,7 @@ * @author EilrahcF * */ +@SortMeta(name = "Slope") public final class SlopeSort extends Sort { /** @@ -18,15 +20,6 @@ public final class SlopeSort extends Sort { */ public SlopeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - setSortListName("Slope"); - setRunAllSortsName("Slope Sort"); - setRunSortName("Slopesort"); - setCategory("Exchange Sorts"); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(true); - setUnreasonableLimit(16384); - setBogoSort(false); } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/SlowSort.java b/src/main/java/io/github/arrayv/sorts/exchange/SlowSort.java deleted file mode 100644 index 6f01a55a..00000000 --- a/src/main/java/io/github/arrayv/sorts/exchange/SlowSort.java +++ /dev/null @@ -1,47 +0,0 @@ -package io.github.arrayv.sorts.exchange; - -import io.github.arrayv.main.ArrayVisualizer; -import io.github.arrayv.sorts.templates.Sort; - -// Code refactored from Python: http://wiki.c2.com/?SlowSort - -public final class SlowSort extends Sort { - public SlowSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Slow"); - this.setRunAllSortsName("Slow Sort"); - this.setRunSortName("Slowsort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(150); - this.setBogoSort(false); - } - - private void slowSort(int[] A, int i, int j) { - if (i >= j) { - return; - } - - int m = i + ((j - i) / 2); - - this.slowSort(A, i, m); - this.slowSort(A, m + 1, j); - - if (Reads.compareValues(A[m], A[j]) == 1) { - Writes.swap(A, m, j, 1, true, false); - } - - Highlights.markArray(1, j); - Highlights.markArray(2, m); - - this.slowSort(A, i, j - 1); - } - - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - this.slowSort(array, 0, currentLength - 1); - } -} diff --git a/src/main/java/io/github/arrayv/sorts/exchange/StableQuickSort.java b/src/main/java/io/github/arrayv/sorts/exchange/StableQuickSort.java index 6b35907e..bd8cfd5e 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/StableQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/StableQuickSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; import io.github.arrayv.utils.ArrayVList; @@ -29,28 +30,18 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Stable Quick") public final class StableQuickSort extends Sort { private int length; public StableQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Stable Quick"); - this.setRunAllSortsName("Stable Quick Sort"); - this.setRunSortName("Stable Quicksort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } // Author: Rodney Shaghoulian // Github: github.com/RodneyShag - private void copy(ArrayVList list, int [] array, int startIndex) { + private void copy(ArrayVList list, int[] array, int startIndex) { for (int num : list) { Writes.write(array, startIndex++, num, 0.25, false, false); Highlights.markArray(1, startIndex); @@ -59,21 +50,20 @@ private void copy(ArrayVList list, int [] array, int startIndex) { /* Partition/Quicksort "Stable Sort" version using O(n) space */ private int stablePartition(int[] array, int start, int end) { - int pivotValue = array[start]; //poor pivot choice + int pivotValue = array[start]; // poor pivot choice Highlights.markArray(3, start); - ArrayVList leftList = Writes.createArrayList(this.length); + ArrayVList leftList = Writes.createArrayList(this.length); ArrayVList rightList = Writes.createArrayList(this.length); - for (int i = start + 1 ; i <= end; i++) { + for (int i = start + 1; i <= end; i++) { Highlights.markArray(1, i); if (Reads.compareValues(array[i], pivotValue) == -1) { // Writes.mockWrite(end - start, leftList.size(), array[i], 0.25); // Writes.arrayListAdd(leftList, array[i]); leftList.add(array[i], 0.25, false); - } - else { + } else { // Writes.mockWrite(end - start, rightList.size(), array[i], 0.25); // Writes.arrayListAdd(rightList, array[i]); rightList.add(array[i], 0.25, false); @@ -96,7 +86,7 @@ private int stablePartition(int[] array, int start, int end) { return newPivotIndex; } - private void stableQuickSort(int [] array, int start, int end) { + private void stableQuickSort(int[] array, int start, int end) { if (start < end) { int pivotIndex = this.stablePartition(array, start, end); this.stableQuickSort(array, start, pivotIndex - 1); diff --git a/src/main/java/io/github/arrayv/sorts/exchange/StableQuickSortParallel.java b/src/main/java/io/github/arrayv/sorts/exchange/StableQuickSortParallel.java index 7f9bbd70..da10b21b 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/StableQuickSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/StableQuickSortParallel.java @@ -3,6 +3,7 @@ import java.util.Random; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -29,41 +30,38 @@ this software and associated documentation files (the "Software"), to deal in CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ - +@SortMeta(listName = "Stable Quick (Parallel)", runName = "Parallel Stable Quick Sort", unreasonableLimit = 4096) public final class StableQuickSortParallel extends Sort { - public StableQuickSortParallel(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Stable Quick (Parallel)"); - this.setRunAllSortsName("Parallel Stable Quick Sort"); - this.setRunSortName("Parallel Stable Quicksort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public StableQuickSortParallel(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int[] array; private int[] tmp; private class QuickSortInt extends Thread { private int a, b; + QuickSortInt(int a, int b) { this.a = a; this.b = b; } + + @Override public void run() { StableQuickSortParallel.this.quickSortInt(a, b); } } + private class QuickSortExt extends Thread { private int a, b; + QuickSortExt(int a, int b) { this.a = a; this.b = b; } + + @Override public void run() { StableQuickSortParallel.this.quickSortExt(a, b); } @@ -71,16 +69,18 @@ public void run() { private int partitionInt(int a, int b) { Random r = new Random(); - int p = a + r.nextInt(b-a); + int p = a + r.nextInt(b - a); int piv = array[p]; - int j = a, k = b-1; + int j = a, k = b - 1; - while(j < p && Reads.compareValues(array[j], piv) <= 0) j++; - if(j < p) Writes.write(tmp, k--, array[j], 1, false, true); + while (j < p && Reads.compareValues(array[j], piv) <= 0) + j++; + if (j < p) + Writes.write(tmp, k--, array[j], 1, false, true); - for(int i = j+1; i < p; i++) { - if(Reads.compareValues(array[i], piv) <= 0) + for (int i = j + 1; i < p; i++) { + if (Reads.compareValues(array[i], piv) <= 0) Writes.write(array, j++, array[i], 1, true, false); else { @@ -88,8 +88,8 @@ private int partitionInt(int a, int b) { Writes.write(tmp, k--, array[i], 1, false, true); } } - for(int i = p+1; i < b; i++) { - if(Reads.compareValues(array[i], piv) < 0) + for (int i = p + 1; i < b; i++) { + if (Reads.compareValues(array[i], piv) < 0) Writes.write(array, j++, array[i], 1, true, false); else { @@ -101,29 +101,32 @@ private int partitionInt(int a, int b) { return j; } + private int partitionExt(int a, int b) { Random r = new Random(); - int p = a + r.nextInt(b-a); + int p = a + r.nextInt(b - a); int piv = tmp[p]; - int j = b-1, k = a; + int j = b - 1, k = a; - while(j > p && Reads.compareValues(tmp[j], piv) > 0) j--; - if(j > p) Writes.write(array, k++, tmp[j], 1, true, false); + while (j > p && Reads.compareValues(tmp[j], piv) > 0) + j--; + if (j > p) + Writes.write(array, k++, tmp[j], 1, true, false); - for(int i = j-1; i > p; i--) { - if(Reads.compareValues(tmp[i], piv) > 0) { + for (int i = j - 1; i > p; i--) { + if (Reads.compareValues(tmp[i], piv) > 0) { Highlights.markArray(2, j); Writes.write(tmp, j--, tmp[i], 1, false, true); - } - else Writes.write(array, k++, tmp[i], 1, true, false); + } else + Writes.write(array, k++, tmp[i], 1, true, false); } - for(int i = p-1; i >= a; i--) { - if(Reads.compareValues(tmp[i], piv) >= 0) { + for (int i = p - 1; i >= a; i--) { + if (Reads.compareValues(tmp[i], piv) >= 0) { Highlights.markArray(2, j); Writes.write(tmp, j--, tmp[i], 1, false, true); - } - else Writes.write(array, k++, tmp[i], 1, true, false); + } else + Writes.write(array, k++, tmp[i], 1, true, false); } Writes.write(array, k, piv, 1, true, false); @@ -131,14 +134,15 @@ private int partitionExt(int a, int b) { } private void quickSortInt(int a, int b) { - int len = b-a; + int len = b - a; - if(len < 2) return; + if (len < 2) + return; int p = this.partitionInt(a, b); - QuickSortInt left = new QuickSortInt(a, p); - QuickSortExt right = new QuickSortExt(p+1, b); + QuickSortInt left = new QuickSortInt(a, p); + QuickSortExt right = new QuickSortExt(p + 1, b); left.start(); right.start(); @@ -149,18 +153,20 @@ private void quickSortInt(int a, int b) { Thread.currentThread().interrupt(); } } + private void quickSortExt(int a, int b) { - int len = b-a; + int len = b - a; - if(len < 2) { - if(len == 1) Writes.write(array, a, tmp[a], 1, true, false); + if (len < 2) { + if (len == 1) + Writes.write(array, a, tmp[a], 1, true, false); return; } int p = this.partitionExt(a, b); - QuickSortInt left = new QuickSortInt(a, p); - QuickSortExt right = new QuickSortExt(p+1, b); + QuickSortInt left = new QuickSortInt(a, p); + QuickSortExt right = new QuickSortExt(p + 1, b); left.start(); right.start(); @@ -172,11 +178,11 @@ private void quickSortExt(int a, int b) { } } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { this.array = array; this.tmp = Writes.createExternalArray(length); this.quickSortInt(0, length); Writes.deleteExternalArray(tmp); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/SwaplessBubbleSort.java b/src/main/java/io/github/arrayv/sorts/exchange/SwaplessBubbleSort.java index 2f1902cf..1ac915f9 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/SwaplessBubbleSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/SwaplessBubbleSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,20 +29,10 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Swapless Bubble") public final class SwaplessBubbleSort extends Sort { public SwaplessBubbleSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Swapless Bubble"); - this.setRunAllSortsName("Swapless Bubble Sort"); - this.setRunSortName("Swapless Bubblesort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override @@ -56,7 +47,8 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.write(array, j - 1, array[j], 0.075, false, false); last = j; } else { - // This code will also handle incrementing pos so this optimization works next time + // This code will also handle incrementing pos so this optimization works next + // time if (pos + 1 < j) Writes.write(array, j - 1, comp, 0.075, false, false); pos = j; diff --git a/src/main/java/io/github/arrayv/sorts/exchange/TableSort.java b/src/main/java/io/github/arrayv/sorts/exchange/TableSort.java index ccab4c1b..42d18b01 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/TableSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/TableSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,21 +29,11 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Table") public final class TableSort extends Sort { - public TableSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Table"); - this.setRunAllSortsName("Table Sort"); - this.setRunSortName("Tablesort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public TableSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private boolean stableComp(int[] array, int[] table, int a, int b) { int comp = Reads.compareIndices(array, table[a], table[b], 0.5, true); @@ -51,15 +42,15 @@ private boolean stableComp(int[] array, int[] table, int a, int b) { } private void medianOfThree(int[] array, int[] table, int a, int b) { - int m = a+(b-1-a)/2; + int m = a + (b - 1 - a) / 2; - if(this.stableComp(array, table, a, m)) + if (this.stableComp(array, table, a, m)) Writes.swap(table, a, m, 1, true, true); - if(this.stableComp(array, table, m, b-1)) { - Writes.swap(table, m, b-1, 1, true, true); + if (this.stableComp(array, table, m, b - 1)) { + Writes.swap(table, m, b - 1, 1, true, true); - if(this.stableComp(array, table, a, m)) + if (this.stableComp(array, table, a, m)) return; } @@ -67,49 +58,53 @@ private void medianOfThree(int[] array, int[] table, int a, int b) { } private int partition(int[] array, int[] table, int a, int b, int p) { - int i = a-1, j = b; + int i = a - 1, j = b; Highlights.markArray(3, p); - while(true) { - do i++; - while(i < j && !this.stableComp(array, table, i, p)); + while (true) { + do + i++; + while (i < j && !this.stableComp(array, table, i, p)); - do j--; - while(j >= i && this.stableComp(array, table, j, p)); + do + j--; + while (j >= i && this.stableComp(array, table, j, p)); - if(i < j) Writes.swap(table, i, j, 1, true, true); - else return j; - } - } + if (i < j) + Writes.swap(table, i, j, 1, true, true); + else + return j; + } + } private void quickSort(int[] array, int[] table, int a, int b) { - if(b-a < 3) { - if(b-a == 2 && this.stableComp(array, table, a, a+1)) - Writes.swap(table, a, a+1, 1, true, true); + if (b - a < 3) { + if (b - a == 2 && this.stableComp(array, table, a, a + 1)) + Writes.swap(table, a, a + 1, 1, true, true); return; } this.medianOfThree(array, table, a, b); - int p = this.partition(array, table, a+1, b, a); + int p = this.partition(array, table, a + 1, b, a); Writes.swap(table, a, p, 1, true, true); this.quickSort(array, table, a, p); - this.quickSort(array, table, p+1, b); + this.quickSort(array, table, p + 1, b); } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { + @Override + public void runSort(int[] array, int currentLength, int bucketCount) { int[] table = Writes.createExternalArray(currentLength); - for(int i = 0; i < currentLength; i++) + for (int i = 0; i < currentLength; i++) Writes.write(table, i, i, 0.5, true, true); - this.quickSort(array, table, 0, currentLength); + this.quickSort(array, table, 0, currentLength); Highlights.clearMark(3); - for(int i = 0; i < table.length; i++) { + for (int i = 0; i < table.length; i++) { Highlights.markArray(2, i); - if(Reads.compareOriginalValues(i, table[i]) != 0) { + if (Reads.compareOriginalValues(i, table[i]) != 0) { int t = array[i]; int j = i, next = table[i]; @@ -119,8 +114,7 @@ public void runSort(int[] array, int currentLength, int bucketCount) { j = next; next = table[next]; - } - while(Reads.compareOriginalValues(next, i) != 0); + } while (Reads.compareOriginalValues(next, i) != 0); Writes.write(array, j, t, 1, true, false); Writes.write(table, j, j, 1, true, true); @@ -128,5 +122,5 @@ public void runSort(int[] array, int currentLength, int bucketCount) { } Writes.deleteExternalArray(table); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortIterative.java b/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortIterative.java index 6d4a3361..96cbe2c6 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortIterative.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -27,40 +28,30 @@ this software and associated documentation files (the "Software"), to deal in CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ - +@SortMeta(listName = "3-Smooth Comb (Iterative)", runName = "Iterative 3-Smooth Comb") public final class ThreeSmoothCombSortIterative extends Sort { - public ThreeSmoothCombSortIterative(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("3-Smooth Comb (Iterative)"); - this.setRunAllSortsName("Iterative 3-Smooth Comb Sort"); - this.setRunSortName("Iterative 3-Smooth Combsort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public ThreeSmoothCombSortIterative(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } - private void compSwap(int[] array, int a, int b) { - if(Reads.compareIndices(array, a, b, 0.5, true) == 1) - Writes.swap(array, a, b, 0.5, true, false); - } + private void compSwap(int[] array, int a, int b) { + if (Reads.compareIndices(array, a, b, 0.5, true) == 1) + Writes.swap(array, a, b, 0.5, true, false); + } - @Override - public void runSort(int[] array, int length, int bucketCount) { - int pow2 = (int)(Math.log(length-1)/Math.log(2)); + @Override + public void runSort(int[] array, int length, int bucketCount) { + int pow2 = (int) (Math.log(length - 1) / Math.log(2)); - for(int k = pow2; k >= 0; k--) { - int pow3 = (int)((Math.log(length) - k*Math.log(2))/Math.log(3)); + for (int k = pow2; k >= 0; k--) { + int pow3 = (int) ((Math.log(length) - k * Math.log(2)) / Math.log(3)); - for(int j = pow3; j >= 0; j--) { - int gap = (int)(Math.pow(2, k)*Math.pow(3, j)); + for (int j = pow3; j >= 0; j--) { + int gap = (int) (Math.pow(2, k) * Math.pow(3, j)); - for(int i = 0; i+gap < length; i++) - this.compSwap(array, i, i+gap); - } - } + for (int i = 0; i + gap < length; i++) + this.compSwap(array, i, i + gap); + } } + } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortParallel.java b/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortParallel.java index 5e6722c2..ec7bccb5 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortParallel.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -25,31 +26,24 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(listName = "3-Smooth Comb (Parallel)", runName = "Parallel 3-Smooth Comb", unreasonableLimit = 4096) public final class ThreeSmoothCombSortParallel extends Sort { - public ThreeSmoothCombSortParallel(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("3-Smooth Comb (Parallel)"); - this.setRunAllSortsName("Parallel 3-Smooth Comb Sort"); - this.setRunSortName("Parallel 3-Smooth Combsort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public ThreeSmoothCombSortParallel(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int[] array; private class RecursiveComb extends Thread { private int pos, gap, end; + RecursiveComb(int pos, int gap, int end) { this.pos = pos; this.gap = gap; this.end = end; } + + @Override public void run() { ThreeSmoothCombSortParallel.this.recursiveComb(pos, gap, end); } @@ -57,21 +51,25 @@ public void run() { private class PowerOfThree extends Thread { private int pos, gap, end; + PowerOfThree(int pos, int gap, int end) { this.pos = pos; this.gap = gap; this.end = end; } + + @Override public void run() { ThreeSmoothCombSortParallel.this.powerOfThree(pos, gap, end); } } - private void recursiveComb(int pos, int gap, int end) { - if(pos+gap > end) return; + private void recursiveComb(int pos, int gap, int end) { + if (pos + gap > end) + return; - RecursiveComb a = new RecursiveComb(pos, gap*2, end); - RecursiveComb b = new RecursiveComb(pos+gap, gap*2, end); + RecursiveComb a = new RecursiveComb(pos, gap * 2, end); + RecursiveComb b = new RecursiveComb(pos + gap, gap * 2, end); a.start(); b.start(); @@ -85,11 +83,12 @@ private void recursiveComb(int pos, int gap, int end) { } private void powerOfThree(int pos, int gap, int end) { - if(pos+gap > end) return; + if (pos + gap > end) + return; - PowerOfThree a = new PowerOfThree(pos, gap*3, end); - PowerOfThree b = new PowerOfThree(pos+gap, gap*3, end); - PowerOfThree c = new PowerOfThree(pos+2*gap, gap*3, end); + PowerOfThree a = new PowerOfThree(pos, gap * 3, end); + PowerOfThree b = new PowerOfThree(pos + gap, gap * 3, end); + PowerOfThree c = new PowerOfThree(pos + 2 * gap, gap * 3, end); a.start(); b.start(); c.start(); @@ -101,14 +100,14 @@ private void powerOfThree(int pos, int gap, int end) { } catch (InterruptedException e) { Thread.currentThread().interrupt(); } - for(int i = pos; i+gap < end; i+=gap) - if(Reads.compareIndices(this.array, i, i+gap, 0.5, true) == 1) - Writes.swap(this.array, i, i+gap, 0.5, false, false); + for (int i = pos; i + gap < end; i += gap) + if (Reads.compareIndices(this.array, i, i + gap, 0.5, true) == 1) + Writes.swap(this.array, i, i + gap, 0.5, false, false); } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { this.array = array; - this.recursiveComb(0, 1, length); - } + this.recursiveComb(0, 1, length); + } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortRecursive.java b/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortRecursive.java index 3e3bfc01..462315a3 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/ThreeSmoothCombSortRecursive.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -25,42 +26,34 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(listName = "3-Smooth Comb (Recursive)", runName = "Recursive 3-Smooth Comb") public final class ThreeSmoothCombSortRecursive extends Sort { public ThreeSmoothCombSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("3-Smooth Comb (Recursive)"); - this.setRunAllSortsName("Recursive 3-Smooth Comb Sort"); - this.setRunSortName("Recursive 3-Smooth Combsort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void recursiveComb(int[] array, int pos, int gap, int end) { - if(pos+gap > end) return; + if (pos + gap > end) + return; - this.recursiveComb(array, pos, gap*2, end); - this.recursiveComb(array, pos+gap, gap*2, end); + this.recursiveComb(array, pos, gap * 2, end); + this.recursiveComb(array, pos + gap, gap * 2, end); - this.powerOfThree(array, pos, gap, end); - } + this.powerOfThree(array, pos, gap, end); + } - private void powerOfThree(int[] array, int pos, int gap, int end) { - if(pos+gap > end) return; + private void powerOfThree(int[] array, int pos, int gap, int end) { + if (pos + gap > end) + return; - this.powerOfThree(array, pos, gap*3, end); - this.powerOfThree(array, pos+gap, gap*3, end); - this.powerOfThree(array, pos+2*gap, gap*3, end); + this.powerOfThree(array, pos, gap * 3, end); + this.powerOfThree(array, pos + gap, gap * 3, end); + this.powerOfThree(array, pos + 2 * gap, gap * 3, end); - for(int i = pos; i+gap < end; i+=gap) - if(Reads.compareIndices(array, i, i+gap, 0.5, true) == 1) - Writes.swap(array, i, i+gap, 0.5, false, false); - } + for (int i = pos; i + gap < end; i += gap) + if (Reads.compareIndices(array, i, i + gap, 0.5, true) == 1) + Writes.swap(array, i, i + gap, 0.5, false, false); + } @Override public void runSort(int[] array, int length, int bucketCount) { diff --git a/src/main/java/io/github/arrayv/sorts/exchange/UnoptimizedBubbleSort.java b/src/main/java/io/github/arrayv/sorts/exchange/UnoptimizedBubbleSort.java index e1ecdfc2..e0aa82fe 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/UnoptimizedBubbleSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/UnoptimizedBubbleSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,37 +29,23 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Unoptimized Bubble") public final class UnoptimizedBubbleSort extends Sort { public UnoptimizedBubbleSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Unoptimized Bubble"); - this.setRunAllSortsName("Unoptimized Bubble Sort"); - this.setRunSortName("Unoptimized Bubblesort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { boolean sorted = false; - while(!sorted) { + while (!sorted) { sorted = true; - for(int i = 0; i < sortLength - 1; i++) { - if(Reads.compareValues(array[i], array[i + 1]) == 1){ + for (int i = 0; i < sortLength - 1; i++) { + if (Reads.compareIndices(array, i, i + 1, 0.05, true) == 1) { Writes.swap(array, i, i + 1, 0.075, true, false); sorted = false; } - - Highlights.markArray(1, i); - Highlights.markArray(2, i + 1); - Delays.sleep(0.05); } } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/UnoptimizedCocktailShakerSort.java b/src/main/java/io/github/arrayv/sorts/exchange/UnoptimizedCocktailShakerSort.java index b46d257c..2abc85bb 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/UnoptimizedCocktailShakerSort.java +++ b/src/main/java/io/github/arrayv/sorts/exchange/UnoptimizedCocktailShakerSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.exchange; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,44 +29,24 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Unoptimized Cocktail Shaker") public final class UnoptimizedCocktailShakerSort extends Sort { public UnoptimizedCocktailShakerSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Unoptimized Cocktail Shaker"); - this.setRunAllSortsName("Unoptimized Cocktail Shaker Sort"); - this.setRunSortName("Unoptimized Cocktailsort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void cocktailShaker(int[] array, int start, int end, double sleep) { int i = start; - while(i < ((end / 2) + start)) { - for(int j = i; j < end + start - i - 1; j++) { - if(Reads.compareValues(array[j], array[j + 1]) == 1) { + while (i < ((end / 2) + start)) { + for (int j = i; j < end + start - i - 1; j++) { + if (Reads.compareIndices(array, j, j + 1, sleep / 2, true) == 1) { Writes.swap(array, j, j + 1, sleep, true, false); } - - Highlights.markArray(1, j); - Highlights.markArray(2, j + 1); - - Delays.sleep(sleep / 2); } - for(int j = end + start - i - 1; j > i; j--){ - if(Reads.compareValues(array[j], array[j - 1]) == -1) { + for (int j = end + start - i - 1; j > i; j--) { + if (Reads.compareIndices(array, j, j - 1, sleep / 2, true) == -1) { Writes.swap(array, j, j - 1, sleep, true, false); } - - Highlights.markArray(1, j); - Highlights.markArray(2, j - 1); - - Delays.sleep(sleep / 2); } i++; diff --git a/src/main/java/io/github/arrayv/sorts/exchange/package-info.java b/src/main/java/io/github/arrayv/sorts/exchange/package-info.java new file mode 100644 index 00000000..ad8da352 --- /dev/null +++ b/src/main/java/io/github/arrayv/sorts/exchange/package-info.java @@ -0,0 +1,2 @@ +@io.github.arrayv.sortdata.SortPackageMeta(category = "Exchange Sorts") +package io.github.arrayv.sorts.exchange; diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/AdaptiveGrailSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/AdaptiveGrailSort.java index 5f934059..3b0c00c2 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/AdaptiveGrailSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/AdaptiveGrailSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -54,19 +55,10 @@ * * @author aphitorite */ +@SortMeta(name = "Adaptive Grail") public final class AdaptiveGrailSort extends Sort { public AdaptiveGrailSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Adaptive Grail"); - this.setRunAllSortsName("Adaptive Grail Sort (Block Merge Sort)"); - this.setRunSortName("Adaptive Grailsort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } enum Subarray { @@ -77,50 +69,52 @@ enum Subarray { private int minRun; private void multiSwap(int[] array, int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(array, a+i, b+i, 1, true, false); + for (int i = 0; i < len; i++) + Writes.swap(array, a + i, b + i, 1, true, false); } - //changes len sized blocks order ABC -> BCA + // changes len sized blocks order ABC -> BCA private void multiTriSwap(int[] array, int a, int b, int c, int len) { Highlights.clearMark(2); - for(int i = 0; i < len; i++) { - int temp = array[a+i]; - Writes.write(array, a+i, array[b+i], 0.333, true, false); - Writes.write(array, b+i, array[c+i], 0.333, true, false); - Writes.write(array, c+i, temp, 0.333, true, false); + for (int i = 0; i < len; i++) { + int temp = array[a + i]; + Writes.write(array, a + i, array[b + i], 0.333, true, false); + Writes.write(array, b + i, array[c + i], 0.333, true, false); + Writes.write(array, c + i, temp, 0.333, true, false); } } private void insertTo(int[] array, int a, int b) { Highlights.clearMark(2); int temp = array[a]; - while(a > b) Writes.write(array, a, array[(a--)-1], 0.5, true, false); + while (a > b) + Writes.write(array, a, array[(a--) - 1], 0.5, true, false); Writes.write(array, b, temp, 0.5, true, false); } private void insertToBW(int[] array, int a, int b) { Highlights.clearMark(2); int temp = array[a]; - while(a < b) Writes.write(array, a, array[(a++)+1], 0.5, true, false); + while (a < b) + Writes.write(array, a, array[(a++) + 1], 0.5, true, false); Writes.write(array, a, temp, 0.5, true, false); } private void shift(int[] array, int a, int m, int b) { - while(m < b) Writes.swap(array, a++, m++, 1, true, false); + while (m < b) + Writes.swap(array, a++, m++, 1, true, false); } private void rotate(int[] array, int a, int m, int b) { - int l = m-a, r = b-m; + int l = m - a, r = b - m; - while(l > 1 && r > 1) { - if(r < l) { - this.multiSwap(array, m-r, m, r); + while (l > 1 && r > 1) { + if (r < l) { + this.multiSwap(array, m - r, m, r); b -= r; m -= r; l -= r; - } - else { + } else { this.multiSwap(array, a, m, l); a += l; m += l; @@ -129,104 +123,102 @@ private void rotate(int[] array, int a, int m, int b) { } Highlights.clearMark(2); - if(r == 1) this.insertTo(array, m, a); - else if(l == 1) this.insertToBW(array, a, b-1); + if (r == 1) + this.insertTo(array, m, a); + else if (l == 1) + this.insertToBW(array, a, b - 1); } private int leftBinarySearch(int[] array, int a, int b, int val) { - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; - if(Reads.compareValues(val, array[m]) <= 0) + if (Reads.compareValues(val, array[m]) <= 0) b = m; else - a = m+1; + a = m + 1; } return a; } private int rightBinarySearch(int[] array, int a, int b, int val) { - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; - if(Reads.compareValues(val, array[m]) < 0) + if (Reads.compareValues(val, array[m]) < 0) b = m; else - a = m+1; + a = m + 1; } return a; } private int buildUniqueRun(int[] array, int a, int n) { - int nKeys = 1, i = a+1; + int nKeys = 1, i = a + 1; - //build run at start - if(Reads.compareIndices(array, i-1, i, 1, true) == -1){ + // build run at start + if (Reads.compareIndices(array, i - 1, i, 1, true) == -1) { i++; nKeys++; - while(nKeys < n && Reads.compareIndices(array, i-1, i, 1, true) == -1) { + while (nKeys < n && Reads.compareIndices(array, i - 1, i, 1, true) == -1) { i++; nKeys++; } - } - else if(Reads.compareIndices(array, i-1, i, 1, true) == 1) { + } else if (Reads.compareIndices(array, i - 1, i, 1, true) == 1) { i++; nKeys++; - while(nKeys < n && Reads.compareIndices(array, i-1, i, 1, true) == 1) { + while (nKeys < n && Reads.compareIndices(array, i - 1, i, 1, true) == 1) { i++; nKeys++; } - Writes.reversal(array, a, i-1, 1, true, false); + Writes.reversal(array, a, i - 1, 1, true, false); } return nKeys; } private int buildUniqueRunBW(int[] array, int b, int n) { - int nKeys = 1, i = b-1; + int nKeys = 1, i = b - 1; - //build run at end - if(Reads.compareIndices(array, i-1, i, 1, true) == -1){ + // build run at end + if (Reads.compareIndices(array, i - 1, i, 1, true) == -1) { i--; nKeys++; - while(nKeys < n && Reads.compareIndices(array, i-1, i, 1, true) == -1) { + while (nKeys < n && Reads.compareIndices(array, i - 1, i, 1, true) == -1) { i--; nKeys++; } - } - else if(Reads.compareIndices(array, i-1, i, 1, true) == 1) { + } else if (Reads.compareIndices(array, i - 1, i, 1, true) == 1) { i--; nKeys++; - while(nKeys < n && Reads.compareIndices(array, i-1, i, 1, true) == 1) { + while (nKeys < n && Reads.compareIndices(array, i - 1, i, 1, true) == 1) { i--; nKeys++; } - Writes.reversal(array, i, b-1, 1, true, false); + Writes.reversal(array, i, b - 1, 1, true, false); } return nKeys; } private int findKeys(int[] array, int a, int b, int nKeys, int n) { - int p = a, pEnd = a+nKeys; + int p = a, pEnd = a + nKeys; Highlights.clearMark(2); - for(int i = pEnd; i < b && nKeys < n; i++) { - Highlights.markArray(1, i); - Delays.sleep(1); + for (int i = pEnd; i < b && nKeys < n; i++) { int loc = this.leftBinarySearch(array, p, pEnd, array[i]); - if(pEnd == loc || Reads.compareValues(array[i], array[loc]) != 0) { + if (pEnd == loc || Reads.compareIndices(array, i, loc, 1, true) != 0) { this.rotate(array, p, pEnd, i); - int inc = i-pEnd; - loc += inc; - p += inc; + int inc = i - pEnd; + loc += inc; + p += inc; pEnd += inc; this.insertTo(array, pEnd, loc); @@ -238,45 +230,48 @@ private int findKeys(int[] array, int a, int b, int nKeys, int n) { return nKeys; } - //special thanks to @MP for this idea + // special thanks to @MP for this idea private int findKeysBW(int[] array, int a, int b, int nKeys, int n) { - int p = b-nKeys, pEnd = b; + int p = b - nKeys, pEnd = b; Highlights.clearMark(2); - for(int i = p-1; i >= a && nKeys < n; i--) { + for (int i = p - 1; i >= a && nKeys < n; i--) { Highlights.markArray(1, i); Delays.sleep(1); int loc = this.leftBinarySearch(array, p, pEnd, array[i]); - if(pEnd == loc || Reads.compareValues(array[i], array[loc]) != 0) { - this.rotate(array, i+1, p, pEnd); - int inc = p-(i+1); - loc -= inc; + if (pEnd == loc || Reads.compareValues(array[i], array[loc]) != 0) { + this.rotate(array, i + 1, p, pEnd); + int inc = p - (i + 1); + loc -= inc; pEnd -= inc; - p -= inc+1; + p -= inc + 1; nKeys++; - this.insertToBW(array, i, loc-1); + this.insertToBW(array, i, loc - 1); } } this.rotate(array, p, pEnd, b); return nKeys; } - //instead of insertion level find & create runs divisible by minRun + // instead of insertion level find & create runs divisible by minRun private void buildRuns(int[] array, int a, int b) { - int i = a+1, j = a; + int i = a + 1, j = a; - while(i < b) { - if(Reads.compareIndices(array, i-1, i++, 1, true) == 1) { - while(i < b && Reads.compareIndices(array, i-1, i, 1, true) == 1) i++; - Writes.reversal(array, j, i-1, 1, true, false); - } - else while(i < b && Reads.compareIndices(array, i-1, i, 1, true) <= 0) i++; + while (i < b) { + if (Reads.compareIndices(array, i - 1, i++, 1, true) == 1) { + while (i < b && Reads.compareIndices(array, i - 1, i, 1, true) == 1) + i++; + Writes.reversal(array, j, i - 1, 1, true, false); + } else + while (i < b && Reads.compareIndices(array, i - 1, i, 1, true) <= 0) + i++; - if(i < b) j = i - (i-j-1)%this.minRun - 1;//a%b, if(a%b == 0) -> a = b + if (i < b) + j = i - (i - j - 1) % this.minRun - 1;// a%b, if(a%b == 0) -> a = b - while(i-j < this.minRun && i < b) { + while (i - j < this.minRun && i < b) { this.insertTo(array, i, this.rightBinarySearch(array, j, i, array[i])); i++; } @@ -285,84 +280,88 @@ private void buildRuns(int[] array, int a, int b) { } private void binaryInsertion(int[] array, int a, int b) { - for(int i = a+1; i < b; i++) + for (int i = a + 1; i < b; i++) this.insertTo(array, i, this.rightBinarySearch(array, a, i, array[i])); } private void mergeWithBufRest(int[] array, int a, int m, int b, int p, int pLen) { int i = 0, j = m, k = a; - while(i < pLen && j < b) { - if(Reads.compareValues(array[p+i], array[j]) <= 0) - Writes.swap(array, k++, p+(i++), 1, true, false); + while (i < pLen && j < b) { + if (Reads.compareValues(array[p + i], array[j]) <= 0) + Writes.swap(array, k++, p + (i++), 1, true, false); else Writes.swap(array, k++, j++, 1, true, false); } - while(i < pLen) Writes.swap(array, k++, p+(i++), 1, true, false); + while (i < pLen) + Writes.swap(array, k++, p + (i++), 1, true, false); } private void mergeWithBuf(int[] array, int a, int m, int b, int p) { - int l = m-a; + int l = m - a; this.multiSwap(array, p, a, l); this.mergeWithBufRest(array, a, m, b, p, l); } private void mergeWithBufBW(int[] array, int a, int m, int b, int p) { - int pLen = b-m; + int pLen = b - m; this.multiSwap(array, m, p, pLen); - int i = pLen-1, j = m-1, k = b-1; + int i = pLen - 1, j = m - 1, k = b - 1; - while(i >= 0 && j >= a) { - if(Reads.compareValues(array[p+i], array[j]) >= 0) - Writes.swap(array, k--, p+(i--), 1, true, false); + while (i >= 0 && j >= a) { + if (Reads.compareValues(array[p + i], array[j]) >= 0) + Writes.swap(array, k--, p + (i--), 1, true, false); else Writes.swap(array, k--, j--, 1, true, false); } - while(i >= 0) Writes.swap(array, k--, p+(i--), 1, true, false); + while (i >= 0) + Writes.swap(array, k--, p + (i--), 1, true, false); } private void inPlaceMerge(int[] array, int a, int m, int b) { int i = a, j = m, k; - while(i < j && j < b) { - if(Reads.compareValues(array[i], array[j]) > 0) { - k = this.leftBinarySearch(array, j+1, b, array[i]); + while (i < j && j < b) { + if (Reads.compareValues(array[i], array[j]) > 0) { + k = this.leftBinarySearch(array, j + 1, b, array[i]); this.rotate(array, i, j, k); - i += k-j; + i += k - j; j = k; - } - else i++; + } else + i++; } } private void inPlaceMergeBW(int[] array, int a, int m, int b) { - int i = m-1, j = b-1, k; + int i = m - 1, j = b - 1, k; - while(j > i && i >= a){ - if(Reads.compareValues(array[i], array[j]) > 0) { + while (j > i && i >= a) { + if (Reads.compareValues(array[i], array[j]) > 0) { k = this.rightBinarySearch(array, a, i, array[j]); - this.rotate(array, k, i+1, j+1); + this.rotate(array, k, i + 1, j + 1); - j -= (i+1)-k; - i = k-1; - } - else j--; + j -= (i + 1) - k; + i = k - 1; + } else + j--; } } private void mergeWithoutBuf(int[] array, int a, int m, int b) { - if(m-a > b-m) this.inPlaceMergeBW(array, a, m, b); - else this.inPlaceMerge(array, a, m, b); + if (m - a > b - m) + this.inPlaceMergeBW(array, a, m, b); + else + this.inPlaceMerge(array, a, m, b); } private boolean checkSorted(int[] array, int a, int m, int b) { - return Reads.compareValues(array[m-1], array[m]) > 0; + return Reads.compareValues(array[m - 1], array[m]) > 0; } private boolean checkReverseBounds(int[] array, int a, int m, int b) { - if(Reads.compareValues(array[a], array[b-1]) == 1) { + if (Reads.compareValues(array[a], array[b - 1]) == 1) { this.rotate(array, a, m, b); return false; } @@ -372,243 +371,255 @@ private boolean checkReverseBounds(int[] array, int a, int m, int b) { private boolean checkBounds(int[] array, int a, int m, int b) { return this.checkSorted(array, a, m, b) - && this.checkReverseBounds(array, a, m, b); + && this.checkReverseBounds(array, a, m, b); } private Subarray grailGetSubarray(int[] array, int t, int mKey) { - if(Reads.compareValues(array[t], array[mKey]) < 0) + if (Reads.compareValues(array[t], array[mKey]) < 0) return Subarray.LEFT; - else return Subarray.RIGHT; + else + return Subarray.RIGHT; } - //returns mKey final position + // returns mKey final position private int blockSelectSort(int[] array, int p, int t, int r, int d, int lCount, int bCount, int bLen) { int mKey = lCount; - for(int j = 0, k = lCount+1; j < k-1; j++) { + for (int j = 0, k = lCount + 1; j < k - 1; j++) { int min = j; - for(int i = Math.max(lCount-r, j+1); i < k; i++) { - int comp = Reads.compareIndices(array, p+d + i*bLen, p+d + min*bLen, 2, true); + for (int i = Math.max(lCount - r, j + 1); i < k; i++) { + int comp = Reads.compareIndices(array, p + d + i * bLen, p + d + min * bLen, 2, true); - if(comp < 0 || (comp == 0 && Reads.compareValues(array[t+i], array[t+min]) < 0)) + if (comp < 0 || (comp == 0 && Reads.compareValues(array[t + i], array[t + min]) < 0)) min = i; } - if(min != j) { - this.multiSwap(array, p + j*bLen, p + min*bLen, bLen); - Writes.swap(array, t+j, t+min, 1, true, false); + if (min != j) { + this.multiSwap(array, p + j * bLen, p + min * bLen, bLen); + Writes.swap(array, t + j, t + min, 1, true, false); - if(k < bCount && min == k-1) k++; + if (k < bCount && min == k - 1) + k++; } - if(min == mKey) mKey = j; + if (min == mKey) + mKey = j; } - return t+mKey; + return t + mKey; } - //special thanks to @Anonymous0726 for this idea + // special thanks to @Anonymous0726 for this idea private void grailSortKeys(int[] array, int b, int p, int mKey) { Writes.swap(array, p, mKey, 1, true, false); - int i = mKey, j = i+1, k = p+1; + int i = mKey, j = i + 1, k = p + 1; - while(j < b) { - if(Reads.compareValues(array[j], array[p]) < 0) + while (j < b) { + if (Reads.compareValues(array[j], array[p]) < 0) Writes.swap(array, i++, j, 1, true, false); - else Writes.swap(array, k++, j, 1, true, false); + else + Writes.swap(array, k++, j, 1, true, false); j++; } - this.multiSwap(array, i, p, b-i); + this.multiSwap(array, i, p, b - i); } private void grailSortKeysWithoutBuf(int[] array, int b, int mKey) { - int i = mKey, j = i+1; + int i = mKey, j = i + 1; - while(j < b) { - if(Reads.compareValues(array[j], array[i]) < 0) + while (j < b) { + if (Reads.compareValues(array[j], array[i]) < 0) this.insertTo(array, j, i++); j++; } } - //special thanks to @Anonymous0726 for this idea + // special thanks to @Anonymous0726 for this idea private int grailMergeBlocks(int[] array, int a, int m, int b, int p) { int i = a, j = m; - while(i < m && j < b) { - if(Reads.compareValues(array[i], array[j]) <= 0) + while (i < m && j < b) { + if (Reads.compareValues(array[i], array[j]) <= 0) Writes.swap(array, p++, i++, 1, true, false); - else Writes.swap(array, p++, j++, 1, true, false); + else + Writes.swap(array, p++, j++, 1, true, false); } - if(i > p) while(i < m) Writes.swap(array, p++, i++, 1, true, false); + if (i > p) + while (i < m) + Writes.swap(array, p++, i++, 1, true, false); return j; } - //same as grailMergeBlocks() except reverses equal items order + // same as grailMergeBlocks() except reverses equal items order private int grailMergeBlocksRev(int[] array, int a, int m, int b, int p) { int i = a, j = m; - while(i < m && j < b) { - if(Reads.compareValues(array[i], array[j]) < 0) + while (i < m && j < b) { + if (Reads.compareValues(array[i], array[j]) < 0) Writes.swap(array, p++, i++, 1, true, false); - else Writes.swap(array, p++, j++, 1, true, false); + else + Writes.swap(array, p++, j++, 1, true, false); } - if(i > p) while(i < m) Writes.swap(array, p++, i++, 1, true, false); + if (i > p) + while (i < m) + Writes.swap(array, p++, i++, 1, true, false); return j; } - //is never called if m-a || b-m <= bLen - //should never be called if (m-a)%bLen != 0 + // is never called if m-a || b-m <= bLen + // should never be called if (m-a)%bLen != 0 private void grailBlockMerge(int[] array, int a, int m, int b, int t, int p, int bLen) { - int b1 = b - (b-m-1)%bLen - 1, - i = a+bLen, j = a, key = t-1, - lCount = (m-i)/bLen, bCount = (b1-i)/bLen, l = -1, r = lCount-1; + int b1 = b - (b - m - 1) % bLen - 1, + i = a + bLen, j = a, key = t - 1, + lCount = (m - i) / bLen, bCount = (b1 - i) / bLen, l = -1, r = lCount - 1; - this.multiTriSwap(array, p, m-bLen, a, bLen); - this.insertToBW(array, t, t+lCount-1); + this.multiTriSwap(array, p, m - bLen, a, bLen); + this.insertToBW(array, t, t + lCount - 1); - int mKey = this.blockSelectSort(array, i, t, 1, bLen-1, lCount, bCount, bLen); + int mKey = this.blockSelectSort(array, i, t, 1, bLen - 1, lCount, bCount, bLen); Subarray frag = Subarray.LEFT; - while(l < lCount && r < bCount) { - if(frag == Subarray.LEFT) { + while (l < lCount && r < bCount) { + if (frag == Subarray.LEFT) { do { j += bLen; l++; key++; - } - while(l < lCount && this.grailGetSubarray(array, key, mKey) == Subarray.LEFT); + } while (l < lCount && this.grailGetSubarray(array, key, mKey) == Subarray.LEFT); - if(l == lCount) { - i = this.grailMergeBlocks(array, i, j, b, i-bLen); - this.mergeWithBufRest(array, i-bLen, i, b, p, bLen); - } - else i = this.grailMergeBlocks(array, i, j, j+bLen-1, i-bLen); + if (l == lCount) { + i = this.grailMergeBlocks(array, i, j, b, i - bLen); + this.mergeWithBufRest(array, i - bLen, i, b, p, bLen); + } else + i = this.grailMergeBlocks(array, i, j, j + bLen - 1, i - bLen); frag = Subarray.RIGHT; - } - else { + } else { do { j += bLen; r++; key++; - } - while(r < bCount && this.grailGetSubarray(array, key, mKey) == Subarray.RIGHT); + } while (r < bCount && this.grailGetSubarray(array, key, mKey) == Subarray.RIGHT); - if(r == bCount) { - this.shift(array, i-bLen, i, b); - this.multiSwap(array, p, b-bLen, bLen); - } - else i = this.grailMergeBlocksRev(array, i, j, j+bLen-1, i-bLen); + if (r == bCount) { + this.shift(array, i - bLen, i, b); + this.multiSwap(array, p, b - bLen, bLen); + } else + i = this.grailMergeBlocksRev(array, i, j, j + bLen - 1, i - bLen); frag = Subarray.LEFT; } } - this.grailSortKeys(array, t+bCount, p, mKey); - } - - //TODO: rewrite strat 2 merge to be more adaptive - - //1024 items, 8 unique, linear, final merge pass - //old: 5812 comps & 5762 writes - //new: ??? - - /*private int grailMergeBlocksWithoutBuf(int[] array, int a, int m, int b) { - int i = a, j = m, k; - - while(i < j && j < b) { - if(Reads.compareValues(array[i], array[j]) > 0) { - k = this.leftBinarySearch(array, j+1, b, array[i]); - this.rotate(array, i, j, k); - - i += k-j; - j = k; - } - else i++; - } - - return i; - } - - private int grailMergeBlocksWithoutBufRev(int[] array, int a, int m, int b) { - int i = a, j = m, k; - - while(i < j && j < b) { - if(Reads.compareValues(array[i], array[j]) >= 0) { - k = this.rightBinarySearch(array, j+1, b, array[i]); - this.rotate(array, i, j, k); - - i += k-j; - j = k; - } - else i++; - } - - return i; - }*/ - - //old + this.grailSortKeys(array, t + bCount, p, mKey); + } + + // TODO: rewrite strat 2 merge to be more adaptive + + // 1024 items, 8 unique, linear, final merge pass + // old: 5812 comps & 5762 writes + // new: ??? + + /* + * private int grailMergeBlocksWithoutBuf(int[] array, int a, int m, int b) { + * int i = a, j = m, k; + * + * while(i < j && j < b) { + * if(Reads.compareValues(array[i], array[j]) > 0) { + * k = this.leftBinarySearch(array, j+1, b, array[i]); + * this.rotate(array, i, j, k); + * + * i += k-j; + * j = k; + * } + * else i++; + * } + * + * return i; + * } + * + * private int grailMergeBlocksWithoutBufRev(int[] array, int a, int m, int b) { + * int i = a, j = m, k; + * + * while(i < j && j < b) { + * if(Reads.compareValues(array[i], array[j]) >= 0) { + * k = this.rightBinarySearch(array, j+1, b, array[i]); + * this.rotate(array, i, j, k); + * + * i += k-j; + * j = k; + * } + * else i++; + * } + * + * return i; + * } + */ + + // old private void grailBlockMergeWithoutBuf(int[] array, int a, int m, int b, int t, int bLen) { - int a1 = a + (m-a)%bLen, b1 = b - (b-m)%bLen, - i = a, j = a1, key = t, - lCount = (m-j)/bLen + 1, bCount = (b1-j)/bLen + 1, l = 0, r = lCount; + int a1 = a + (m - a) % bLen, b1 = b - (b - m) % bLen, + i = a, j = a1, key = t, + lCount = (m - j) / bLen + 1, bCount = (b1 - j) / bLen + 1, l = 0, r = lCount; - int mKey = this.blockSelectSort(array, j, t, 0, 0, lCount-1, bCount-1, bLen); + int mKey = this.blockSelectSort(array, j, t, 0, 0, lCount - 1, bCount - 1, bLen); Subarray frag = Subarray.LEFT; - while(l < lCount && r < bCount) { + while (l < lCount && r < bCount) { Subarray next = this.grailGetSubarray(array, key++, mKey); - if(next == frag) { - if(frag == Subarray.LEFT) l++; - else r++; + if (next == frag) { + if (frag == Subarray.LEFT) + l++; + else + r++; i = j; - } - else {//grailMergeBlocksWithoutBuf() - int m2 = j, b2 = j+bLen, k; + } else {// grailMergeBlocksWithoutBuf() + int m2 = j, b2 = j + bLen, k; - if(frag == Subarray.LEFT) { - while(i < m2 && m2 < b2) { - if(Reads.compareValues(array[i], array[m2]) > 0) { - k = this.leftBinarySearch(array, m2+1, b2, array[i]); + if (frag == Subarray.LEFT) { + while (i < m2 && m2 < b2) { + if (Reads.compareValues(array[i], array[m2]) > 0) { + k = this.leftBinarySearch(array, m2 + 1, b2, array[i]); this.rotate(array, i, m2, k); - i += k-m2; + i += k - m2; m2 = k; - } - else i++; + } else + i++; } - } - else { - while(i < m2 && m2 < b2) { - if(Reads.compareValues(array[i], array[m2]) >= 0) { - k = this.rightBinarySearch(array, m2+1, b2, array[i]); + } else { + while (i < m2 && m2 < b2) { + if (Reads.compareValues(array[i], array[m2]) >= 0) { + k = this.rightBinarySearch(array, m2 + 1, b2, array[i]); this.rotate(array, i, m2, k); - i += k-m2; + i += k - m2; m2 = k; - } - else i++; + } else + i++; } } - if(i < m2) {//right side is merged first - if(next == Subarray.LEFT) l++; - else r++; - } - else { - if(frag == Subarray.LEFT) l++; - else r++; + if (i < m2) {// right side is merged first + if (next == Subarray.LEFT) + l++; + else + r++; + } else { + if (frag == Subarray.LEFT) + l++; + else + r++; frag = next; } } @@ -616,36 +627,38 @@ private void grailBlockMergeWithoutBuf(int[] array, int a, int m, int b, int t, j += bLen; } - if(l < lCount) this.inPlaceMergeBW(array, a, b1, b); - this.grailSortKeysWithoutBuf(array, t+bCount-1, mKey); + if (l < lCount) + this.inPlaceMergeBW(array, a, b1, b); + this.grailSortKeysWithoutBuf(array, t + bCount - 1, mKey); } private void smartMerge(int[] array, int a, int m, int b, int p) { - if(this.checkBounds(array, a, m, b)) { - a = this.rightBinarySearch(array, a, m-1, array[m]); + if (this.checkBounds(array, a, m, b)) { + a = this.rightBinarySearch(array, a, m - 1, array[m]); this.mergeWithBuf(array, a, m, b, p); } } private void smartMergeBW(int[] array, int a, int m, int b, int p) { - if(this.checkBounds(array, a, m, b)) { - b = this.leftBinarySearch(array, m+1, b, array[m-1]); + if (this.checkBounds(array, a, m, b)) { + b = this.leftBinarySearch(array, m + 1, b, array[m - 1]); this.mergeWithBufBW(array, a, m, b, p); } } private void smartBlockMerge(int[] array, int a, int m, int b, int t, int p, int bLen) { - if(this.checkBounds(array, a, m, b)) { - int n = this.rightBinarySearch(array, a, m-1, array[m]); - b = this.leftBinarySearch(array, m+1, b, array[m-1]); - - if(this.checkReverseBounds(array, n, m, b)) { - if(m-n <= bLen || b-m <= bLen) { - if(b-m < m-n) this.mergeWithBufBW(array, n, m, b, p); - else this.mergeWithBuf(array, n, m, b, p); - } - else { - n -= (n-a)%bLen; + if (this.checkBounds(array, a, m, b)) { + int n = this.rightBinarySearch(array, a, m - 1, array[m]); + b = this.leftBinarySearch(array, m + 1, b, array[m - 1]); + + if (this.checkReverseBounds(array, n, m, b)) { + if (m - n <= bLen || b - m <= bLen) { + if (b - m < m - n) + this.mergeWithBufBW(array, n, m, b, p); + else + this.mergeWithBuf(array, n, m, b, p); + } else { + n -= (n - a) % bLen; this.grailBlockMerge(array, n, m, b, t, p, bLen); } } @@ -653,16 +666,18 @@ private void smartBlockMerge(int[] array, int a, int m, int b, int t, int p, int } private void smartBlockMergeWithoutBuf(int[] array, int a, int m, int b, int t, int bLen) { - if(this.checkBounds(array, a, m, b)) { - a = this.rightBinarySearch(array, a, m-1, array[m]); + if (this.checkBounds(array, a, m, b)) { + a = this.rightBinarySearch(array, a, m - 1, array[m]); - if(m-a <= bLen) this.inPlaceMerge(array, a, m, b); - else this.grailBlockMergeWithoutBuf(array, a, m, b, t, bLen); + if (m - a <= bLen) + this.inPlaceMerge(array, a, m, b); + else + this.grailBlockMergeWithoutBuf(array, a, m, b, t, bLen); } } private void smartInPlaceMerge(int[] array, int a, int m, int b) { - if(this.checkSorted(array, a, m, b)) + if (this.checkSorted(array, a, m, b)) this.inPlaceMergeBW(array, a, m, b); } @@ -670,240 +685,264 @@ private void redistBuffer(int[] array, int a, int m, int b) { int rPos = this.leftBinarySearch(array, m, b, array[a]); this.rotate(array, a, m, rPos); - int dist = rPos-m; + int dist = rPos - m; a += dist; m += dist; - int a1 = a+(m-a)/2; + int a1 = a + (m - a) / 2; rPos = this.leftBinarySearch(array, m, b, array[a1]); this.rotate(array, a1, m, rPos); - dist = rPos-m; - a1 += dist; - m += dist; + dist = rPos - m; + a1 += dist; + m += dist; - this.mergeWithoutBuf(array, a, a1-dist, a1); + this.mergeWithoutBuf(array, a, a1 - dist, a1); this.mergeWithoutBuf(array, a1, m, b); } private void redistBufferBW(int[] array, int a, int m, int b) { - int rPos = this.rightBinarySearch(array, a, m, array[b-1]); + int rPos = this.rightBinarySearch(array, a, m, array[b - 1]); this.rotate(array, rPos, m, b); - int dist = m-rPos; + int dist = m - rPos; b -= dist; m -= dist; - int b1 = m+(b-m)/2; - rPos = this.rightBinarySearch(array, a, m, array[b1-1]); + int b1 = m + (b - m) / 2; + rPos = this.rightBinarySearch(array, a, m, array[b1 - 1]); this.rotate(array, rPos, m, b1); - dist = m-rPos; - b1 -= dist; - m -= dist; + dist = m - rPos; + b1 -= dist; + m -= dist; - this.mergeWithoutBuf(array, b1, b1+dist, b); + this.mergeWithoutBuf(array, b1, b1 + dist, b); this.mergeWithoutBuf(array, a, m, b1); } private void inPlaceMergeSort(int[] array, int a, int b) { this.buildRuns(array, a, b); - int len = b-a; - for(int i, j = this.minRun; j < len; j *= 2) { - for(i = a; i + 2*j <= b; i += 2*j) - this.smartInPlaceMerge(array, i, i+j, i+2*j); + int len = b - a; + for (int i, j = this.minRun; j < len; j *= 2) { + for (i = a; i + 2 * j <= b; i += 2 * j) + this.smartInPlaceMerge(array, i, i + j, i + 2 * j); - if(i + j < b) - this.smartInPlaceMerge(array, i, i+j, b); + if (i + j < b) + this.smartInPlaceMerge(array, i, i + j, b); } } private void grailAdaptiveSortWithoutBuf(int[] array, int a, int b, int keys, int ideal, boolean bwBuf) { - int len = b-a, bLen; - for(bLen = Math.min(keys, this.minRun); 2*bLen <= keys; bLen *= 2); - int tLen = keys-bLen; + int len = b - a, bLen; + for (bLen = Math.min(keys, this.minRun); 2 * bLen <= keys; bLen *= 2) + ; + int tLen = keys - bLen; int i, j = this.minRun, - t, p, a1, b1; + t, p, a1, b1; - if(bwBuf) { - p = b-bLen; a1 = a; b1 = p-tLen; t = b1; - } - else { - p = a+tLen; a1 = p+bLen; b1 = b; t = a; + if (bwBuf) { + p = b - bLen; + a1 = a; + b1 = p - tLen; + t = b1; + } else { + p = a + tLen; + a1 = p + bLen; + b1 = b; + t = a; } - //insertion level + // insertion level this.buildRuns(array, a1, b1); - //merge with buffer level - while(j <= bLen && j < len) { - for(i = a1; i + 2*j <= b1; i += 2*j) - this.smartMerge(array, i, i+j, i+2*j, p); + // merge with buffer level + while (j <= bLen && j < len) { + for (i = a1; i + 2 * j <= b1; i += 2 * j) + this.smartMerge(array, i, i + j, i + 2 * j, p); - if(i + j < b1) - this.smartMergeBW(array, i, i+j, b1, p); + if (i + j < b1) + this.smartMergeBW(array, i, i + j, b1, p); j *= 2; } - if(bLen/2 >= this.minRun && bLen/2 >= (keys+1)/2) { - this.binaryInsertion(array, p, p+bLen); + if (bLen / 2 >= this.minRun && bLen / 2 >= (keys + 1) / 2) { + this.binaryInsertion(array, p, p + bLen); bLen /= 2; - tLen = keys-bLen; + tLen = keys - bLen; p += bLen; } - //block merge level - while(tLen >= 2*j/bLen - 1 && j < len) { - for(i = a1; i + 2*j <= b1; i += 2*j) - this.smartBlockMerge(array, i, i+j, i+2*j, t, p, bLen); + // block merge level + while (tLen >= 2 * j / bLen - 1 && j < len) { + for (i = a1; i + 2 * j <= b1; i += 2 * j) + this.smartBlockMerge(array, i, i + j, i + 2 * j, t, p, bLen); - if(i + j < b1) { - if(b1 - (i+j) > bLen) - this.smartBlockMerge(array, i, i+j, b1, t, p, bLen); + if (i + j < b1) { + if (b1 - (i + j) > bLen) + this.smartBlockMerge(array, i, i + j, b1, t, p, bLen); - else this.smartMergeBW(array, i, i+j, b1, p); + else + this.smartMergeBW(array, i, i + j, b1, p); } j *= 2; } - this.binaryInsertion(array, p, p+bLen); - tLen = keys-keys%2; + this.binaryInsertion(array, p, p + bLen); + tLen = keys - keys % 2; - //block merge w/o buffer level - while(j < len) { - bLen = 2*j / tLen; + // block merge w/o buffer level + while (j < len) { + bLen = 2 * j / tLen; - for(i = a1; i + 2*j <= b1; i += 2*j) - this.smartBlockMergeWithoutBuf(array, i, i+j, i+2*j, t, bLen); + for (i = a1; i + 2 * j <= b1; i += 2 * j) + this.smartBlockMergeWithoutBuf(array, i, i + j, i + 2 * j, t, bLen); - if(i + j < b1) { - if(b1 - (i+j) > bLen) - this.smartBlockMergeWithoutBuf(array, i, i+j, b1, t, bLen); + if (i + j < b1) { + if (b1 - (i + j) > bLen) + this.smartBlockMergeWithoutBuf(array, i, i + j, b1, t, bLen); - else this.smartInPlaceMerge(array, i, i+j, b1); + else + this.smartInPlaceMerge(array, i, i + j, b1); } j *= 2; } - //buffer redistribution - if(bwBuf) { + // buffer redistribution + if (bwBuf) { a = this.rightBinarySearch(array, a, b1, array[b1]); - if(keys >= ideal/2) this.redistBufferBW(array, a, b1, b); - else this.mergeWithoutBuf(array, a, b1, b); - } - else { - b = this.leftBinarySearch(array, a1, b, array[a1-1]); - if(keys >= ideal/2) this.redistBuffer(array, a, a1, b); - else this.mergeWithoutBuf(array, a, a1, b); + if (keys >= ideal / 2) + this.redistBufferBW(array, a, b1, b); + else + this.mergeWithoutBuf(array, a, b1, b); + } else { + b = this.leftBinarySearch(array, a1, b, array[a1 - 1]); + if (keys >= ideal / 2) + this.redistBuffer(array, a, a1, b); + else + this.mergeWithoutBuf(array, a, a1, b); } } protected void grailAdaptiveSort(int[] array, int a, int b) { - int len = b-a; + int len = b - a; - //insertion on small len - if(len < 31) { + // insertion on small len + if (len < 31) { this.binaryInsertion(array, a, b); return; } - //mini adaptive grail sort - if(len < 63) { - this.minRun = (len+1)/2; + // mini adaptive grail sort + if (len < 63) { + this.minRun = (len + 1) / 2; this.buildRuns(array, a, b); - int m = a+this.minRun; - if(this.checkBounds(array, a, m, b)) + int m = a + this.minRun; + if (this.checkBounds(array, a, m, b)) this.redistBufferBW(array, a, m, b); return; } - //calculate optimal minRun & block len - for(this.minRun = len; this.minRun >= 32; this.minRun = (this.minRun+1)/2); + // calculate optimal minRun & block len + for (this.minRun = len; this.minRun >= 32; this.minRun = (this.minRun + 1) / 2) + ; int bLen; - for(bLen = this.minRun; bLen*bLen < len; bLen *= 2); + for (bLen = this.minRun; bLen * bLen < len; bLen *= 2) + ; - int tLen = len/bLen - 2, - ideal = tLen + bLen; + int tLen = len / bLen - 2, + ideal = tLen + bLen; - //choose direction to find keys + // choose direction to find keys boolean bwBuf; int rRun = this.buildUniqueRunBW(array, b, ideal), lRun = 0; - if(rRun == ideal) bwBuf = true; + if (rRun == ideal) + bwBuf = true; else { lRun = this.buildUniqueRun(array, a, ideal); - if(lRun == ideal) bwBuf = false; - else bwBuf = (rRun < 16 && lRun < 16) || rRun >= lRun; + if (lRun == ideal) + bwBuf = false; + else + bwBuf = (rRun < 16 && lRun < 16) || rRun >= lRun; } - //find bLen + tLen unique buffer keys + // find bLen + tLen unique buffer keys int keys = bwBuf ? this.findKeysBW(array, a, b, rRun, ideal) - : this.findKeys(array, a, b, lRun, ideal); + : this.findKeys(array, a, b, lRun, ideal); - if(keys < ideal) { - if(keys == 1) return; - else if(keys <= 4) this.inPlaceMergeSort(array, a, b); - else this.grailAdaptiveSortWithoutBuf(array, a, b, keys, ideal, bwBuf); + if (keys < ideal) { + if (keys == 1) + return; + else if (keys <= 4) + this.inPlaceMergeSort(array, a, b); + else + this.grailAdaptiveSortWithoutBuf(array, a, b, keys, ideal, bwBuf); return; } int i, j = this.minRun, - t, p, a1, b1; + t, p, a1, b1; - if(bwBuf) { - p = b-bLen; a1 = a; b1 = p-tLen; t = b1; - } - else { - p = a+tLen; a1 = p+bLen; b1 = b; t = a; + if (bwBuf) { + p = b - bLen; + a1 = a; + b1 = p - tLen; + t = b1; + } else { + p = a + tLen; + a1 = p + bLen; + b1 = b; + t = a; } - //insertion level + // insertion level this.buildRuns(array, a1, b1); - //merge with buffer level - while(j <= bLen && j < len) { - for(i = a1; i + 2*j <= b1; i += 2*j) - this.smartMerge(array, i, i+j, i+2*j, p); + // merge with buffer level + while (j <= bLen && j < len) { + for (i = a1; i + 2 * j <= b1; i += 2 * j) + this.smartMerge(array, i, i + j, i + 2 * j, p); - if(i + j < b1) - this.smartMergeBW(array, i, i+j, b1, p); + if (i + j < b1) + this.smartMergeBW(array, i, i + j, b1, p); j *= 2; } - //block merge level - while(j < len) { - for(i = a1; i + 2*j <= b1; i += 2*j) - this.smartBlockMerge(array, i, i+j, i+2*j, t, p, bLen); + // block merge level + while (j < len) { + for (i = a1; i + 2 * j <= b1; i += 2 * j) + this.smartBlockMerge(array, i, i + j, i + 2 * j, t, p, bLen); - if(i + j < b1) { - if(b1 - (i+j) > bLen) - this.smartBlockMerge(array, i, i+j, b1, t, p, bLen); + if (i + j < b1) { + if (b1 - (i + j) > bLen) + this.smartBlockMerge(array, i, i + j, b1, t, p, bLen); - else this.smartMergeBW(array, i, i+j, b1, p); + else + this.smartMergeBW(array, i, i + j, b1, p); } j *= 2; } - this.binaryInsertion(array, p, p+bLen); + this.binaryInsertion(array, p, p + bLen); - //buffer redistribution - if(bwBuf) { + // buffer redistribution + if (bwBuf) { a = this.rightBinarySearch(array, a, b1, array[b1]); this.redistBufferBW(array, a, b1, b); - } - else { - b = this.leftBinarySearch(array, a1, b, array[a1-1]); + } else { + b = this.leftBinarySearch(array, a1, b, array[a1 - 1]); this.redistBuffer(array, a, a1, b); } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/BinaryMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/BinaryMergeSort.java index 97fd1d42..77015321 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/BinaryMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/BinaryMergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.MergeSorting; /* @@ -28,20 +29,10 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Binary Merge") public final class BinaryMergeSort extends MergeSorting { public BinaryMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Binary Merge"); - this.setRunAllSortsName("Binary Merge Sort"); - this.setRunSortName("Binary Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/BufferPartitionMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/BufferPartitionMergeSort.java index fea96ef3..48196854 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/BufferPartitionMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/BufferPartitionMergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.BinaryInsertionSort; import io.github.arrayv.sorts.insert.InsertionSort; import io.github.arrayv.sorts.templates.Sort; @@ -30,261 +31,265 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Buffer Partition Merge") public final class BufferPartitionMergeSort extends Sort { - public BufferPartitionMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Buffer Partition Merge (BPM)"); - this.setRunAllSortsName("Buffer Partition Merge Sort"); - this.setRunSortName("BPMSort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public BufferPartitionMergeSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private InsertionSort insSort; private BinaryInsertionSort binInsSort; private void shiftBW(int[] array, int a, int m, int b) { - while(m > a) Writes.swap(array, --b, --m, 1, true, false); + while (m > a) + Writes.swap(array, --b, --m, 1, true, false); } private void multiSwap(int[] array, int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(array, a+i, b+i, 1, true, false); + for (int i = 0; i < len; i++) + Writes.swap(array, a + i, b + i, 1, true, false); } - private void rotate(int[] array, int a, int m, int b) { - int l = m-a, r = b-m; + private void rotate(int[] array, int a, int m, int b) { + int l = m - a, r = b - m; - while(l > 0 && r > 0) { - if(r < l) { - this.multiSwap(array, m-r, m, r); + while (l > 0 && r > 0) { + if (r < l) { + this.multiSwap(array, m - r, m, r); b -= r; m -= r; l -= r; - } - else { + } else { this.multiSwap(array, a, m, l); a += l; m += l; r -= l; - } - } - } + } + } + } private void inPlaceMerge(int[] array, int a, int m, int b) { int i = a, j = m, k; - while(i < j && j < b) { - if(Reads.compareValues(array[i], array[j]) > 0) { + while (i < j && j < b) { + if (Reads.compareValues(array[i], array[j]) > 0) { k = j; - while(++k < b && Reads.compareIndices(array, i, k, 0, false) > 0); + while (++k < b && Reads.compareIndices(array, i, k, 0, false) > 0) + ; this.rotate(array, i, j, k); - i += k-j; + i += k - j; j = k; - } - else i++; + } else + i++; } } private void medianOfThree(int[] array, int a, int b) { - int m = a+(b-1-a)/2; + int m = a + (b - 1 - a) / 2; - if(Reads.compareIndices(array, a, m, 1, true) == 1) + if (Reads.compareIndices(array, a, m, 1, true) == 1) Writes.swap(array, a, m, 1, true, false); - if(Reads.compareIndices(array, m, b-1, 1, true) == 1) { - Writes.swap(array, m, b-1, 1, true, false); + if (Reads.compareIndices(array, m, b - 1, 1, true) == 1) { + Writes.swap(array, m, b - 1, 1, true, false); - if(Reads.compareIndices(array, a, m, 1, true) == 1) + if (Reads.compareIndices(array, a, m, 1, true) == 1) return; } Writes.swap(array, a, m, 1, true, false); } - //lite version + // lite version private void medianOfMedians(int[] array, int a, int b, int s) { int end = b, start = a, i, j; boolean ad = true; - while(end - start > 1) { + while (end - start > 1) { j = start; Highlights.markArray(2, j); - for(i = start; i+2*s <= end; i+=s) { - this.insSort.customInsertSort(array, i, i+s, 0.25, false); - Writes.swap(array, j++, i+s/2, 1, false, false); + for (i = start; i + 2 * s <= end; i += s) { + this.insSort.customInsertSort(array, i, i + s, 0.25, false); + Writes.swap(array, j++, i + s / 2, 1, false, false); Highlights.markArray(2, j); } - if(i < end) { + if (i < end) { this.insSort.customInsertSort(array, i, end, 0.25, false); - Writes.swap(array, j++, i+(end-(ad ? 1 : 0)-i)/2, 1, false, false); + Writes.swap(array, j++, i + (end - (ad ? 1 : 0) - i) / 2, 1, false, false); Highlights.markArray(2, j); - if((end-i)%2 == 0) ad = !ad; + if ((end - i) % 2 == 0) + ad = !ad; } end = j; } } private int partition(int[] array, int a, int b) { - int i = a, j = b; + int i = a, j = b; Highlights.markArray(3, a); - while(true) { + while (true) { do { i++; - Highlights.markArray(1, i); - Delays.sleep(0.5); - } - while(i < j && Reads.compareIndices(array, i, a, 0, false) == 1); + Highlights.markArray(1, i); + Delays.sleep(0.5); + } while (i < j && Reads.compareIndices(array, i, a, 0, false) == 1); do { j--; - Highlights.markArray(2, j); - Delays.sleep(0.5); - } - while(j >= i && Reads.compareIndices(array, j, a, 0, false) == -1); + Highlights.markArray(2, j); + Delays.sleep(0.5); + } while (j >= i && Reads.compareIndices(array, j, a, 0, false) == -1); - if(i < j) Writes.swap(array, i, j, 1, true, false); - else return j; - } - } + if (i < j) + Writes.swap(array, i, j, 1, true, false); + else + return j; + } + } private int quickSelect(int[] array, int a, int b, int m) { boolean badPartition = false, mom = false; - int m1 = (m+b+1)/2; + int m1 = (m + b + 1) / 2; - while(true) { - if(badPartition) { + while (true) { + if (badPartition) { this.medianOfMedians(array, a, b, 5); mom = true; - } - else this.medianOfThree(array, a, b); + } else + this.medianOfThree(array, a, b); int p = this.partition(array, a, b); Writes.swap(array, a, p, 1, true, false); - int l = Math.max(1, p-a); - int r = Math.max(1, b-(p+1)); - badPartition = !mom && (l/r >= 16 || r/l >= 16); + int l = Math.max(1, p - a); + int r = Math.max(1, b - (p + 1)); + badPartition = !mom && (l / r >= 16 || r / l >= 16); - if(p >= m && p < m1) return p; - else if(p < m) a = p+1; - else b = p; + if (p >= m && p < m1) + return p; + else if (p < m) + a = p + 1; + else + b = p; } } private void merge(int[] array, int a, int m, int b, int p) { int i = a, j = m; - while(i < m && j < b) { - if(Reads.compareIndices(array, i, j, 0, false) <= 0) + while (i < m && j < b) { + if (Reads.compareIndices(array, i, j, 0, false) <= 0) Writes.swap(array, p++, i++, 1, true, false); else Writes.swap(array, p++, j++, 1, true, false); } - while(i < m) Writes.swap(array, p++, i++, 1, true, false); - while(j < b) Writes.swap(array, p++, j++, 1, true, false); + while (i < m) + Writes.swap(array, p++, i++, 1, true, false); + while (j < b) + Writes.swap(array, p++, j++, 1, true, false); } private int mergeFW(int[] array, int p, int a, int m, int b) { int i = a, j = m; - while(i < m && j < b) { - if(Reads.compareIndices(array, i, j, 0, false) <= 0) + while (i < m && j < b) { + if (Reads.compareIndices(array, i, j, 0, false) <= 0) Writes.swap(array, p++, i++, 1, true, false); else Writes.swap(array, p++, j++, 1, true, false); } - if(i < m) return i; - else return j; + if (i < m) + return i; + else + return j; } public static int getMinLevel(int n) { - while(n >= 32) n = (n+3)/4; + while (n >= 32) + n = (n + 3) / 4; return n; } private void mergeSort(int[] array, int a, int b, int p) { - int len = b-a; - if(len < 2) return; + int len = b - a; + if (len < 2) + return; int i, pos, j = getMinLevel(len); - for(i = a; i+j <= b; i+=j) - this.binInsSort.customBinaryInsert(array, i, i+j, 0.25); + for (i = a; i + j <= b; i += j) + this.binInsSort.customBinaryInsert(array, i, i + j, 0.25); this.binInsSort.customBinaryInsert(array, i, b, 0.25); - while(j < len) { + while (j < len) { pos = p; - for(i = a; i+2*j <= b; i+=2*j, pos+=2*j) - this.merge(array, i, i+j, i+2*j, pos); - if(i + j < b) - this.merge(array, i, i+j, b, pos); + for (i = a; i + 2 * j <= b; i += 2 * j, pos += 2 * j) + this.merge(array, i, i + j, i + 2 * j, pos); + if (i + j < b) + this.merge(array, i, i + j, b, pos); else - while(i < b) Writes.swap(array, i++, pos++, 1, true, false); + while (i < b) + Writes.swap(array, i++, pos++, 1, true, false); j *= 2; pos = a; - for(i = p; i+2*j <= p+len; i+=2*j, pos+=2*j) - this.merge(array, i, i+j, i+2*j, pos); - if(i + j < p+len) - this.merge(array, i, i+j, p+len, pos); + for (i = p; i + 2 * j <= p + len; i += 2 * j, pos += 2 * j) + this.merge(array, i, i + j, i + 2 * j, pos); + if (i + j < p + len) + this.merge(array, i, i + j, p + len, pos); else - while(i < p+len) Writes.swap(array, i++, pos++, 1, true, false); + while (i < p + len) + Writes.swap(array, i++, pos++, 1, true, false); j *= 2; } } private void sort(int[] array, int a, int b) { - int minLvl = (int)Math.sqrt(b-a); + int minLvl = (int) Math.sqrt(b - a); - int m = (a+b+1)/2; + int m = (a + b + 1) / 2; this.mergeSort(array, m, b, a); - while(m-a > minLvl) { - int m1 = (a+m+1)/2; + while (m - a > minLvl) { + int m1 = (a + m + 1) / 2; m1 = this.quickSelect(array, a, m, m1); this.mergeSort(array, m1, m, a); - int bSize = m1-a; - int m2 = Math.min(m1+bSize, b); + int bSize = m1 - a; + int m2 = Math.min(m1 + bSize, b); m1 = this.mergeFW(array, a, m1, m, m2); - while(m1 < m) { + while (m1 < m) { this.shiftBW(array, m1, m, m2); - m1 = m2-(m-m1); - a = m1-bSize; - m = m2; + m1 = m2 - (m - m1); + a = m1 - bSize; + m = m2; - if(m == b) break; + if (m == b) + break; - m2 = Math.min(m2+bSize, b); + m2 = Math.min(m2 + bSize, b); m1 = this.mergeFW(array, a, m1, m, m2); } m = m1; - a = m1-bSize; + a = m1 - bSize; } this.binInsSort.customBinaryInsert(array, a, m, 0.25); this.inPlaceMerge(array, a, m, b); } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { this.insSort = new InsertionSort(this.arrayVisualizer); this.binInsSort = new BinaryInsertionSort(this.arrayVisualizer); this.sort(array, 0, length); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/ChaliceSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/ChaliceSort.java index 6f8f7d57..4f59dcfc 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/ChaliceSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/ChaliceSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.select.MaxHeapSort; import io.github.arrayv.sorts.templates.BlockMergeSorting; @@ -29,140 +30,135 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Chalice") public final class ChaliceSort extends BlockMergeSorting { - public ChaliceSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Chalice"); - this.setRunAllSortsName("Chalice Sort"); - this.setRunSortName("Chalicesort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - //stable merge sort using O(cbrt n) dynamic external buffer + public ChaliceSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } + + // stable merge sort using O(cbrt n) dynamic external buffer private int ceilCbrt(int n) { int a = 0, b = 11; - while(a < b) { - int m = (a+b)/2; + while (a < b) { + int m = (a + b) / 2; - if((1 << 3*m) >= n) b = m; - else a = m+1; + if ((1 << 3 * m) >= n) + b = m; + else + a = m + 1; } return 1 << a; } - private int calcKeys(int bLen, int n) { //assumes keys needed is <= n/4 - int a = 1, b = n/4; + private int calcKeys(int bLen, int n) { // assumes keys needed is <= n/4 + int a = 1, b = n / 4; - while(a < b) { - int m = (a+b)/2; + while (a < b) { + int m = (a + b) / 2; - if((n-4*m-1)/bLen-2 < m) b = m; - else a = m+1; + if ((n - 4 * m - 1) / bLen - 2 < m) + b = m; + else + a = m + 1; } return a; } private void laziestSortExt(int[] array, int[] tmp, int a, int b) { - for(int i = a, s = tmp.length; i < b; i += s) { - int j = Math.min(b, i+s); + for (int i = a, s = tmp.length; i < b; i += s) { + int j = Math.min(b, i + s); this.binaryInsertion(array, i, j); - if(i > a) this.mergeBWExt(array, tmp, a, i, j); + if (i > a) + this.mergeBWExt(array, tmp, a, i, j); } } private int[] findKeysSm(int[] array, int a, int b, int a1, int b1, boolean full, int n) { int p = a, pEnd = 0; - if(full) { - for(; p < b; p++) { + if (full) { + for (; p < b; p++) { Highlights.markArray(1, p); int loc = this.leftBinSearch(array, a1, b1, array[p]); - if(loc == b1 || Reads.compareValues(array[p], array[loc]) != 0) { - pEnd = p+1; + if (loc == b1 || Reads.compareValues(array[p], array[loc]) != 0) { + pEnd = p + 1; break; } } - if(pEnd != 0) { - for(int i = pEnd; i < b && pEnd-p < n; i++) { + if (pEnd != 0) { + for (int i = pEnd; i < b && pEnd - p < n; i++) { Highlights.markArray(1, i); int loc = this.leftBinSearch(array, a1, b1, array[i]); - if(loc == b1 || Reads.compareValues(array[i], array[loc]) != 0) { + if (loc == b1 || Reads.compareValues(array[i], array[loc]) != 0) { loc = this.leftBinSearch(array, p, pEnd, array[i]); - if(loc == pEnd || Reads.compareValues(array[i], array[loc]) != 0) { + if (loc == pEnd || Reads.compareValues(array[i], array[loc]) != 0) { this.rotate(array, p, pEnd, i); - int len1 = i-pEnd; - p += len1; - loc += len1; - pEnd = i+1; + int len1 = i - pEnd; + p += len1; + loc += len1; + pEnd = i + 1; this.insertTo(array, i, loc); } } } - } - else pEnd = p; - } - else { - pEnd = p+1; + } else + pEnd = p; + } else { + pEnd = p + 1; - for(int i = pEnd; i < b && pEnd-p < n; i++) { + for (int i = pEnd; i < b && pEnd - p < n; i++) { Highlights.markArray(1, i); int loc = this.leftBinSearch(array, p, pEnd, array[i]); - if(loc == pEnd || Reads.compareValues(array[i], array[loc]) != 0) { + if (loc == pEnd || Reads.compareValues(array[i], array[loc]) != 0) { this.rotate(array, p, pEnd, i); - int len1 = i-pEnd; - p += len1; - loc += len1; - pEnd = i+1; + int len1 = i - pEnd; + p += len1; + loc += len1; + pEnd = i + 1; this.insertTo(array, i, loc); } } } - int[] t = {p, pEnd}; + int[] t = { p, pEnd }; return t; } - private int findKeys(int[] array, int[] tmp, int a, int b, int n, int s) { //searches for n keys s blocks at a time + + private int findKeys(int[] array, int[] tmp, int a, int b, int n, int s) { // searches for n keys s blocks at a time int[] t = this.findKeysSm(array, a, b, 0, 0, false, Math.min(n, s)); int p = t[0], pEnd = t[1]; - if(s < n && pEnd-p == s) { - for(n -= s; ; n -= s) { + if (s < n && pEnd - p == s) { + for (n -= s;; n -= s) { t = this.findKeysSm(array, pEnd, b, p, pEnd, true, Math.min(s, n)); - int keys = t[1]-t[0]; + int keys = t[1] - t[0]; - if(keys == 0) break; + if (keys == 0) + break; - if(keys < s || n == s) { + if (keys < s || n == s) { this.rotate(array, pEnd, t[0], t[1]); t[0] = pEnd; pEnd += keys; - this.mergeBWExt(array, tmp, p, t[0], pEnd); //merge can be done inplace + stable + this.mergeBWExt(array, tmp, p, t[0], pEnd); // merge can be done inplace + stable break; - } - else { + } else { this.rotate(array, p, pEnd, t[0]); - p += t[0]-pEnd; + p += t[0] - pEnd; pEnd = t[1]; this.mergeBWExt(array, tmp, p, t[0], pEnd); @@ -170,108 +166,111 @@ private int findKeys(int[] array, int[] tmp, int a, int b, int n, int s) { //sea } } this.rotate(array, a, p, pEnd); - return pEnd-p; + return pEnd - p; } private int[] findBitsSm(int[] array, int a, int b, int a1, boolean bw, int n) { int p = a, pEnd, cmp = bw ? -1 : 1; - while(p < b && Reads.compareIndices(array, p, a1, 1, true) != cmp) p++; + while (p < b && Reads.compareIndices(array, p, a1, 1, true) != cmp) + p++; a1++; - if(p < b) { - pEnd = p+1; + if (p < b) { + pEnd = p + 1; - for(int i = pEnd; i < b && pEnd-p < n; i++) { - if(Reads.compareIndices(array, i, a1, 1, true) == cmp) { + for (int i = pEnd; i < b && pEnd - p < n; i++) { + if (Reads.compareIndices(array, i, a1, 1, true) == cmp) { this.rotate(array, p, pEnd, i); - p += i-pEnd; - pEnd = i+1; + p += i - pEnd; + pEnd = i + 1; a1++; } } - } - else pEnd = p; + } else + pEnd = p; - int[] t = {p, pEnd}; + int[] t = { p, pEnd }; return t; } + private int findBits(int[] array, int[] tmp, int a, int b, int n, int s) { - this.laziestSortExt(array, tmp, a, a+n); + this.laziestSortExt(array, tmp, a, a + n); - int a0 = a, a1 = a+n, c = 0, c0 = 0; + int a0 = a, a1 = a + n, c = 0, c0 = 0; - for(int i = 0; c < n && i < 2; i++) { + for (int i = 0; c < n && i < 2; i++) { int p = a1, pEnd = p; - while(true) { - int[] t = this.findBitsSm(array, pEnd, b, a0, i == 1, Math.min(s, n-c)); - int bits = t[1]-t[0]; + while (true) { + int[] t = this.findBitsSm(array, pEnd, b, a0, i == 1, Math.min(s, n - c)); + int bits = t[1] - t[0]; - if(bits == 0) break; + if (bits == 0) + break; a0 += bits; - c += bits; + c += bits; - if(bits < s || c == n) { + if (bits < s || c == n) { this.rotate(array, pEnd, t[0], t[1]); t[0] = pEnd; pEnd += bits; break; - } - else { + } else { this.rotate(array, p, pEnd, t[0]); - p += t[0]-pEnd; + p += t[0] - pEnd; pEnd = t[1]; } } this.rotate(array, a1, p, pEnd); - a1 += pEnd-p; + a1 += pEnd - p; - if(i == 0) c0 = c; + if (i == 0) + c0 = c; } - //returns the count of ascending pairs of elements NOT how many bits found + // returns the count of ascending pairs of elements NOT how many bits found - if(c < n) return -1; + if (c < n) + return -1; else { - this.multiSwap(array, a+c0, a+n+c0, n-c0); + this.multiSwap(array, a + c0, a + n + c0, n - c0); return c0; } } private void bitReversal(int[] array, int a, int b) { - int len = b-a, m = 0; - int d1 = len>>1, d2 = d1+(d1>>1); + int len = b - a, m = 0; + int d1 = len >> 1, d2 = d1 + (d1 >> 1); - for(int i = 1; i < len-1; i++) { + for (int i = 1; i < len - 1; i++) { int j = d1; - for( - int k = i, n = d2; - (k&1) == 0; - j -= n, k >>= 1, n >>= 1 - ); + for (int k = i, n = d2; (k & 1) == 0; j -= n, k >>= 1, n >>= 1) + ; m += j; - if(m > i) Writes.swap(array, a+i, a+m, 1, true, false); + if (m > i) + Writes.swap(array, a + i, a + m, 1, true, false); } } - private void unshuffle(int[] array, int a, int b) { //b-a is even - int len = (b-a)>>1, c = 0; - for(int n = 2; len > 0; len >>= 1, n *= 2) { - if((len&1) == 1) { - int a1 = a+c; + private void unshuffle(int[] array, int a, int b) { // b-a is even + int len = (b - a) >> 1, c = 0; - this.bitReversal(array, a1, a1+n); - this.bitReversal(array, a1, a1+n/2); - this.bitReversal(array, a1+n/2, a1+n); - this.rotate(array, a+c/2, a1, a1+n/2); + for (int n = 2; len > 0; len >>= 1, n *= 2) { + if ((len & 1) == 1) { + int a1 = a + c; + + this.bitReversal(array, a1, a1 + n); + this.bitReversal(array, a1, a1 + n / 2); + this.bitReversal(array, a1 + n / 2, a1 + n); + this.rotate(array, a + c / 2, a1, a1 + n / 2); c += n; } @@ -281,83 +280,95 @@ private void unshuffle(int[] array, int a, int b) { //b-a is even private void redistBuffer(int[] array, int[] tmp, int a, int m, int b) { int s = tmp.length; - while(m-a > s && m < b) { - int i = this.leftBinSearch(array, m, b, array[a+s]); - this.rotate(array, a+s, m, i); + while (m - a > s && m < b) { + int i = this.leftBinSearch(array, m, b, array[a + s]); + this.rotate(array, a + s, m, i); - int t = i-m; + int t = i - m; m = i; - this.mergeFWExt(array, tmp, a, a+s, m); - a += t+s; + this.mergeFWExt(array, tmp, a, a + s, m); + a += t + s; } - if(m < b) this.mergeFWExt(array, tmp, a, m, b); + if (m < b) + this.mergeFWExt(array, tmp, a, m, b); } private void dualMergeBW(int[] array, int a, int m, int b, int p) { - int i = m-1; b--; + int i = m - 1; + b--; - while(p > b+1 && b >= m) { + while (p > b + 1 && b >= m) { Highlights.markArray(2, i); - if(Reads.compareValues(array[b], array[i]) >= 0) + if (Reads.compareValues(array[b], array[i]) >= 0) Writes.swap(array, --p, b--, 1, true, false); else Writes.swap(array, --p, i--, 1, true, false); } - if(b < m) this.shiftBW(array, a, i+1, p); + if (b < m) + this.shiftBW(array, a, i + 1, p); else { - i++; b++; p = m-(i-a); + i++; + b++; + p = m - (i - a); - while(a < i && m < b) { + while (a < i && m < b) { Highlights.markArray(2, m); - if(Reads.compareValues(array[a], array[m]) <= 0) + if (Reads.compareValues(array[a], array[m]) <= 0) Writes.swap(array, p++, a++, 1, true, false); else Writes.swap(array, p++, m++, 1, true, false); } - while(a < i) Writes.swap(array, p++, a++, 1, true, false); + while (a < i) + Writes.swap(array, p++, a++, 1, true, false); } } + private void dualMergeBWExt(int[] array, int a, int m, int b, int p) { - int i = m-1; b--; + int i = m - 1; + b--; - while(p > b+1 && b >= m) { + while (p > b + 1 && b >= m) { Highlights.markArray(2, i); - if(Reads.compareValues(array[b], array[i]) >= 0) + if (Reads.compareValues(array[b], array[i]) >= 0) Writes.write(array, --p, array[b--], 1, true, false); else Writes.write(array, --p, array[i--], 1, true, false); } - if(b < m) this.shiftBWExt(array, a, i+1, p); + if (b < m) + this.shiftBWExt(array, a, i + 1, p); else { - i++; b++; p = m-(i-a); + i++; + b++; + p = m - (i - a); - while(a < i && m < b) { + while (a < i && m < b) { Highlights.markArray(2, m); - if(Reads.compareValues(array[a], array[m]) <= 0) + if (Reads.compareValues(array[a], array[m]) <= 0) Writes.write(array, p++, array[a++], 1, true, false); else Writes.write(array, p++, array[m++], 1, true, false); } - while(a < i) Writes.write(array, p++, array[a++], 1, true, false); + while (a < i) + Writes.write(array, p++, array[a++], 1, true, false); } } private int smartMerge(int[] array, int p, int a, int m, boolean rev) { int i = m, cmp = rev ? 0 : 1; - while(a < m) { + while (a < m) { Highlights.markArray(2, i); - if(Reads.compareValues(array[a], array[i]) < cmp) + if (Reads.compareValues(array[a], array[i]) < cmp) Writes.write(array, p++, array[a++], 1, true, false); else Writes.write(array, p++, array[i++], 1, true, false); @@ -365,233 +376,252 @@ private int smartMerge(int[] array, int p, int a, int m, boolean rev) { return i; } + private void smartTailMerge(int[] array, int[] tmp, int p, int a, int m, int b) { int i = m, bLen = tmp.length; - while(a < m && i < b) { + while (a < m && i < b) { Highlights.markArray(2, i); - if(Reads.compareValues(array[a], array[i]) <= 0) + if (Reads.compareValues(array[a], array[i]) <= 0) Writes.write(array, p++, array[a++], 1, true, false); else Writes.write(array, p++, array[i++], 1, true, false); } - if(a < m) { - if(a > p) this.shiftFWExt(array, p, a, m); - Writes.arraycopy(tmp, 0, array, b-bLen, bLen, 1, true, false); - } - else { + if (a < m) { + if (a > p) + this.shiftFWExt(array, p, a, m); + Writes.arraycopy(tmp, 0, array, b - bLen, bLen, 1, true, false); + } else { a = 0; - while(a < bLen && i < b) { + while (a < bLen && i < b) { Highlights.markArray(2, i); - if(Reads.compareValues(tmp[a], array[i]) <= 0) + if (Reads.compareValues(tmp[a], array[i]) <= 0) Writes.write(array, p++, tmp[a++], 1, true, false); else Writes.write(array, p++, array[i++], 1, true, false); } - while(a < bLen) Writes.write(array, p++, tmp[a++], 1, true, false); + while (a < bLen) + Writes.write(array, p++, tmp[a++], 1, true, false); } } + private void blockCycle(int[] array, int a, int t, int tIdx, int tLen, int bLen) { - for(int i = 0; i < tLen-1; i++) { - if(Reads.compareValues(array[t+i], array[tIdx+i]) > 0 || - (i > 0 && Reads.compareValues(array[t+i], array[tIdx+i-1]) < 0)) { + for (int i = 0; i < tLen - 1; i++) { + if (Reads.compareValues(array[t + i], array[tIdx + i]) > 0 || + (i > 0 && Reads.compareValues(array[t + i], array[tIdx + i - 1]) < 0)) { - Writes.arraycopy(array, a+i*bLen, array, a-bLen, bLen, 1, true, false); + Writes.arraycopy(array, a + i * bLen, array, a - bLen, bLen, 1, true, false); - int val = i, next = this.leftBinSearch(array, tIdx, tIdx+tLen, array[t+i])-tIdx; + int val = i, next = this.leftBinSearch(array, tIdx, tIdx + tLen, array[t + i]) - tIdx; do { - Writes.arraycopy(array, a+next*bLen, array, a+val*bLen, bLen, 1, true, false); - Writes.swap(array, t+i, t+next, 1, true, false); + Writes.arraycopy(array, a + next * bLen, array, a + val * bLen, bLen, 1, true, false); + Writes.swap(array, t + i, t + next, 1, true, false); - val = next; - next = this.leftBinSearch(array, tIdx, tIdx+tLen, array[t+i])-tIdx; - } - while(next != i); + val = next; + next = this.leftBinSearch(array, tIdx, tIdx + tLen, array[t + i]) - tIdx; + } while (next != i); - Writes.arraycopy(array, a-bLen, array, a+val*bLen, bLen, 1, true, false); + Writes.arraycopy(array, a - bLen, array, a + val * bLen, bLen, 1, true, false); } } } - private void blockMerge(int[] array, int[] tmp, int a, int m, int b, int tl, int tLen, int t, int tIdx, int bp1, int bp2, int bLen) { - if(b-m <= bLen) { + + private void blockMerge(int[] array, int[] tmp, int a, int m, int b, int tl, int tLen, int t, int tIdx, int bp1, + int bp2, int bLen) { + if (b - m <= bLen) { Highlights.clearMark(2); this.mergeBWExt(array, tmp, a, m, b); return; } - this.insertTo(array, t+tl-1, t); + this.insertTo(array, t + tl - 1, t); - int i = a+bLen-1, j = m+bLen-1, ti = t, tj = t+tl, tp = tIdx; + int i = a + bLen - 1, j = m + bLen - 1, ti = t, tj = t + tl, tp = tIdx; - while(ti < t+tl && tj < t+tLen) { - if(Reads.compareValues(array[i], array[j]) <= 0) { + while (ti < t + tl && tj < t + tLen) { + if (Reads.compareValues(array[i], array[j]) <= 0) { Writes.swap(array, tp++, ti++, 1, true, false); i += bLen; - } - else { + } else { Writes.swap(array, tp++, tj++, 1, true, false); Writes.swap(array, bp1, bp2, 1, true, false); j += bLen; } - bp1++; bp2++; + bp1++; + bp2++; } - while(ti < t+tl) { + while (ti < t + tl) { Writes.swap(array, tp++, ti++, 1, true, false); - bp1++; bp2++; + bp1++; + bp2++; } - while(tj < t+tLen) { + while (tj < t + tLen) { Writes.swap(array, tp++, tj++, 1, true, false); Writes.swap(array, bp1++, bp2++, 1, true, false); } - t ^= tIdx; tIdx ^= t; t ^= tIdx; + t ^= tIdx; + tIdx ^= t; + t ^= tIdx; MaxHeapSort sortHeap = new MaxHeapSort(this.arrayVisualizer); - sortHeap.customHeapSort(array, tIdx, tIdx+tLen, 1); + sortHeap.customHeapSort(array, tIdx, tIdx + tLen, 1); - Writes.arraycopy(array, m-bLen, tmp, 0, bLen, 1, true, true); - Writes.arraycopy(array, a, array, m-bLen, bLen, 1, true, false); + Writes.arraycopy(array, m - bLen, tmp, 0, bLen, 1, true, true); + Writes.arraycopy(array, a, array, m - bLen, bLen, 1, true, false); - this.blockCycle(array, a+bLen, t, tIdx, tLen, bLen); + this.blockCycle(array, a + bLen, t, tIdx, tLen, bLen); this.multiSwap(array, t, tIdx, tLen); - bp1 -= tLen; bp2 -= tLen; + bp1 -= tLen; + bp2 -= tLen; - int f = a+bLen, a1 = f, bp3 = bp2+tLen; + int f = a + bLen, a1 = f, bp3 = bp2 + tLen; boolean rev = Reads.compareIndices(array, bp1, bp2, 1, true) > 0; - while(true) { + while (true) { do { - if(rev) Writes.swap(array, bp1, bp2, 1, true, false); + if (rev) + Writes.swap(array, bp1, bp2, 1, true, false); - bp1++; bp2++; + bp1++; + bp2++; a1 += bLen; - } - while(bp2 < bp3 && Reads.compareIndices(array, bp1, bp2, 1, true) == (rev ? 1 : -1)); + } while (bp2 < bp3 && Reads.compareIndices(array, bp1, bp2, 1, true) == (rev ? 1 : -1)); - if(bp2 == bp3) { - this.smartTailMerge(array, tmp, f-bLen, f, rev ? f : a1, b); + if (bp2 == bp3) { + this.smartTailMerge(array, tmp, f - bLen, f, rev ? f : a1, b); return; } - f = this.smartMerge(array, f-bLen, f, a1, rev); + f = this.smartMerge(array, f - bLen, f, a1, rev); rev = !rev; } } private void blockCycleEasy(int[] array, int a, int t, int tIdx, int tLen, int bLen) { - for(int i = 0; i < tLen-1; i++) { - if(Reads.compareValues(array[t+i], array[tIdx+i]) > 0 || - (i > 0 && Reads.compareValues(array[t+i], array[tIdx+i-1]) < 0)) { + for (int i = 0; i < tLen - 1; i++) { + if (Reads.compareValues(array[t + i], array[tIdx + i]) > 0 || + (i > 0 && Reads.compareValues(array[t + i], array[tIdx + i - 1]) < 0)) { - int next = this.leftBinSearch(array, tIdx, tIdx+tLen, array[t+i])-tIdx; + int next = this.leftBinSearch(array, tIdx, tIdx + tLen, array[t + i]) - tIdx; do { - this.multiSwap(array, a+i*bLen, a+next*bLen, bLen); - Writes.swap(array, t+i, t+next, 1, true, false); + this.multiSwap(array, a + i * bLen, a + next * bLen, bLen); + Writes.swap(array, t + i, t + next, 1, true, false); - next = this.leftBinSearch(array, tIdx, tIdx+tLen, array[t+i])-tIdx; - } - while(next != i); + next = this.leftBinSearch(array, tIdx, tIdx + tLen, array[t + i]) - tIdx; + } while (next != i); } } } + private int inPlaceMergeBW(int[] array, int a, int m, int b, boolean rev) { - int f = rev ? this.rightBinSearch(array, m, b, array[m-1]) - : this.leftBinSearch(array, m, b, array[m-1]); + int f = rev ? this.rightBinSearch(array, m, b, array[m - 1]) + : this.leftBinSearch(array, m, b, array[m - 1]); b = f; - while(b > m && m > a) { - int i = rev ? this.leftBinSearch(array, a, m, array[b-1]) - : this.rightBinSearch(array, a, m, array[b-1]); + while (b > m && m > a) { + int i = rev ? this.leftBinSearch(array, a, m, array[b - 1]) + : this.rightBinSearch(array, a, m, array[b - 1]); this.rotate(array, i, m, b); - int t = m-i; + int t = m - i; m = i; - b -= t+1; + b -= t + 1; - if(m == a) break; + if (m == a) + break; - b = rev ? this.rightBinSearch(array, m, b, array[m-1]) - : this.leftBinSearch(array, m, b, array[m-1]); + b = rev ? this.rightBinSearch(array, m, b, array[m - 1]) + : this.leftBinSearch(array, m, b, array[m - 1]); } return f; } - private void blockMergeEasy(int[] array, int a, int m, int b, int lenA, int lenB, int tl, int tLen, int t, int tIdx, int bp1, int bp2, int bLen) { - if(b-m <= bLen) { + + private void blockMergeEasy(int[] array, int a, int m, int b, int lenA, int lenB, int tl, int tLen, int t, int tIdx, + int bp1, int bp2, int bLen) { + if (b - m <= bLen) { this.inPlaceMergeBW(array, a, m, b, false); return; } - int a1 = a+lenA, b1 = b-lenB; + int a1 = a + lenA, b1 = b - lenB; - int i = a1+bLen-1, j = m+bLen-1, ti = tIdx, tj = tIdx+tl, tp = t; + int i = a1 + bLen - 1, j = m + bLen - 1, ti = tIdx, tj = tIdx + tl, tp = t; - while(ti < tIdx+tl && tj < tIdx+tLen) { - if(Reads.compareValues(array[i], array[j]) <= 0) { + while (ti < tIdx + tl && tj < tIdx + tLen) { + if (Reads.compareValues(array[i], array[j]) <= 0) { Writes.swap(array, ti++, tp++, 1, true, false); i += bLen; - } - else { + } else { Writes.swap(array, tj++, tp++, 1, true, false); Writes.swap(array, bp1, bp2, 1, true, false); j += bLen; } - bp1++; bp2++; + bp1++; + bp2++; } - while(ti < tIdx+tl) { + while (ti < tIdx + tl) { Writes.swap(array, ti++, tp++, 1, true, false); - bp1++; bp2++; + bp1++; + bp2++; } - while(tj < tIdx+tLen) { + while (tj < tIdx + tLen) { Writes.swap(array, tj++, tp++, 1, true, false); Writes.swap(array, bp1++, bp2++, 1, true, false); } - t ^= tIdx; tIdx ^= t; t ^= tIdx; + t ^= tIdx; + tIdx ^= t; + t ^= tIdx; MaxHeapSort sortHeap = new MaxHeapSort(this.arrayVisualizer); - sortHeap.customHeapSort(array, tIdx, tIdx+tLen, 1); + sortHeap.customHeapSort(array, tIdx, tIdx + tLen, 1); this.blockCycleEasy(array, a1, t, tIdx, tLen, bLen); this.multiSwap(array, t, tIdx, tLen); - bp1 -= tLen; bp2 -= tLen; + bp1 -= tLen; + bp2 -= tLen; - int f = a1, a2 = f, bp3 = bp2+tLen; + int f = a1, a2 = f, bp3 = bp2 + tLen; boolean rev = Reads.compareIndices(array, bp1, bp2, 1, true) > 0; - while(true) { + while (true) { do { - if(rev) Writes.swap(array, bp1, bp2, 1, true, false); + if (rev) + Writes.swap(array, bp1, bp2, 1, true, false); - bp1++; bp2++; + bp1++; + bp2++; a2 += bLen; - } - while(bp2 < bp3 && Reads.compareIndices(array, bp1, bp2, 1, true) == (rev ? 1 : -1)); + } while (bp2 < bp3 && Reads.compareIndices(array, bp1, bp2, 1, true) == (rev ? 1 : -1)); - if(bp2 == bp3) { - if(!rev) this.inPlaceMergeBW(array, a1, b1, b, false); + if (bp2 == bp3) { + if (!rev) + this.inPlaceMergeBW(array, a1, b1, b, false); this.inPlaceMerge(array, a, a1, b); return; } - f = this.inPlaceMergeBW(array, f, a2, a2+bLen, rev); + f = this.inPlaceMergeBW(array, f, a2, a2 + bLen, rev); rev = !rev; } } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - int a = 0, b = currentLength, n = b-a; + @Override + public void runSort(int[] array, int currentLength, int bucketCount) { + int a = 0, b = currentLength, n = b - a; - if(n < 128) { - if(n < 32) this.binaryInsertion(array, a, b); + if (n < 128) { + if (n < 32) + this.binaryInsertion(array, a, b); else { FifthMergeSort smallSort = new FifthMergeSort(this.arrayVisualizer); @@ -601,167 +631,199 @@ public void runSort(int[] array, int currentLength, int bucketCount) { return; } - int cbrt = 2*ceilCbrt(n/4), bLen = 2*cbrt; + int cbrt = 2 * ceilCbrt(n / 4), bLen = 2 * cbrt; int kLen = this.calcKeys(bLen, n); int[] tmp = Writes.createExternalArray(bLen); - int keys = this.findKeys(array, tmp, a, b, 2*kLen, cbrt); + int keys = this.findKeys(array, tmp, a, b, 2 * kLen, cbrt); - if(keys < 8) { //need at least 8 keys to perform a block merge - for(int j = 1; j < n; j *= 2) - for(int i = a+j; i < b; i += 2*j) - this.inPlaceMergeBW(array, i-j, i, Math.min(i+j, b), false); + if (keys < 8) { // need at least 8 keys to perform a block merge + for (int j = 1; j < n; j *= 2) + for (int i = a + j; i < b; i += 2 * j) + this.inPlaceMergeBW(array, i - j, i, Math.min(i + j, b), false); return; - } - else if(keys < 2*kLen) { - keys -= keys%4; - kLen = keys/2; + } else if (keys < 2 * kLen) { + keys -= keys % 4; + kLen = keys / 2; } - //bit buffer length always equal to key buffer length - int a1 = a+keys, a2 = a1+keys, bSep = this.findBits(array, tmp, a1, b, kLen, cbrt); + // bit buffer length always equal to key buffer length + int a1 = a + keys, a2 = a1 + keys, bSep = this.findBits(array, tmp, a1, b, kLen, cbrt); - if(bSep == -1) { //if we cant find enough bits we dont have to sort + if (bSep == -1) { // if we cant find enough bits we dont have to sort this.laziestSortExt(array, tmp, a, a2); this.inPlaceMerge(array, a, a2, b); return; } - //[a][ keys ][a1][ bits ][a2][extbuf][a3][main sequence][b] - int a3 = a2+bLen, i, j = 1; n = b-a3; + // [a][ keys ][a1][ bits ][a2][extbuf][a3][main sequence][b] + int a3 = a2 + bLen, i, j = 1; + n = b - a3; - //advanced build blocks + // advanced build blocks this.binaryInsertion(array, a2, a3); Writes.arraycopy(array, a2, tmp, 0, bLen, 1, true, true); - for(; j < cbrt; j *= 2) { + for (; j < cbrt; j *= 2) { int p = Math.max(2, j); - for(i = a3; i+2*j < b; i += 2*j) - this.mergeWithBufFWExt(array, i, i+j, i+2*j, i-p); + for (i = a3; i + 2 * j < b; i += 2 * j) + this.mergeWithBufFWExt(array, i, i + j, i + 2 * j, i - p); - if(i+j < b) this.mergeWithBufFWExt(array, i, i+j, b, i-p); - else this.shiftFWExt(array, i-p, i, b); + if (i + j < b) + this.mergeWithBufFWExt(array, i, i + j, b, i - p); + else + this.shiftFWExt(array, i - p, i, b); - a3 -= p; b -= p; + a3 -= p; + b -= p; } - i = b-n%(2*j); + i = b - n % (2 * j); - if(i+j < b) this.mergeWithBufBWExt(array, i, i+j, b, b+j); - else this.shiftBWExt(array, i, b, b+j); + if (i + j < b) + this.mergeWithBufBWExt(array, i, i + j, b, b + j); + else + this.shiftBWExt(array, i, b, b + j); - for(i -= 2*j; i >= a3; i -= 2*j) - this.mergeWithBufBWExt(array, i, i+j, i+2*j, i+3*j); + for (i -= 2 * j; i >= a3; i -= 2 * j) + this.mergeWithBufBWExt(array, i, i + j, i + 2 * j, i + 3 * j); - a3 += j; b += j; j *= 2; + a3 += j; + b += j; + j *= 2; - for(i = a3; i+2*j < b; i += 2*j) - this.mergeWithBufFWExt(array, i, i+j, i+2*j, i-j); + for (i = a3; i + 2 * j < b; i += 2 * j) + this.mergeWithBufFWExt(array, i, i + j, i + 2 * j, i - j); - if(i+j < b) this.mergeWithBufFWExt(array, i, i+j, b, i-j); - else this.shiftFWExt(array, i-j, i, b); + if (i + j < b) + this.mergeWithBufFWExt(array, i, i + j, b, i - j); + else + this.shiftFWExt(array, i - j, i, b); - a3 -= j; b -= j; j *= 2; + a3 -= j; + b -= j; + j *= 2; - i = b-n%(2*j); + i = b - n % (2 * j); - if(i+j < b) this.dualMergeBWExt(array, i, i+j, b, b+j/2); - else this.shiftBWExt(array, i, b, b+j/2); + if (i + j < b) + this.dualMergeBWExt(array, i, i + j, b, b + j / 2); + else + this.shiftBWExt(array, i, b, b + j / 2); - for(i -= 2*j; i >= a3; i -= 2*j) - this.dualMergeBWExt(array, i, i+j, i+2*j, i+2*j+j/2); + for (i -= 2 * j; i >= a3; i -= 2 * j) + this.dualMergeBWExt(array, i, i + j, i + 2 * j, i + 2 * j + j / 2); - a3 += j/2; b += j/2; j *= 2; + a3 += j / 2; + b += j / 2; + j *= 2; - //advanced build blocks (in-place using keys) - if(keys >= j) { + // advanced build blocks (in-place using keys) + if (keys >= j) { this.rotate(array, a, a1, a3); - a2 = a1+bLen; + a2 = a1 + bLen; - if(kLen >= j) { - for(int mLvl = 2*j; j < kLen; j *= 2) { + if (kLen >= j) { + for (int mLvl = 2 * j; j < kLen; j *= 2) { int p = Math.max(mLvl, j); - for(i = a3; i+2*j < b; i += 2*j) - this.mergeWithBufFW(array, i, i+j, i+2*j, i-p); + for (i = a3; i + 2 * j < b; i += 2 * j) + this.mergeWithBufFW(array, i, i + j, i + 2 * j, i - p); - if(i+j < b) this.mergeWithBufFW(array, i, i+j, b, i-p); - else this.shiftFW(array, i-p, i, b); + if (i + j < b) + this.mergeWithBufFW(array, i, i + j, b, i - p); + else + this.shiftFW(array, i - p, i, b); - a3 -= p; b -= p; + a3 -= p; + b -= p; } - i = b-n%(2*j); + i = b - n % (2 * j); - if(i+j < b) this.mergeWithBufBW(array, i, i+j, b, b+j); - else this.shiftBW(array, i, b, b+j); + if (i + j < b) + this.mergeWithBufBW(array, i, i + j, b, b + j); + else + this.shiftBW(array, i, b, b + j); - for(i -= 2*j; i >= a3; i -= 2*j) - this.mergeWithBufBW(array, i, i+j, i+2*j, i+3*j); + for (i -= 2 * j; i >= a3; i -= 2 * j) + this.mergeWithBufBW(array, i, i + j, i + 2 * j, i + 3 * j); - a3 += j; b += j; j *= 2; + a3 += j; + b += j; + j *= 2; } - if(keys >= j) { - for(i = a3; i+2*j < b; i += 2*j) - this.mergeWithBufFW(array, i, i+j, i+2*j, i-j); + if (keys >= j) { + for (i = a3; i + 2 * j < b; i += 2 * j) + this.mergeWithBufFW(array, i, i + j, i + 2 * j, i - j); - if(i+j < b) this.mergeWithBufFW(array, i, i+j, b, i-j); - else this.shiftFW(array, i-j, i, b); + if (i + j < b) + this.mergeWithBufFW(array, i, i + j, b, i - j); + else + this.shiftFW(array, i - j, i, b); - a3 -= j; b -= j; j *= 2; + a3 -= j; + b -= j; + j *= 2; - i = b-n%(2*j); + i = b - n % (2 * j); - if(i+j < b) this.dualMergeBW(array, i, i+j, b, b+j/2); - else this.shiftBW(array, i, b, b+j/2); + if (i + j < b) + this.dualMergeBW(array, i, i + j, b, b + j / 2); + else + this.shiftBW(array, i, b, b + j / 2); - for(i -= 2*j; i >= a3; i -= 2*j) - this.dualMergeBW(array, i, i+j, i+2*j, i+2*j+j/2); + for (i -= 2 * j; i >= a3; i -= 2 * j) + this.dualMergeBW(array, i, i + j, i + 2 * j, i + 2 * j + j / 2); - a3 += j/2; b += j/2; j *= 2; + a3 += j / 2; + b += j / 2; + j *= 2; } this.rotate(array, a, a2, a3); - a2 = a1+keys; + a2 = a1 + keys; MaxHeapSort sortHeap = new MaxHeapSort(this.arrayVisualizer); sortHeap.customHeapSort(array, a, a1, 1); } Writes.arraycopy(tmp, 0, array, a2, bLen, 1, true, false); - //main block merge + // main block merge this.unshuffle(array, a, a1); - int limit = bLen*(kLen+2); + int limit = bLen * (kLen + 2); - for(int k = j/bLen-1; j < n && Math.min(2*j, n) <= limit; j *= 2, k = 2*k+1) { - for(i = a3; i+2*j <= b; i += 2*j) - this.blockMerge(array, tmp, i, i+j, i+2*j, k, 2*k, a, a+kLen, a1, a1+kLen, bLen); + for (int k = j / bLen - 1; j < n && Math.min(2 * j, n) <= limit; j *= 2, k = 2 * k + 1) { + for (i = a3; i + 2 * j <= b; i += 2 * j) + this.blockMerge(array, tmp, i, i + j, i + 2 * j, k, 2 * k, a, a + kLen, a1, a1 + kLen, bLen); - if(i+j < b) - this.blockMerge(array, tmp, i, i+j, b, k, (b-i-1)/bLen-1, a, a+kLen, a1, a1+kLen, bLen); + if (i + j < b) + this.blockMerge(array, tmp, i, i + j, b, k, (b - i - 1) / bLen - 1, a, a + kLen, a1, a1 + kLen, bLen); } - //in-place block merge - for(; j < n; j *= 2) { - bLen = (2*j)/kLen; - int lenA = j%bLen, lenB = lenA; + // in-place block merge + for (; j < n; j *= 2) { + bLen = (2 * j) / kLen; + int lenA = j % bLen, lenB = lenA; - for(i = a3; i+2*j <= b; i += 2*j) - this.blockMergeEasy(array, i, i+j, i+2*j, lenA, lenB, kLen/2, kLen, a, a+kLen, a1, a1+kLen, bLen); + for (i = a3; i + 2 * j <= b; i += 2 * j) + this.blockMergeEasy(array, i, i + j, i + 2 * j, lenA, lenB, kLen / 2, kLen, a, a + kLen, a1, a1 + kLen, + bLen); - if(i+j < b) - this.blockMergeEasy(array, i, i+j, b, lenA, (b-i-j)%bLen, kLen/2, kLen/2+(b-i-j)/bLen, a, a+kLen, a1, a1+kLen, bLen); + if (i + j < b) + this.blockMergeEasy(array, i, i + j, b, lenA, (b - i - j) % bLen, kLen / 2, + kLen / 2 + (b - i - j) / bLen, a, a + kLen, a1, a1 + kLen, bLen); } - //cleaning up - this.multiSwap(array, a1+bSep, a1+kLen+bSep, kLen-bSep); //restore bit buffer initial position + // cleaning up + this.multiSwap(array, a1 + bSep, a1 + kLen + bSep, kLen - bSep); // restore bit buffer initial position this.laziestSortExt(array, tmp, a, a3); this.redistBuffer(array, tmp, a, a3, b); Writes.deleteExternalArray(tmp); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/CircularGrailSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/CircularGrailSort.java index 857d3772..fc45ecc1 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/CircularGrailSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/CircularGrailSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,99 +29,93 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Circular Grail") public final class CircularGrailSort extends Sort { - public CircularGrailSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Circular Grail"); - this.setRunAllSortsName("Circular Grail Sort"); - this.setRunSortName("Circular Grailsort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public CircularGrailSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int n; private void circSwap(int[] array, int a, int b) { - Writes.swap(array, a%n, b%n, 1, true, false); + Writes.swap(array, a % n, b % n, 1, true, false); } + private int circCompareIndices(int[] array, int a, int b) { - return Reads.compareValues(array[a%n], array[b%n]); + return Reads.compareValues(array[a % n], array[b % n]); } private void shiftFW(int[] array, int a, int m, int b) { - while(m < b) this.circSwap(array, a++, m++); + while (m < b) + this.circSwap(array, a++, m++); } + private void shiftBW(int[] array, int a, int m, int b) { - while(m > a) this.circSwap(array, --b, --m); + while (m > a) + this.circSwap(array, --b, --m); } private void insertion(int[] array, int a, int b) { - for(int i = a+1; i < b; i++) - while(i > a && this.circCompareIndices(array, i-1, i) > 0) + for (int i = a + 1; i < b; i++) + while (i > a && this.circCompareIndices(array, i - 1, i) > 0) this.circSwap(array, i, --i); } private void multiSwap(int[] array, int a, int b, int len) { - for(int i = 0; i < len; i++) - this.circSwap(array, a+i, b+i); + for (int i = 0; i < len; i++) + this.circSwap(array, a + i, b + i); } - private void rotate(int[] array, int a, int m, int b) { - int l = m-a, r = b-m; + private void rotate(int[] array, int a, int m, int b) { + int l = m - a, r = b - m; - while(l > 0 && r > 0) { - if(r < l) { - this.multiSwap(array, m-r, m, r); + while (l > 0 && r > 0) { + if (r < l) { + this.multiSwap(array, m - r, m, r); b -= r; m -= r; l -= r; - } - else { + } else { this.multiSwap(array, a, m, l); a += l; m += l; r -= l; - } - } - } + } + } + } private void inPlaceMerge(int[] array, int a, int m, int b) { int i = a, j = m, k; - while(i < j && j < b) { - if(this.circCompareIndices(array, i, j) > 0) { + while (i < j && j < b) { + if (this.circCompareIndices(array, i, j) > 0) { k = j; - while(++k < b && this.circCompareIndices(array, i, k) > 0); + while (++k < b && this.circCompareIndices(array, i, k) > 0) + ; this.rotate(array, i, j, k); - i += k-j; + i += k - j; j = k; - } - else i++; + } else + i++; } } private int merge(int[] array, int p, int a, int m, int b, boolean full) { int i = a, j = m; - while(i < m && j < b) { - if(this.circCompareIndices(array, i, j) <= 0) + while (i < m && j < b) { + if (this.circCompareIndices(array, i, j) <= 0) this.circSwap(array, p++, i++); else this.circSwap(array, p++, j++); } - if(i < m) { - if(i > p) this.shiftFW(array, p, i, m); - } - else if(full) + if (i < m) { + if (i > p) + this.shiftFW(array, p, i, m); + } else if (full) this.shiftFW(array, p, j, b); return i < m ? i : j; @@ -129,81 +124,85 @@ else if(full) private boolean blockLessThan(int[] array, int a, int b, int bLen) { int cmp = this.circCompareIndices(array, a, b); - return cmp == -1 || (cmp == 0 && this.circCompareIndices(array, a+bLen-1, b+bLen-1) == -1); + return cmp == -1 || (cmp == 0 && this.circCompareIndices(array, a + bLen - 1, b + bLen - 1) == -1); } private void blockMerge(int[] array, int a, int m, int b, int bLen) { - int b1 = b-(b-m-1)%bLen-1; + int b1 = b - (b - m - 1) % bLen - 1; - if(b1 > m) { + if (b1 > m) { int b2 = b1; - for(int i = m-bLen; i > a && this.blockLessThan(array, b1, i, bLen); i -= bLen, b2 -= bLen); + for (int i = m - bLen; i > a && this.blockLessThan(array, b1, i, bLen); i -= bLen, b2 -= bLen) + ; - for(int j = a; j < b1-bLen; j += bLen) { + for (int j = a; j < b1 - bLen; j += bLen) { int min = j; - for(int i = min+bLen; i < b1; i += bLen) - if(this.blockLessThan(array, i, min, bLen)) min = i; + for (int i = min + bLen; i < b1; i += bLen) + if (this.blockLessThan(array, i, min, bLen)) + min = i; - if(min != j) this.multiSwap(array, j, min, bLen); + if (min != j) + this.multiSwap(array, j, min, bLen); } int f = a; - for(int i = a+bLen; i < b2; i += bLen) { - f = this.merge(array, f-bLen, f, i, i+bLen, false); + for (int i = a + bLen; i < b2; i += bLen) { + f = this.merge(array, f - bLen, f, i, i + bLen, false); - if(f < i) { - this.shiftBW(array, f, i, i+bLen); + if (f < i) { + this.shiftBW(array, f, i, i + bLen); f += bLen; } } - this.merge(array, f-bLen, f, b1, b, true); - } - else this.merge(array, a-bLen, a, m, b, true); + this.merge(array, f - bLen, f, b1, b, true); + } else + this.merge(array, a - bLen, a, m, b, true); } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { this.n = length; - if(length <= 16) { + if (length <= 16) { this.insertion(array, 0, length); return; } int bLen = 1; - for(; bLen*bLen < length; bLen *= 2); + for (; bLen * bLen < length; bLen *= 2) + ; - int i = bLen, j = 1, len = length-i, b = length; + int i = bLen, j = 1, len = length - i, b = length; - while(j <= bLen) { - for(; i+2*j < b; i += 2*j) - this.merge(array, i-j, i, i+j, i+2*j, true); - if(i+j < b) - this.merge(array, i-j, i, i+j, b, true); + while (j <= bLen) { + for (; i + 2 * j < b; i += 2 * j) + this.merge(array, i - j, i, i + j, i + 2 * j, true); + if (i + j < b) + this.merge(array, i - j, i, i + j, b, true); else - this.shiftFW(array, i-j, i, b); + this.shiftFW(array, i - j, i, b); - i = b+bLen-j; - b = i+len; + i = b + bLen - j; + b = i + len; j *= 2; } - while(j < len) { - for(; i+2*j < b; i += 2*j) - this.blockMerge(array, i, i+j, i+2*j, bLen); - if(i+j < b) - this.blockMerge(array, i, i+j, b, bLen); + while (j < len) { + for (; i + 2 * j < b; i += 2 * j) + this.blockMerge(array, i, i + j, i + 2 * j, bLen); + if (i + j < b) + this.blockMerge(array, i, i + j, b, bLen); else - this.shiftFW(array, i-bLen, i, b); + this.shiftFW(array, i - bLen, i, b); i = b; b += len; j *= 2; } - this.insertion(array, i-bLen, i); - this.inPlaceMerge(array, i-bLen, i, b); + this.insertion(array, i - bLen, i); + this.inPlaceMerge(array, i - bLen, i, b); - this.rotate(array, 0, (i-bLen)%n, length); - } + this.rotate(array, 0, (i - bLen) % n, length); + } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/CocktailMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/CocktailMergeSort.java index 9b132cfd..fdd2c7f8 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/CocktailMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/CocktailMergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.exchange.CocktailShakerSort; import io.github.arrayv.sorts.templates.Sort; import io.github.arrayv.sorts.templates.TimSorting; @@ -13,26 +14,20 @@ // this is constant time, as the minrun value is not dependent on the number of elements we are sorting, but // Cocktail Shaker has worse constant factors than Insertion Sort. So basically, this is just for fun. // But hey, why not? ;) - +@SortMeta(name = "Cocktail Merge") public class CocktailMergeSort extends Sort { - private TimSorting timSortInstance; // TimSort cannot be simply written off as an abstract class, as it creates an instance of itself - // in order to track its state. Plus, it contains both instance and static methods, requiring even - // more refactoring, which would be just doing unnecessary busy work. Instead of what we've done for - // the rest of the algorithms, we'll favor composition over inheritance here and pass "util" objects + private TimSorting timSortInstance; // TimSort cannot be simply written off as an abstract class, as it creates an + // instance of itself + // in order to track its state. Plus, it contains both instance and static + // methods, requiring even + // more refactoring, which would be just doing unnecessary busy work. Instead of + // what we've done for + // the rest of the algorithms, we'll favor composition over inheritance here and + // pass "util" objects // to it. public CocktailMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Cocktail Merge"); - this.setRunAllSortsName("Cocktail Merge Sort"); - this.setRunSortName("Cocktail Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override @@ -42,8 +37,7 @@ public void runSort(int[] array, int sortLength, int bucketCount) throws Excepti if (sortLength == minRunLen) { cocktailShaker.runSort(array, sortLength, bucketCount); - } - else { + } else { int i = 0; for (; i <= (sortLength - minRunLen); i += minRunLen) { cocktailShaker.customSort(array, i, i + minRunLen); diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/DropMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/DropMergeSort.java index f87b6fa1..7f3d9564 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/DropMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/DropMergeSort.java @@ -3,6 +3,7 @@ import java.util.List; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -26,20 +27,10 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Drop Merge") public final class DropMergeSort extends Sort { public DropMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Drop Merge"); - this.setRunAllSortsName("Drop Merge Sort"); - this.setRunSortName("Drop Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private final int RECENCY = 8; @@ -47,13 +38,14 @@ public DropMergeSort(ArrayVisualizer arrayVisualizer) { private final double EARLY_OUT_DISORDER_FRACTION = 0.6; private void truncateArrayList(List arrayList, int len) { - int size = arrayList.size(); - arrayList.subList(len, size).clear(); + int size = arrayList.size(); + arrayList.subList(len, size).clear(); } @Override public void runSort(int[] array, int length, int bucketCount) { - if (length < 2) return; + if (length < 2) + return; PDQBranchedSort pdqSort = new PDQBranchedSort(arrayVisualizer); List dropped = Writes.createArrayList(length); @@ -87,50 +79,52 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.write(array, write++, array[read++], 1, true, false); num_dropped_in_a_row = 0; } else { - if (num_dropped_in_a_row == 0 && write >= 2 && Reads.compareIndices(array, read, write - 2, 0, false) >= 0) { - // Quick undo: drop previously accepted element, and overwrite with new one - Writes.arrayListAdd(dropped, array[write - 1], false, 0); - Writes.write(array, write - 1, array[read++], 1, true, false); - continue; - } - - if (num_dropped_in_a_row < RECENCY) { - Writes.arrayListAdd(dropped, array[read++], false, 0); - Delays.sleep(1); - num_dropped_in_a_row++; - } else { - //We accepted something num_dropped_in_row elements back that made us drop all RECENCY subsequent items. - //Accepting that element was obviously a mistake - so let's undo it! - - // Undo dropping the last num_dropped_in_row elements: - int trunc_to_length = dropped.size() - num_dropped_in_a_row; - truncateArrayList(dropped, trunc_to_length); - read -= num_dropped_in_a_row; - - int num_backtracked = 1; - write--; - - int max_of_dropped = read; - for (int i = read + 1; i <= read + num_dropped_in_a_row; i++) { - if (Reads.compareValues(array[i], max_of_dropped) == 1) { - max_of_dropped = array[i]; - } - } - - while (write >= 1 && Reads.compareValues(max_of_dropped, array[write - 1]) == -1) { - Highlights.markArray(1, --write); - Delays.sleep(1); - num_backtracked++; - } - - for (int i = write; i < write + num_backtracked; i++) { - Highlights.markArray(1, i); - Writes.arrayListAdd(dropped, array[i], true, 0); - Delays.sleep(1); - } - - num_dropped_in_a_row = 0; - } + if (num_dropped_in_a_row == 0 && write >= 2 + && Reads.compareIndices(array, read, write - 2, 0, false) >= 0) { + // Quick undo: drop previously accepted element, and overwrite with new one + Writes.arrayListAdd(dropped, array[write - 1], false, 0); + Writes.write(array, write - 1, array[read++], 1, true, false); + continue; + } + + if (num_dropped_in_a_row < RECENCY) { + Writes.arrayListAdd(dropped, array[read++], false, 0); + Delays.sleep(1); + num_dropped_in_a_row++; + } else { + // We accepted something num_dropped_in_row elements back that made us drop all + // RECENCY subsequent items. + // Accepting that element was obviously a mistake - so let's undo it! + + // Undo dropping the last num_dropped_in_row elements: + int trunc_to_length = dropped.size() - num_dropped_in_a_row; + truncateArrayList(dropped, trunc_to_length); + read -= num_dropped_in_a_row; + + int num_backtracked = 1; + write--; + + int max_of_dropped = read; + for (int i = read + 1; i <= read + num_dropped_in_a_row; i++) { + if (Reads.compareValues(array[i], max_of_dropped) == 1) { + max_of_dropped = array[i]; + } + } + + while (write >= 1 && Reads.compareValues(max_of_dropped, array[write - 1]) == -1) { + Highlights.markArray(1, --write); + Delays.sleep(1); + num_backtracked++; + } + + for (int i = write; i < write + num_backtracked; i++) { + Highlights.markArray(1, i); + Writes.arrayListAdd(dropped, array[i], true, 0); + Delays.sleep(1); + } + + num_dropped_in_a_row = 0; + } } } @@ -142,7 +136,6 @@ public void runSort(int[] array, int length, int bucketCount) { pdqSort.customSort(array, write, length); - int[] buffer = Writes.createExternalArray(dropped.size()); Writes.arraycopy(array, write, buffer, 0, dropped.size(), 1, true, true); diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/EctaSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/EctaSort.java index ee297349..d8de9c84 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/EctaSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/EctaSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.BinaryDoubleInsertionSort; import io.github.arrayv.sorts.templates.Sort; @@ -29,51 +30,47 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Ecta") public final class EctaSort extends Sort { public EctaSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Ecta"); - this.setRunAllSortsName("Ecta Sort"); - this.setRunSortName("Ectasort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + super(arrayVisualizer); + } private int getMinRun(int n) { int mRun = n; - for(; mRun >= 32; mRun = (mRun+1)/2); + for (; mRun >= 32; mRun = (mRun + 1) / 2) + ; return mRun; } private void shift(int[] array, int a, int m, int b) { - while(m < b) Writes.write(array, a++, array[m++], 1, true, false); + while (m < b) + Writes.write(array, a++, array[m++], 1, true, false); } + private void shiftBW(int[] array, int a, int m, int b) { - while(m > a) Writes.write(array, --b, array[--m], 1, true, false); + while (m > a) + Writes.write(array, --b, array[--m], 1, true, false); } private void mergeTo(int[] array, int a, int m, int b, int p) { int i = a, j = m; - while(i < m && j < b) { - if(Reads.compareIndices(array, i, j, 0, false) <= 0) + while (i < m && j < b) { + if (Reads.compareIndices(array, i, j, 0, false) <= 0) Writes.write(array, p++, array[i++], 1, true, false); else Writes.write(array, p++, array[j++], 1, true, false); } - while(i < m) Writes.write(array, p++, array[i++], 1, true, false); - while(j < b) Writes.write(array, p++, array[j++], 1, true, false); + while (i < m) + Writes.write(array, p++, array[i++], 1, true, false); + while (j < b) + Writes.write(array, p++, array[j++], 1, true, false); } private void pingPongMerge(int[] array, int a, int m1, int m2, int m3, int b, int p) { - int p1 = p + m2-a, pEnd = p + b-a; + int p1 = p + m2 - a, pEnd = p + b - a; this.mergeTo(array, a, m1, m2, p); this.mergeTo(array, m2, m3, b, p1); @@ -81,50 +78,52 @@ private void pingPongMerge(int[] array, int a, int m1, int m2, int m3, int b, in } private void merge(int[] array, int a, int m, int b, int p) { - int len = b-m, pEnd = p+len-1; + int len = b - m, pEnd = p + len - 1; Writes.arraycopy(array, m--, array, p, len, 1, true, false); - while(m >= a && pEnd >= p) { - if(Reads.compareValues(array[m], array[pEnd]) > 0) + while (m >= a && pEnd >= p) { + if (Reads.compareValues(array[m], array[pEnd]) > 0) Writes.write(array, --b, array[m--], 1, true, false); - else Writes.write(array, --b, array[pEnd--], 1, true, false); + else + Writes.write(array, --b, array[pEnd--], 1, true, false); } - while(pEnd >= p) + while (pEnd >= p) Writes.write(array, --b, array[pEnd--], 1, true, false); } private void mergeFromBuf(int[] array, int[] buf, int a, int m, int b, int bufLen) { int i = 0; - while(i < bufLen && m < b) { + while (i < bufLen && m < b) { Highlights.markArray(2, i); - if(Reads.compareValues(buf[i], array[m]) <= 0) + if (Reads.compareValues(buf[i], array[m]) <= 0) Writes.write(array, a++, buf[i++], 1, true, false); else Writes.write(array, a++, array[m++], 1, true, false); } - while(i < bufLen) { + while (i < bufLen) { Highlights.markArray(2, i); Writes.write(array, a++, buf[i++], 1, true, false); } } private void dualMergeFromBufBW(int[] array, int[] buf, int a, int a1, int m, int b, int bufLen) { - int i = bufLen-1; - bufLen -= b-(m--); + int i = bufLen - 1; + bufLen -= b - (m--); - while(i >= bufLen && m >= a1) { + while (i >= bufLen && m >= a1) { Highlights.markArray(2, i); - if(Reads.compareValues(buf[i], array[m]) > 0) + if (Reads.compareValues(buf[i], array[m]) > 0) Writes.write(array, --b, buf[i--], 1, true, false); else Writes.write(array, --b, array[m--], 1, true, false); } - if(m < a1) - while(i >= 0) Writes.write(array, --b, buf[i--], 1, true, false); + if (m < a1) + while (i >= 0) + Writes.write(array, --b, buf[i--], 1, true, false); else this.mergeFromBuf(array, buf, a, a1, b, bufLen); } @@ -133,29 +132,29 @@ private int mergeSort(int[] array, int a, int b, int p, int mRun, int bufLen) { BinaryDoubleInsertionSort smallSort = new BinaryDoubleInsertionSort(this.arrayVisualizer); int i = a, j = mRun; - for(; i+j <= b; i += j) - smallSort.customDoubleInsert(array, i, i+j, 0.5); + for (; i + j <= b; i += j) + smallSort.customDoubleInsert(array, i, i + j, 0.5); smallSort.customDoubleInsert(array, i, b, 0.5); - while(4*j <= bufLen) { - for(i = a; i+4*j <= b; i += 4*j) - this.pingPongMerge(array, i, i+j, i+2*j, i+3*j, i+4*j, p); + while (4 * j <= bufLen) { + for (i = a; i + 4 * j <= b; i += 4 * j) + this.pingPongMerge(array, i, i + j, i + 2 * j, i + 3 * j, i + 4 * j, p); - if(i+3*j < b) - this.pingPongMerge(array, i, i+j, i+2*j, i+3*j, b, p); - else if(i+2*j < b) - this.pingPongMerge(array, i, i+j, i+2*j, b, b, p); - else if(i+j < b) - this.merge(array, i, i+j, b, p); + if (i + 3 * j < b) + this.pingPongMerge(array, i, i + j, i + 2 * j, i + 3 * j, b, p); + else if (i + 2 * j < b) + this.pingPongMerge(array, i, i + j, i + 2 * j, b, b, p); + else if (i + j < b) + this.merge(array, i, i + j, b, p); j *= 4; } - while(j <= bufLen) { - for(i = a; i+2*j <= b; i += 2*j) - this.merge(array, i, i+j, i+2*j, p); + while (j <= bufLen) { + for (i = a; i + 2 * j <= b; i += 2 * j) + this.merge(array, i, i + j, i + 2 * j, p); - if(i+j < b) - this.merge(array, i, i+j, b, p); + if (i + j < b) + this.merge(array, i, i + j, b, p); j *= 2; } @@ -166,23 +165,22 @@ else if(i+j < b) private void blockCycle(int[] array, int[] keys, int a, int bLen, int t, int p, boolean excl, boolean fw) { int s = fw ? bLen : -bLen; - for(int i = 0; i < t; i++) { - if(Reads.compareOriginalValues(i, keys[i]) != 0) { - Writes.arraycopy(array, a + i*s, array, p, bLen, 1, true, false); + for (int i = 0; i < t; i++) { + if (Reads.compareOriginalValues(i, keys[i]) != 0) { + Writes.arraycopy(array, a + i * s, array, p, bLen, 1, true, false); int j = i, next = keys[i]; do { - if(!(excl && j == t-1)) - Writes.arraycopy(array, a + next*s, array, a + j*s, bLen, 1, true, false); + if (!(excl && j == t - 1)) + Writes.arraycopy(array, a + next * s, array, a + j * s, bLen, 1, true, false); Highlights.markArray(2, j); Writes.write(keys, j, j, 1, false, true); j = next; next = keys[next]; - } - while(Reads.compareOriginalValues(next, i) != 0); + } while (Reads.compareOriginalValues(next, i) != 0); - Writes.arraycopy(array, p, array, a + j*s, bLen, 1, true, false); + Writes.arraycopy(array, p, array, a + j * s, bLen, 1, true, false); Highlights.markArray(2, j); Writes.write(keys, j, j, 1, false, true); } @@ -192,29 +190,26 @@ private void blockCycle(int[] array, int[] keys, int a, int bLen, int t, int p, private void ectaMergeFW(int[] array, int[] tags, int a, int m, int b, int bLen) { int i = a, j = m, t = 0, tc = 0; - int[] s = {2*bLen, 0}; - int[] p = {a-2*bLen, m}; + int[] s = { 2 * bLen, 0 }; + int[] p = { a - 2 * bLen, m }; do { int c = s[0] < bLen ? 1 : 0; - for(int k = 0; k < bLen; k++) { - if(i < m && j < b) { - if(Reads.compareValues(array[i], array[j]) <= 0) { - Writes.write(array, p[c]+k, array[i++], 1, true, false); + for (int k = 0; k < bLen; k++) { + if (i < m && j < b) { + if (Reads.compareValues(array[i], array[j]) <= 0) { + Writes.write(array, p[c] + k, array[i++], 1, true, false); s[0]++; - } - else { - Writes.write(array, p[c]+k, array[j++], 1, true, false); + } else { + Writes.write(array, p[c] + k, array[j++], 1, true, false); s[1]++; } - } - else if(i < m) { - Writes.write(array, p[c]+k, array[i++], 1, true, false); + } else if (i < m) { + Writes.write(array, p[c] + k, array[i++], 1, true, false); s[0]++; - } - else { - Writes.write(array, p[c]+k, array[j++], 1, true, false); + } else { + Writes.write(array, p[c] + k, array[j++], 1, true, false); s[1]++; } } @@ -223,44 +218,42 @@ else if(i < m) { Highlights.markArray(2, tc); Writes.write(tags, tc++, c == 0 ? t++ : -1, 1, false, true); - } - while(i < m || j < b); + } while (i < m || j < b); - if(s[0] > 0) Writes.write(tags, tc, t++, 1, false, true); + if (s[0] > 0) + Writes.write(tags, tc, t++, 1, false, true); - for(int k = 2; k < tc; k++) { - if(tags[k] == -1) { + for (int k = 2; k < tc; k++) { + if (tags[k] == -1) { Highlights.markArray(2, k); Writes.write(tags, k, t++, 1, false, true); } } - this.blockCycle(array, tags, a-2*bLen, bLen, t, b-bLen, s[0] > 0, true); + this.blockCycle(array, tags, a - 2 * bLen, bLen, t, b - bLen, s[0] > 0, true); } + private void ectaMergeBW(int[] array, int[] tags, int a, int m, int b, int bLen) { - int i = b-1, j = m-1, t = 0, tc = 0; - int[] s = {2*bLen, 0}; - int[] p = {b+2*bLen, m}; + int i = b - 1, j = m - 1, t = 0, tc = 0; + int[] s = { 2 * bLen, 0 }; + int[] p = { b + 2 * bLen, m }; do { int c = s[0] < bLen ? 1 : 0; - for(int k = 1; k <= bLen; k++) { - if(i >= m && j >= a) { - if(Reads.compareValues(array[i], array[j]) >= 0) { - Writes.write(array, p[c]-k, array[i--], 1, true, false); + for (int k = 1; k <= bLen; k++) { + if (i >= m && j >= a) { + if (Reads.compareValues(array[i], array[j]) >= 0) { + Writes.write(array, p[c] - k, array[i--], 1, true, false); s[0]++; - } - else { - Writes.write(array, p[c]-k, array[j--], 1, true, false); + } else { + Writes.write(array, p[c] - k, array[j--], 1, true, false); s[1]++; } - } - else if(i >= m) { - Writes.write(array, p[c]-k, array[i--], 1, true, false); + } else if (i >= m) { + Writes.write(array, p[c] - k, array[i--], 1, true, false); s[0]++; - } - else { - Writes.write(array, p[c]-k, array[j--], 1, true, false); + } else { + Writes.write(array, p[c] - k, array[j--], 1, true, false); s[1]++; } } @@ -269,29 +262,28 @@ else if(i >= m) { Highlights.markArray(2, tc); Writes.write(tags, tc++, c == 0 ? t++ : -1, 1, false, true); - } - while(i >= m || j >= a); + } while (i >= m || j >= a); - if(s[0] > 0) Writes.write(tags, tc, t++, 1, false, true); + if (s[0] > 0) + Writes.write(tags, tc, t++, 1, false, true); - for(int k = 2; k < tc; k++) { - if(tags[k] == -1) { + for (int k = 2; k < tc; k++) { + if (tags[k] == -1) { Highlights.markArray(2, k); Writes.write(tags, k, t++, 1, false, true); } } - this.blockCycle(array, tags, b+bLen, bLen, t, a, s[0] > 0, false); + this.blockCycle(array, tags, b + bLen, bLen, t, a, s[0] > 0, false); } - @Override - public void runSort(int[] array, int length, int bucketCount) { - if(length < 256) { - if(length <= 32) { + @Override + public void runSort(int[] array, int length, int bucketCount) { + if (length < 256) { + if (length <= 32) { BinaryDoubleInsertionSort smallSort = new BinaryDoubleInsertionSort(this.arrayVisualizer); smallSort.customDoubleInsert(array, 0, length, 0.5); - } - else { - int mRun = this.getMinRun(length), bufLen = length/2; + } else { + int mRun = this.getMinRun(length), bufLen = length / 2; int[] buf = Writes.createExternalArray(bufLen); Writes.arraycopy(array, bufLen, buf, 0, bufLen, 1, true, true); @@ -308,13 +300,14 @@ public void runSort(int[] array, int length, int bucketCount) { } int mRun = this.getMinRun(length), bLen = mRun; - for(; bLen*bLen < length/2; bLen *= 2); - int bufLen = 2*bLen + length%bLen; + for (; bLen * bLen < length / 2; bLen *= 2) + ; + int bufLen = 2 * bLen + length % bLen; - int a = bufLen, b = length, len = b-a; + int a = bufLen, b = length, len = b - a; - int[] buf = Writes.createExternalArray(bufLen); - int[] tags = Writes.createExternalArray(len/bLen+1); + int[] buf = Writes.createExternalArray(bufLen); + int[] tags = Writes.createExternalArray(len / bLen + 1); Writes.arraycopy(array, a, buf, 0, bufLen, 1, true, true); this.mergeSort(array, 0, a, a, this.getMinRun(bufLen), bufLen); @@ -325,38 +318,45 @@ public void runSort(int[] array, int length, int bucketCount) { int i = a, j = this.mergeSort(array, a, b, 0, mRun, bufLen); boolean bw = false; - while(j < len) { - for(i = a; i+2*j <= b; i += 2*j) - this.ectaMergeFW(array, tags, i, i+j, i+2*j, bLen); + while (j < len) { + for (i = a; i + 2 * j <= b; i += 2 * j) + this.ectaMergeFW(array, tags, i, i + j, i + 2 * j, bLen); - if(i+j < b) this.ectaMergeFW(array, tags, i, i+j, b, bLen); - else this.shift(array, i-2*bLen, i, b); + if (i + j < b) + this.ectaMergeFW(array, tags, i, i + j, b, bLen); + else + this.shift(array, i - 2 * bLen, i, b); j *= 2; - a -= 2*bLen; - b -= 2*bLen; + a -= 2 * bLen; + b -= 2 * bLen; - if(j >= len) { + if (j >= len) { bw = true; break; } - for(i = a; i+2*j <= b; i += 2*j); + for (i = a; i + 2 * j <= b; i += 2 * j) + ; - if(i+j < b) this.ectaMergeBW(array, tags, i, i+j, b, bLen); - else this.shiftBW(array, i, b, b+2*bLen); + if (i + j < b) + this.ectaMergeBW(array, tags, i, i + j, b, bLen); + else + this.shiftBW(array, i, b, b + 2 * bLen); - for(i -= 2*j; i >= a; i -= 2*j) - this.ectaMergeBW(array, tags, i, i+j, i+2*j, bLen); + for (i -= 2 * j; i >= a; i -= 2 * j) + this.ectaMergeBW(array, tags, i, i + j, i + 2 * j, bLen); j *= 2; - a += 2*bLen; - b += 2*bLen; + a += 2 * bLen; + b += 2 * bLen; } - if(bw) this.dualMergeFromBufBW(array, buf, 0, a, b, length, bufLen); - else this.mergeFromBuf(array, buf, 0, a, b, bufLen); + if (bw) + this.dualMergeFromBufBW(array, buf, 0, a, b, length, bufLen); + else + this.mergeFromBuf(array, buf, 0, a, b, bufLen); Writes.deleteExternalArray(buf); Writes.deleteExternalArray(tags); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/FifthMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/FifthMergeSort.java index b0ff1332..b58800d0 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/FifthMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/FifthMergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.BinaryInsertionSort; import io.github.arrayv.sorts.templates.Sort; @@ -27,7 +28,7 @@ of this software and associated documentation files (the "Software"), to deal OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - +@SortMeta(name = "Fifth Merge") public final class FifthMergeSort extends Sort { protected final class IndexPair { public int aEnd, bEnd; @@ -42,16 +43,6 @@ public IndexPair(int aEnd, int bEnd) { public FifthMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Fifth Merge"); - this.setRunAllSortsName("Fifth Merge Sort"); - this.setRunSortName("Fifth Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } protected void mergeInPlaceForwards(int[] array, int buffer, int start, int mid, int end) { @@ -99,7 +90,8 @@ protected IndexPair mergeInPlaceBackwards(int[] array, int buffer, int bufferLen return new IndexPair(left + 1, right + 1); } - protected void mergeForwardsWithBuffer(int[] array, int[] buffer, int dest, int left, int leftEnd, int mid, int end) { + protected void mergeForwardsWithBuffer(int[] array, int[] buffer, int dest, int left, int leftEnd, int mid, + int end) { int right = mid; while (left < leftEnd && right < end) { Highlights.markArray(2, left); @@ -186,7 +178,7 @@ protected void pingPong(int[] array, int[] buffer, int start, int end) { } } - public void fifthMergeSort(int[] array, int currentLength) { + public void fifthMergeSort(int[] array, int currentLength) { inserter = new BinaryInsertionSort(arrayVisualizer); int fifthLen = currentLength / 5; @@ -212,10 +204,10 @@ public void fifthMergeSort(int[] array, int currentLength) { mergeForwardsWithBuffer(array, buffer, 0, 0, bufferLen, bufferLen, currentLength); Writes.deleteExternalArray(buffer); - } + } @Override public void runSort(int[] array, int currentLength, int bucketCount) { - fifthMergeSort(array, currentLength); + fifthMergeSort(array, currentLength); } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/FlanSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/FlanSort.java index 59ce93b3..8f726780 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/FlanSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/FlanSort.java @@ -3,6 +3,7 @@ import java.util.Random; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.MultiWayMergeSorting; /* @@ -30,117 +31,110 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Flan") public final class FlanSort extends MultiWayMergeSorting { - public FlanSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Flan"); - this.setRunAllSortsName("Flan Sort"); - this.setRunSortName("Flansort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - //unstable sorting algorithm performing an average of - //O(n log n) comparisons and O(n) moves in O(1) memory + public FlanSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } + + // unstable sorting algorithm performing an average of + // O(n log n) comparisons and O(n) moves in O(1) memory private final int G = 14; private final int R = 4; private int medianOfThree(int[] array, int a, int m, int b) { - if(Reads.compareValues(array[m], array[a]) > 0) { - if(Reads.compareValues(array[m], array[b]) < 0) + if (Reads.compareIndices(array, m, a, 0.5, true) > 0) { + if (Reads.compareIndices(array, m, b, 0.5, true) < 0) return m; - if(Reads.compareValues(array[a], array[b]) > 0) + if (Reads.compareIndices(array, a, b, 0.5, true) > 0) return a; else return b; - } - else { - if(Reads.compareValues(array[m], array[b]) > 0) + } else { + if (Reads.compareIndices(array, m, b, 0.5, true) > 0) return m; - if(Reads.compareValues(array[a], array[b]) < 0) + if (Reads.compareIndices(array, a, b, 0.5, true) < 0) return a; else return b; } } - //when shuffled the first 9 and 27 items will be accessed instead respectively + + // when shuffled the first 9 and 27 items will be accessed instead respectively private int ninther(int[] array, int a, int b) { - int s = (b-a)/9; + int s = (b - a) / 9; - int a1 = this.medianOfThree(array, a, a+ s, a+2*s); - int m1 = this.medianOfThree(array, a+3*s, a+4*s, a+5*s); - int b1 = this.medianOfThree(array, a+6*s, a+7*s, a+8*s); + int a1 = this.medianOfThree(array, a, a + s, a + 2 * s); + int m1 = this.medianOfThree(array, a + 3 * s, a + 4 * s, a + 5 * s); + int b1 = this.medianOfThree(array, a + 6 * s, a + 7 * s, a + 8 * s); return this.medianOfThree(array, a1, m1, b1); } + private int medianOfThreeNinthers(int[] array, int a, int b) { - int s = (b-a)/3; + int s = (b - a) / 3; - int a1 = this.ninther(array, a, a+s); - int m1 = this.ninther(array, a+s, a+2*s); - int b1 = this.ninther(array, a+2*s, b); + int a1 = this.ninther(array, a, a + s); + int m1 = this.ninther(array, a + s, a + 2 * s); + int b1 = this.ninther(array, a + 2 * s, b); return this.medianOfThree(array, a1, m1, b1); } private void shiftBW(int[] array, int a, int m, int b) { - while(m > a) Writes.swap(array, --b, --m, 1, true, false); + while (m > a) + Writes.swap(array, --b, --m, 1, true, false); } private int leftBlockSearch(int[] array, int a, int b, int val) { - int s = G+1; + int s = G + 1; - while(a < b) { - int m = a+(((b-a)/s)/2)*s; + while (a < b) { + int m = a + (((b - a) / s) / 2) * s; Highlights.markArray(3, m); Delays.sleep(0.25); - if(Reads.compareValues(val, array[m]) <= 0) + if (Reads.compareValues(val, array[m]) <= 0) b = m; else - a = m+s; + a = m + s; } Highlights.clearMark(3); return a; } + private int rightBlockSearch(int[] array, int a, int b, int val) { - int s = G+1; + int s = G + 1; - while(a < b) { - int m = a+(((b-a)/s)/2)*s; + while (a < b) { + int m = a + (((b - a) / s) / 2) * s; Highlights.markArray(3, m); Delays.sleep(0.25); - if(Reads.compareValues(val, array[m]) < 0) + if (Reads.compareValues(val, array[m]) < 0) b = m; else - a = m+s; + a = m + s; } Highlights.clearMark(3); return a; } - private int rightBinSearch(int[] array, int a, int b, int val, boolean bw) { + private int rightBinSearch(int[] array, int a, int b, int val, boolean bw) { int cmp = bw ? 1 : -1; - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; Highlights.markArray(3, m); Delays.sleep(0.25); - if(Reads.compareValues(val, array[m]) == cmp) + if (Reads.compareValues(val, array[m]) == cmp) b = m; else - a = m+1; + a = m + 1; } Highlights.clearMark(3); @@ -149,35 +143,38 @@ private int rightBinSearch(int[] array, int a, int b, int val, boolean bw) { private void insertTo(int[] array, int tmp, int a, int b) { Highlights.clearMark(2); - while(a > b) Writes.write(array, a, array[--a], 0.5, true, false); + while (a > b) + Writes.write(array, a, array[--a], 0.5, true, false); Writes.write(array, b, tmp, 0.5, true, false); } private void binaryInsertion(int[] array, int a, int b) { - for(int i = a+1; i < b; i++) + for (int i = a + 1; i < b; i++) this.insertTo(array, array[i], i, this.rightBinSearch(array, a, i, array[i], false)); - } + } private void kWayMerge(int[] array, int[] heap, int[] pa, int s, int b, int p, int size) { - if(size < 2) { - if(size == 1) while(pa[0] < b) Writes.swap(array, p++, pa[0]++, 1, true, false); + if (size < 2) { + if (size == 1) + while (pa[0] < b) + Writes.swap(array, p++, pa[0]++, 1, true, false); return; } int a = pa[0]; - for(int i = 0; i < size; i++) + for (int i = 0; i < size; i++) Writes.write(heap, i, i, 0, false, true); - for(int i = (size-1)/2; i >= 0; i--) + for (int i = (size - 1) / 2; i >= 0; i--) this.siftDown(array, heap, pa, heap[i], i, size); - while(size > 0) { + while (size > 0) { int min = heap[0]; Writes.swap(array, p++, pa[min], 0, true, false); - Writes.write(pa, min, pa[min]+1, 1, false, true); + Writes.write(pa, min, pa[min] + 1, 1, false, true); - if(pa[min] == Math.min(a+(min+1)*s, b)) + if (pa[min] == Math.min(a + (min + 1) * s, b)) this.siftDown(array, heap, pa, heap[--size], 0, size); else this.siftDown(array, heap, pa, heap[0], 0, size); @@ -185,24 +182,26 @@ private void kWayMerge(int[] array, int[] heap, int[] pa, int s, int b, int p, i } private void retrieve(int[] array, int i, int p, int pEnd, int bsv, boolean bw) { - int j = i-1, m; + int j = i - 1, m; - for(int k = pEnd-(G+1); k > p+G;) { - m = this.rightBinSearch(array, k-G, k, bsv, bw)-1; - k -= G+1; + for (int k = pEnd - (G + 1); k > p + G;) { + m = this.rightBinSearch(array, k - G, k, bsv, bw) - 1; + k -= G + 1; - while(m >= k) Writes.swap(array, j--, m--, 1, true, false); + while (m >= k) + Writes.swap(array, j--, m--, 1, true, false); } - m = this.rightBinSearch(array, p, p+G, bsv, bw)-1; - while(m >= p) Writes.swap(array, j--, m--, 1, true, false); + m = this.rightBinSearch(array, p, p + G, bsv, bw) - 1; + while (m >= p) + Writes.swap(array, j--, m--, 1, true, false); } - //buffer length is at least sortLength*(G+1)-1 + // buffer length is at least sortLength*(G+1)-1 private void librarySort(int[] array, int a, int b, int p, int bsv, boolean bw) { - int len = b-a; + int len = b - a; - if(len < 32) { + if (len < 32) { this.binaryInsertion(array, a, b); return; } @@ -210,158 +209,173 @@ private void librarySort(int[] array, int a, int b, int p, int bsv, boolean bw) Random rng = new Random(); int s = len; - while(s >= 32) s = (s-1)/R + 1; + while (s >= 32) + s = (s - 1) / R + 1; - int i = a+s, j = a+R*s, pEnd = p + (s+1)*(G+1)+G; + int i = a + s, j = a + R * s, pEnd = p + (s + 1) * (G + 1) + G; this.binaryInsertion(array, a, i); - for(int k = 0; k < s; k++) //scatter elements to make G sized gaps b/w them - Writes.swap(array, a+k, p + k*(G+1)+G, 1, true, false); + for (int k = 0; k < s; k++) // scatter elements to make G sized gaps b/w them + Writes.swap(array, a + k, p + k * (G + 1) + G, 1, true, false); - while(i < b) { - if(i == j) { //rebalancing (retrieve from buffer & rescatter) + while (i < b) { + if (i == j) { // rebalancing (retrieve from buffer & rescatter) this.retrieve(array, i, p, pEnd, bsv, bw); - s = i-a; - pEnd = p + (s+1)*(G+1)+G; - j = a+(j-a)*R; + s = i - a; + pEnd = p + (s + 1) * (G + 1) + G; + j = a + (j - a) * R; - for(int k = 0; k < s; k++) - Writes.swap(array, a+k, p + k*(G+1)+G, 1, true, false); + for (int k = 0; k < s; k++) + Writes.swap(array, a + k, p + k * (G + 1) + G, 1, true, false); } - int bLoc = this.leftBlockSearch(array, p+G, pEnd-(G+1), array[i]); //search gap location + int bLoc = this.leftBlockSearch(array, p + G, pEnd - (G + 1), array[i]); // search gap location - if(Reads.compareValues(array[i], array[bLoc]) == 0) { //handle equal values to prevent worst case O(n^2) - int eqEnd = this.rightBlockSearch(array, bLoc+(G+1), pEnd-(G+1), array[i]); //find the endpoint of the gaps with equal head element - bLoc += rng.nextInt((eqEnd-bLoc)/(G+1))*(G+1); //choose a random gap from the range of gaps + if (Reads.compareValues(array[i], array[bLoc]) == 0) { // handle equal values to prevent worst case O(n^2) + int eqEnd = this.rightBlockSearch(array, bLoc + (G + 1), pEnd - (G + 1), array[i]); // find the endpoint + // of the gaps with + // equal head + // element + bLoc += rng.nextInt((eqEnd - bLoc) / (G + 1)) * (G + 1); // choose a random gap from the range of gaps } - int loc = this.rightBinSearch(array, bLoc-G, bLoc, bsv, bw); //search next empty space in gap + int loc = this.rightBinSearch(array, bLoc - G, bLoc, bsv, bw); // search next empty space in gap - if(loc == bLoc) { //if there is no empty space filled elements in gap are split - do bLoc += G+1; - while(bLoc < pEnd && this.rightBinSearch(array, bLoc-G, bLoc, bsv, bw) == bLoc); + if (loc == bLoc) { // if there is no empty space filled elements in gap are split + do + bLoc += G + 1; + while (bLoc < pEnd && this.rightBinSearch(array, bLoc - G, bLoc, bsv, bw) == bLoc); - if(bLoc == pEnd) { //rebalancing + if (bLoc == pEnd) { // rebalancing this.retrieve(array, i, p, pEnd, bsv, bw); - s = i-a; - pEnd = p + (s+1)*(G+1)+G; - j = a+(j-a)*R; - - for(int k = 0; k < s; k++) - Writes.swap(array, a+k, p + k*(G+1)+G, 1, true, false); - } - else { //if a gap is full find next non full gap to the right & shift the space down - int rotP = this.rightBinSearch(array, bLoc-G, bLoc, bsv, bw); - int rotS = bLoc - Math.max(rotP, bLoc - G/2); //for odd G whether its floor or ceil(G/2) doesnt matter - this.shiftBW(array, loc-rotS, bLoc-rotS, bLoc); + s = i - a; + pEnd = p + (s + 1) * (G + 1) + G; + j = a + (j - a) * R; + + for (int k = 0; k < s; k++) + Writes.swap(array, a + k, p + k * (G + 1) + G, 1, true, false); + } else { // if a gap is full find next non full gap to the right & shift the space down + int rotP = this.rightBinSearch(array, bLoc - G, bLoc, bsv, bw); + int rotS = bLoc - Math.max(rotP, bLoc - G / 2); // for odd G whether its floor or ceil(G/2) doesnt + // matter + this.shiftBW(array, loc - rotS, bLoc - rotS, bLoc); } - } - else { + } else { int t = array[i]; Writes.write(array, i++, array[loc], 1, true, false); - this.insertTo(array, t, loc, this.rightBinSearch(array, bLoc-G, loc, t, false)); + this.insertTo(array, t, loc, this.rightBinSearch(array, bLoc - G, loc, t, false)); } } this.retrieve(array, b, p, pEnd, bsv, bw); } - @Override - public void runSort(int[] array, int length, int bucketCount) { //to benefit from worst case O(n log n) comparisons & O(n) moves - //we would normally shuffle the array before sorting - //but for the sake of demonstration this step is omitted - int[] pa = new int[G+2]; - int[] heap = new int[G+2]; + @Override + public void runSort(int[] array, int length, int bucketCount) { // to benefit from worst case O(n log n) comparisons + // & O(n) moves + // we would normally shuffle the array before + // sorting + // but for the sake of demonstration this step is + // omitted + int[] pa = new int[G + 2]; + int[] heap = new int[G + 2]; int alloc = pa.length + heap.length; Writes.changeAllocAmount(alloc); int a = 0, b = length; - while(b-a >= 32) { + while (b - a >= 32) { int piv = array[this.medianOfThreeNinthers(array, a, b)]; - //partition -> [a][E > piv][i][E == piv][j][E < piv][b] - int i1 = a, i = a-1, j = b, j1 = b; + // partition -> [a][E > piv][i][E == piv][j][E < piv][b] + int i1 = a, i = a - 1, j = b, j1 = b; - for(;;) { - while(++i < j) { + for (;;) { + while (++i < j) { int cmp = Reads.compareIndexValue(array, i, piv, 0.5, true); - if(cmp == 0) Writes.swap(array, i1++, i, 1, true, false); - else if(cmp < 0) break; + if (cmp == 0) + Writes.swap(array, i1++, i, 1, true, false); + else if (cmp < 0) + break; } Highlights.clearMark(2); - while(--j > i) { + while (--j > i) { int cmp = Reads.compareIndexValue(array, j, piv, 0.5, true); - if(cmp == 0) Writes.swap(array, --j1, j, 1, true, false); - else if(cmp > 0) break; + if (cmp == 0) + Writes.swap(array, --j1, j, 1, true, false); + else if (cmp > 0) + break; } Highlights.clearMark(2); - if(i < j) { + if (i < j) { Writes.swap(array, i, j, 1, true, false); Highlights.clearMark(2); - } - else { - if(i1 == b) return; - else if(j < i) j++; + } else { + if (i1 == b) + return; + else if (j < i) + j++; - while(i1 > a) Writes.swap(array, --i, --i1, 1, true, false); - while(j1 < b) Writes.swap(array, j++, j1++, 1, true, false); + while (i1 > a) + Writes.swap(array, --i, --i1, 1, true, false); + while (j1 < b) + Writes.swap(array, j++, j1++, 1, true, false); break; } } - int left = i-a, right = b-j, m, kCnt = 0; + int left = i - a, right = b - j, m, kCnt = 0; - if(left <= right) { //sort the smaller partition using larger partition as space - m = b-left; - left = Math.max((right+1)/(G+1), 16); + if (left <= right) { // sort the smaller partition using larger partition as space + m = b - left; + left = Math.max((right + 1) / (G + 1), 16); - for(int k = a; k < i; k += left) { - this.librarySort(array, k, Math.min(k+left, i), j, piv, true); + for (int k = a; k < i; k += left) { + this.librarySort(array, k, Math.min(k + left, i), j, piv, true); Writes.write(pa, kCnt++, k, 0, false, true); } this.kWayMerge(array, heap, pa, left, i, m, kCnt); - //swap items eq to pivot next to sorted area - //eq items zone: [i][E == piv][j][E < piv][m][sorted area] - if(j-i < m-j) { - while(i < j) Writes.swap(array, i++, --m, 1, true, false); + // swap items eq to pivot next to sorted area + // eq items zone: [i][E == piv][j][E < piv][m][sorted area] + if (j - i < m - j) { + while (i < j) + Writes.swap(array, i++, --m, 1, true, false); b = m; - } - else { - while(m > j) Writes.swap(array, i++, --m, 1, true, false); + } else { + while (m > j) + Writes.swap(array, i++, --m, 1, true, false); b = i; } - } - else { - m = a+right; - right = Math.max((left+1)/(G+1), 16); + } else { + m = a + right; + right = Math.max((left + 1) / (G + 1), 16); - for(int k = j; k < b; k += right) { - this.librarySort(array, k, Math.min(k+right, b), a, piv, false); + for (int k = j; k < b; k += right) { + this.librarySort(array, k, Math.min(k + right, b), a, piv, false); Writes.write(pa, kCnt++, k, 0, false, true); } this.kWayMerge(array, heap, pa, right, b, a, kCnt); - //eq items zone: [sorted area][m][E > piv][i][E == piv][j] - if(i-m < j-i) { - while(m < i) Writes.swap(array, m++, --j, 1, true, false); + // eq items zone: [sorted area][m][E > piv][i][E == piv][j] + if (i - m < j - i) { + while (m < i) + Writes.swap(array, m++, --j, 1, true, false); a = j; - } - else { - while(j > i) Writes.swap(array, m++, --j, 1, true, false); + } else { + while (j > i) + Writes.swap(array, m++, --j, 1, true, false); a = m; } } } this.binaryInsertion(array, a, b); Writes.changeAllocAmount(-alloc); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/FluxSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/FluxSort.java index 8d4ec864..3a33efa5 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/FluxSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/FluxSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.QuadSorting; /* @@ -33,21 +34,11 @@ a copy of this software and associated documentation files (the /* fluxsort 1.1.3.3 */ - +@SortMeta(name = "Flux") public final class FluxSort extends QuadSorting { - public FluxSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Flux"); - this.setRunAllSortsName("Flux Sort"); - this.setRunSortName("Fluxsort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public FluxSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private final int FLUX_OUT = 24; @@ -58,17 +49,19 @@ private boolean fluxAnalyze(int[] array, int nmemb) { pta = 0; cnt = nmemb; - while(--cnt > 0) - if(Reads.compareIndices(array, pta, ++pta, 0.5, true) > 0) balance++; + while (--cnt > 0) + if (Reads.compareIndices(array, pta, ++pta, 0.5, true) > 0) + balance++; - if(balance == 0) return false; + if (balance == 0) + return false; - if(balance == nmemb-1) { - Writes.reversal(array, 0, nmemb-1, 1, true, false); + if (balance == nmemb - 1) { + Writes.reversal(array, 0, nmemb - 1, 1, true, false); return false; } - if(balance <= nmemb / 6 || balance >= nmemb / 6 * 5) { + if (balance <= nmemb / 6 || balance >= nmemb / 6 * 5) { this.quadSort(array, 0, nmemb); return false; } @@ -80,25 +73,44 @@ private int medianOfFive(int[] array, int v0, int v1, int v2, int v3, int v4) { int[] t = new int[4]; int val; - val = (Reads.compareIndices(array, v0, v1, 1, true)+1)/2; t[0] = val; t[1] = val^1; - val = (Reads.compareIndices(array, v0, v2, 1, true)+1)/2; t[0] += val; t[2] = val^1; - val = (Reads.compareIndices(array, v0, v3, 1, true)+1)/2; t[0] += val; t[3] = val^1; - val = (Reads.compareIndices(array, v0, v4, 1, true)+1)/2; t[0] += val; - - if (t[0] == 2) return v0; - - val = (Reads.compareIndices(array, v1, v2, 1, true)+1)/2; t[1] += val; t[2] += val^1; - val = (Reads.compareIndices(array, v1, v3, 1, true)+1)/2; t[1] += val; t[3] += val^1; - val = (Reads.compareIndices(array, v1, v4, 1, true)+1)/2; t[1] += val; - - if (t[1] == 2) return v1; - - val = (Reads.compareIndices(array, v2, v3, 1, true)+1)/2; t[2] += val; t[3] += val^1; - val = (Reads.compareIndices(array, v2, v4, 1, true)+1)/2; t[2] += val; - - if (t[2] == 2) return v2; - - val = (Reads.compareIndices(array, v3, v4, 1, true)+1)/2; t[3] += val; + val = (Reads.compareIndices(array, v0, v1, 1, true) + 1) / 2; + t[0] = val; + t[1] = val ^ 1; + val = (Reads.compareIndices(array, v0, v2, 1, true) + 1) / 2; + t[0] += val; + t[2] = val ^ 1; + val = (Reads.compareIndices(array, v0, v3, 1, true) + 1) / 2; + t[0] += val; + t[3] = val ^ 1; + val = (Reads.compareIndices(array, v0, v4, 1, true) + 1) / 2; + t[0] += val; + + if (t[0] == 2) + return v0; + + val = (Reads.compareIndices(array, v1, v2, 1, true) + 1) / 2; + t[1] += val; + t[2] += val ^ 1; + val = (Reads.compareIndices(array, v1, v3, 1, true) + 1) / 2; + t[1] += val; + t[3] += val ^ 1; + val = (Reads.compareIndices(array, v1, v4, 1, true) + 1) / 2; + t[1] += val; + + if (t[1] == 2) + return v1; + + val = (Reads.compareIndices(array, v2, v3, 1, true) + 1) / 2; + t[2] += val; + t[3] += val ^ 1; + val = (Reads.compareIndices(array, v2, v4, 1, true) + 1) / 2; + t[2] += val; + + if (t[2] == 2) + return v2; + + val = (Reads.compareIndices(array, v3, v4, 1, true) + 1) / 2; + t[3] += val; return t[3] == 2 ? v3 : v4; } @@ -107,34 +119,39 @@ private int medianOfThree(int[] array, int v0, int v1, int v2) { int[] t = new int[2]; int val; - val = (Reads.compareIndices(array, v0, v1, 1, true)+1)/2; t[0] = val; t[1] = val^1; - val = (Reads.compareIndices(array, v0, v2, 1, true)+1)/2; t[0] += val; + val = (Reads.compareIndices(array, v0, v1, 1, true) + 1) / 2; + t[0] = val; + t[1] = val ^ 1; + val = (Reads.compareIndices(array, v0, v2, 1, true) + 1) / 2; + t[0] += val; - if (t[0] == 1) return v0; + if (t[0] == 1) + return v0; - val = (Reads.compareIndices(array, v1, v2, 1, true)+1)/2; t[1] += val; + val = (Reads.compareIndices(array, v1, v2, 1, true) + 1) / 2; + t[1] += val; return t[1] == 1 ? v1 : v2; } private int medianOfFifteen(int[] array, int ptx, int nmemb) { - int v0, v1, v2, v3, v4, div = nmemb/16; + int v0, v1, v2, v3, v4, div = nmemb / 16; - v0 = this.medianOfThree(array, ptx+div*2, ptx+div*1, ptx+div*3); - v1 = this.medianOfThree(array, ptx+div*5, ptx+div*4, ptx+div*6); - v2 = this.medianOfThree(array, ptx+div*8, ptx+div*7, ptx+div*9); - v3 = this.medianOfThree(array, ptx+div*11, ptx+div*10, ptx+div*12); - v4 = this.medianOfThree(array, ptx+div*14, ptx+div*13, ptx+div*15); + v0 = this.medianOfThree(array, ptx + div * 2, ptx + div * 1, ptx + div * 3); + v1 = this.medianOfThree(array, ptx + div * 5, ptx + div * 4, ptx + div * 6); + v2 = this.medianOfThree(array, ptx + div * 8, ptx + div * 7, ptx + div * 9); + v3 = this.medianOfThree(array, ptx + div * 11, ptx + div * 10, ptx + div * 12); + v4 = this.medianOfThree(array, ptx + div * 14, ptx + div * 13, ptx + div * 15); return this.medianOfFive(array, v2, v0, v1, v3, v4); } private int medianOfNine(int[] array, int ptx, int nmemb) { - int v0, v1, v2, div = nmemb/16; + int v0, v1, v2, div = nmemb / 16; - v0 = this.medianOfThree(array, ptx+div*2, ptx+div*1, ptx+div*4); - v1 = this.medianOfThree(array, ptx+div*8, ptx+div*6, ptx+div*10); - v2 = this.medianOfThree(array, ptx+div*14, ptx+div*12, ptx+div*15); + v0 = this.medianOfThree(array, ptx + div * 2, ptx + div * 1, ptx + div * 4); + v1 = this.medianOfThree(array, ptx + div * 8, ptx + div * 6, ptx + div * 10); + v2 = this.medianOfThree(array, ptx + div * 14, ptx + div * 12, ptx + div * 15); return this.medianOfThree(array, v0, v1, v2); } @@ -148,45 +165,46 @@ private void fluxPartition(int[] array, int[] swap, int[] main, int start, int n piv = main[nmemb > 1024 ? this.medianOfFifteen(main, ptx, nmemb) : this.medianOfNine(main, ptx, nmemb)]; - pte = ptx+nmemb; + pte = ptx + nmemb; pta = start; pts = 0; - while(ptx < pte) { + while (ptx < pte) { Highlights.markArray(3, ptx); - val = (Reads.compareValues(main[ptx], piv)+1)/2; + val = (Reads.compareValues(main[ptx], piv) + 1) / 2; Delays.sleep(0.25); - Writes.write(array, pta, main[ptx], 0.25, true, false); pta += val^1; + Writes.write(array, pta, main[ptx], 0.25, true, false); + pta += val ^ 1; Highlights.markArray(2, pts); - Writes.write(swap, pts, main[ptx], 0.25, false, true); pts += val; + Writes.write(swap, pts, main[ptx], 0.25, false, true); + pts += val; ptx++; } Highlights.clearMark(3); sSize = pts; - aSize = nmemb-sSize; + aSize = nmemb - sSize; - if(aSize <= sSize/16 || sSize <= FLUX_OUT) { + if (aSize <= sSize / 16 || sSize <= FLUX_OUT) { Writes.arraycopy(swap, 0, array, pta, sSize, 0.5, true, false); this.quadSortSwap(array, swap, pta, sSize); - } - else + } else this.fluxPartition(array, swap, swap, pta, sSize); - if(sSize <= aSize/16 || aSize <= FLUX_OUT) + if (sSize <= aSize / 16 || aSize <= FLUX_OUT) this.quadSortSwap(array, swap, start, aSize); else this.fluxPartition(array, swap, array, start, aSize); } public void fluxsort(int[] array, int nmemb) { - if(nmemb < 32) + if (nmemb < 32) this.quadSort(array, 0, nmemb); - else if(this.fluxAnalyze(array, nmemb)) { + else if (this.fluxAnalyze(array, nmemb)) { int[] swap = Writes.createExternalArray(nmemb); this.fluxPartition(array, swap, array, 0, nmemb); @@ -195,8 +213,8 @@ else if(this.fluxAnalyze(array, nmemb)) { } } - @Override - public void runSort(int[] array, int nmemb, int bucketCount) { + @Override + public void runSort(int[] array, int nmemb, int bucketCount) { this.fluxsort(array, nmemb); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/GrailSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/GrailSort.java index aa59b07f..3f27cd77 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/GrailSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/GrailSort.java @@ -48,12 +48,7 @@ this software and associated documentation files (the "Software"), to deal in /* */ /*********************************************************/ -@SortMeta( - name = "Grail", - category = "Hybrid Sorts", - question = "Enter external buffer type (0 = in-place, 1 = static, 2 = dynamic):", - defaultAnswer = 0 -) +@SortMeta(name = "Grail", question = "Enter external buffer type (0 = in-place, 1 = static, 2 = dynamic):", defaultAnswer = 0) public final class GrailSort extends GrailSorting { public GrailSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -69,23 +64,24 @@ public void customSort(int[] array, int start, int end) { @Override public void runSort(int[] array, int length, int bucketCount) { - switch(bucketCount) { - case 1: - int[] ExtBuf = Writes.createExternalArray(this.getStaticBuffer()); - this.grailCommonSort(array, 0, length, ExtBuf, 0, this.getStaticBuffer()); - Writes.deleteExternalArray(ExtBuf); - break; + switch (bucketCount) { + case 1: + int[] ExtBuf = Writes.createExternalArray(this.getStaticBuffer()); + this.grailCommonSort(array, 0, length, ExtBuf, 0, this.getStaticBuffer()); + Writes.deleteExternalArray(ExtBuf); + break; - case 2: - int tempLen = 1; - while(tempLen * tempLen < length) tempLen *= 2; - int[] DynExtBuf = Writes.createExternalArray(tempLen); - this.grailCommonSort(array, 0, length, DynExtBuf, 0, tempLen); - Writes.deleteExternalArray(DynExtBuf); - break; + case 2: + int tempLen = 1; + while (tempLen * tempLen < length) + tempLen *= 2; + int[] DynExtBuf = Writes.createExternalArray(tempLen); + this.grailCommonSort(array, 0, length, DynExtBuf, 0, tempLen); + Writes.deleteExternalArray(DynExtBuf); + break; - default: - this.grailCommonSort(array, 0, length, null, 0, 0); - } + default: + this.grailCommonSort(array, 0, length, null, 0, 0); + } } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/HybridCombSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/HybridCombSort.java index ad61f878..8c59dce4 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/HybridCombSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/HybridCombSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.CombSorting; /* @@ -27,24 +28,14 @@ this software and associated documentation files (the "Software"), to deal in CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ - +@SortMeta(name = "Hybrid Comb", question = "Enter shrink factor (input/100):", defaultAnswer = 130) public final class HybridCombSort extends CombSorting { public HybridCombSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Hybrid Comb"); - this.setRunAllSortsName("Hybrid Comb Sort"); - this.setRunSortName("Hybrid Combsort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override public void runSort(int[] array, int currentLength, int bucketCount) { - this.combSort(array, currentLength, 1.3, true); + this.combSort(array, currentLength, bucketCount / 100d, true); } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/ImprovedBlockSelectionSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/ImprovedBlockSelectionSort.java index 4ec1c4fd..311c2ed0 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/ImprovedBlockSelectionSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/ImprovedBlockSelectionSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,87 +29,79 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Improved Block Selection Merge") public final class ImprovedBlockSelectionSort extends Sort { - public ImprovedBlockSelectionSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Improved Block Selection Merge"); - this.setRunAllSortsName("Improved Block Selection Merge Sort"); - this.setRunSortName("Improved Block Selection Merge Sort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - public static int sqrt(int n) { - int i = 1; - for(; i*i < n; i*=2); - return i; - } - - private void multiSwap(int[] array, int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(array, a+i, b+i, 1, true, false); + public ImprovedBlockSelectionSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); } - private void rotate(int[] array, int a, int m, int b) { - int l = m-a, r = b-m; + public static int sqrt(int n) { + int i = 1; + for (; i * i < n; i *= 2) + ; + return i; + } + + private void multiSwap(int[] array, int a, int b, int len) { + for (int i = 0; i < len; i++) + Writes.swap(array, a + i, b + i, 1, true, false); + } - while(l > 0 && r > 0) { - if(r < l) { - this.multiSwap(array, m-r, m, r); + private void rotate(int[] array, int a, int m, int b) { + int l = m - a, r = b - m; + + while (l > 0 && r > 0) { + if (r < l) { + this.multiSwap(array, m - r, m, r); b -= r; m -= r; l -= r; - } - else { + } else { this.multiSwap(array, a, m, l); a += l; m += l; r -= l; - } - } - } + } + } + } private int inPlaceMerge(int[] array, int a, int m, int b) { int i = a, j = m, k; - while(i < j && j < b) { - if(Reads.compareValues(array[i], array[j]) > 0) { + while (i < j && j < b) { + if (Reads.compareValues(array[i], array[j]) > 0) { k = j; - do k++; - while(k < b && Reads.compareIndices(array, i, k, 0, false) > 0); + do + k++; + while (k < b && Reads.compareIndices(array, i, k, 0, false) > 0); this.rotate(array, i, j, k); - i += k-j; + i += k - j; j = k; - } - else i++; + } else + i++; } return i; } private void inPlaceMergeBW(int[] array, int a, int m, int b) { - int i = m-1, j = b-1, k; + int i = m - 1, j = b - 1, k; - while(j > i && i >= a){ - if(Reads.compareValues(array[i], array[j]) > 0) { + while (j > i && i >= a) { + if (Reads.compareValues(array[i], array[j]) > 0) { k = i; - do k--; - while(k >= a && Reads.compareIndices(array, k, j, 0, false) > 0); + do + k--; + while (k >= a && Reads.compareIndices(array, k, j, 0, false) > 0); - this.rotate(array, k+1, i+1, j+1); + this.rotate(array, k + 1, i + 1, j + 1); - j -= i-k; + j -= i - k; i = k; - } - else j--; + } else + j--; } } @@ -116,10 +109,10 @@ private int selectRange(int[] array, int a, int b, int bLen) { int min = a; a += bLen; - while(a < b) { + while (a < b) { int comp = Reads.compareIndices(array, a, min, 0, false); - if(comp == -1 || (comp == 0 && Reads.compareIndices(array, a+bLen-1, min+bLen-1, 0, false) == -1)) + if (comp == -1 || (comp == 0 && Reads.compareIndices(array, a + bLen - 1, min + bLen - 1, 0, false) == -1)) min = a; a += bLen; @@ -127,58 +120,63 @@ private int selectRange(int[] array, int a, int b, int bLen) { return min; } - private void blockSelect(int[] array, int a, int m, int b, int bLen) { + private void blockSelect(int[] array, int a, int m, int b, int bLen) { int k = a, j = m; - while(k < m && Reads.compareIndices(array, k, m, 0.5, true) <= 0) k += bLen; - if(k == m) return; + while (k < m && Reads.compareIndices(array, k, m, 0.5, true) <= 0) + k += bLen; + if (k == m) + return; int i = m; this.multiSwap(array, k, j, bLen); k += bLen; j += bLen; - while(k < j && j < b) { - if(Reads.compareIndices(array, i, j, 0.5, true) <= 0) { - if(k != i) this.multiSwap(array, k, i, bLen); + while (k < j && j < b) { + if (Reads.compareIndices(array, i, j, 0.5, true) <= 0) { + if (k != i) + this.multiSwap(array, k, i, bLen); k += bLen; i = this.selectRange(array, Math.max(m, k), j, bLen); - } - else { - if(i == k) i = j; - if(k != j) this.multiSwap(array, k, j, bLen); + } else { + if (i == k) + i = j; + if (k != j) + this.multiSwap(array, k, j, bLen); k += bLen; j += bLen; } } - //if(k != m) - while(k < j) { - i = this.selectRange(array, k, b, bLen); - if(k != i) this.multiSwap(array, k, i, bLen); - k += bLen; - } - } + // if(k != m) + while (k < j) { + i = this.selectRange(array, k, b, bLen); + if (k != i) + this.multiSwap(array, k, i, bLen); + k += bLen; + } + } - @Override - public void runSort(int[] array, int length, int bucketCount) { - for(int i, j = 1; j < length; j *= 2) { + @Override + public void runSort(int[] array, int length, int bucketCount) { + for (int i, j = 1; j < length; j *= 2) { int bLen = sqrt(j), n = j, - b = length-length%bLen; + b = length - length % bLen; - while(n > 16) { - for(i = 0; i+j < b; i += 2*j) - for(int k = i; k+n < Math.min(i+2*j, b); k += n) - this.blockSelect(array, k, k+n, Math.min(k+2*n, b), bLen); + while (n > 16) { + for (i = 0; i + j < b; i += 2 * j) + for (int k = i; k + n < Math.min(i + 2 * j, b); k += n) + this.blockSelect(array, k, k + n, Math.min(k + 2 * n, b), bLen); n = bLen; bLen = sqrt(bLen); } - for(i = 0; i+j < b; i += 2*j) - for(int k = i, f = i; k+n < Math.min(i+2*j, b); k += n) - f = this.inPlaceMerge(array, f, k+n, Math.min(k+2*n, b)); + for (i = 0; i + j < b; i += 2 * j) + for (int k = i, f = i; k + n < Math.min(i + 2 * j, b); k += n) + f = this.inPlaceMerge(array, f, k + n, Math.min(k + 2 * n, b)); - this.inPlaceMergeBW(array, length-length%(2*j), b, length); - } - } + this.inPlaceMergeBW(array, length - length % (2 * j), b, length); + } + } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/IntroCircleSortIterative.java b/src/main/java/io/github/arrayv/sorts/hybrid/IntroCircleSortIterative.java index d179d484..c3974c5f 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/IntroCircleSortIterative.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/IntroCircleSortIterative.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.BinaryInsertionSort; import io.github.arrayv.sorts.templates.IterativeCircleSorting; @@ -15,35 +16,26 @@ Free Documentation License". * */ - +@SortMeta(listName = "Intro Circle (Iterative)", runName = "Iterative Introspective Circle Sort") public final class IntroCircleSortIterative extends IterativeCircleSorting { public IntroCircleSortIterative(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Intro Circle (Iterative)"); - this.setRunAllSortsName("Iterative Introspective Circle Sort"); - this.setRunSortName("Iterative Introspective Circlesort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override public void runSort(int[] array, int length, int bucketCount) { - this.end = length; - int threshold = 0, n = 1; - for(; n < length; n*=2, threshold++); + this.end = length; + int threshold = 0, n = 1; + for (; n < length; n *= 2, threshold++) + ; - threshold /= 2; + threshold /= 2; int iterations = 0; do { iterations++; - if(iterations >= threshold) { + if (iterations >= threshold) { BinaryInsertionSort binaryInserter = new BinaryInsertionSort(this.arrayVisualizer); binaryInserter.customBinaryInsert(array, 0, length, 0.1); break; diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/IntroCircleSortRecursive.java b/src/main/java/io/github/arrayv/sorts/hybrid/IntroCircleSortRecursive.java index 1bbfe44c..1520f21e 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/IntroCircleSortRecursive.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/IntroCircleSortRecursive.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.BinaryInsertionSort; import io.github.arrayv.sorts.templates.CircleSorting; @@ -15,35 +16,26 @@ Free Documentation License". * */ - +@SortMeta(listName = "Intro Circle (Recursive)", runName = "Recursive Introspective Circle Sort") public final class IntroCircleSortRecursive extends CircleSorting { public IntroCircleSortRecursive(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Intro Circle (Recursive)"); - this.setRunAllSortsName("Recursive Introspective Circle Sort"); - this.setRunSortName("Introspective Circlesort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override public void runSort(int[] array, int length, int bucketCount) { - this.end = length; - int threshold = 0, n = 1; - for(; n < length; n*=2, threshold++); + this.end = length; + int threshold = 0, n = 1; + for (; n < length; n *= 2, threshold++) + ; - threshold /= 2; + threshold /= 2; int iterations = 0; do { iterations++; - if(iterations >= threshold) { + if (iterations >= threshold) { BinaryInsertionSort binaryInserter = new BinaryInsertionSort(this.arrayVisualizer); binaryInserter.customBinaryInsert(array, 0, length, 0.1); break; diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/IntroSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/IntroSort.java index 8e808b09..8f644fdc 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/IntroSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/IntroSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.InsertionSort; import io.github.arrayv.sorts.select.MaxHeapSort; import io.github.arrayv.sorts.templates.Sort; @@ -9,7 +10,7 @@ // http://ralphunden.net/content/tutorials/a-guide-to-introsort/?q=a-guide-to-introsort // Modifications: Bernhard Pfahringer // changes include: local insertion sort, no global array - +@SortMeta(name = "Introspective") public final class IntroSort extends Sort { private MaxHeapSort heapSorter; @@ -18,17 +19,6 @@ public final class IntroSort extends Sort { public IntroSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Intro"); - //this.setRunAllID("Introspective Sort (std::sort)"); - this.setRunAllSortsName("Introspective Sort"); - this.setRunSortName("Introsort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private static int floorLogBaseTwo(int a) { @@ -36,26 +26,23 @@ private static int floorLogBaseTwo(int a) { } // Swaps the median of arr[left], arr[mid], and arr[right] to index left. - // taken from gcc source code found here: https://gcc.gnu.org/onlinedocs/gcc-4.7.2/libstdc++/api/a01462_source.html + // taken from gcc source code found here: + // https://gcc.gnu.org/onlinedocs/gcc-4.7.2/libstdc++/api/a01462_source.html @SuppressWarnings("unused") private int gccmedianof3(int[] arr, int left, int mid, int right) { if (Reads.compareValues(arr[left], arr[mid]) < 0) { if (Reads.compareValues(arr[mid], arr[right]) < 0) { Writes.swap(arr, left, mid, 1, true, false); - } - else if (Reads.compareValues(arr[left], arr[right]) < 0) { + } else if (Reads.compareValues(arr[left], arr[right]) < 0) { Writes.swap(arr, left, right, 1, true, false); } - } - else if (Reads.compareValues(arr[left], arr[right]) < 0) { + } else if (Reads.compareValues(arr[left], arr[right]) < 0) { middle = left; Highlights.markArray(3, left); return arr[left]; - } - else if (Reads.compareValues(arr[mid], arr[right]) < 0) { + } else if (Reads.compareValues(arr[mid], arr[right]) < 0) { Writes.swap(arr, left, right, 1, true, false); - } - else { + } else { Writes.swap(arr, left, mid, 1, true, false); } middle = left; @@ -64,13 +51,13 @@ else if (Reads.compareValues(arr[mid], arr[right]) < 0) { } private int medianof3(int[] arr, int left, int mid, int right) { - if(Reads.compareValues(arr[right], arr[left]) == -1) { + if (Reads.compareValues(arr[right], arr[left]) == -1) { Writes.swap(arr, left, right, 1, true, false); } - if(Reads.compareValues(arr[mid], arr[left]) == -1) { + if (Reads.compareValues(arr[mid], arr[left]) == -1) { Writes.swap(arr, mid, left, 1, true, false); } - if(Reads.compareValues(arr[right], arr[mid]) == -1) { + if (Reads.compareValues(arr[right], arr[mid]) == -1) { Writes.swap(arr, right, mid, 1, true, false); } middle = mid; @@ -95,17 +82,17 @@ private int partition(int[] a, int lo, int hi, int x) { j--; } - if(!(i < j)) { + if (!(i < j)) { Highlights.markArray(1, i); Delays.sleep(0.5); return i; } // Follow the pivot and highlight it. - if(i == middle) { + if (i == middle) { Highlights.markArray(3, j); } - if(j == middle) { + if (j == middle) { Highlights.markArray(3, i); } @@ -114,7 +101,7 @@ private int partition(int[] a, int lo, int hi, int x) { } } - private void introsortLoop (int[] a, int lo, int hi, int depthLimit) { + private void introsortLoop(int[] a, int lo, int hi, int depthLimit) { while (hi - lo > sizeThreshold) { if (depthLimit == 0) { Highlights.clearAllMarks(); diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/KotaSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/KotaSort.java index eaa53c58..2e18c99e 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/KotaSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/KotaSort.java @@ -1,32 +1,21 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.KotaSorting; +@SortMeta(name = "Kota") public final class KotaSort extends KotaSorting { public KotaSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Kota"); - //this.setRunAllID("Grail Sort (Block Merge Sort)"); - //this.setRunAllSortsName("Grail Sort [Block Merge Sort]"); - this.setRunAllSortsName("Kotasort"); - this.setRunSortName("Kotasort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override public void runSort(int[] array, int length, int bucketCount) { - if(Delays.getSleepRatio() == 55.1) { + if (Delays.getSleepRatio() == 55.1) { Delays.setSleepRatio(1); - //this.kotaSortDynamicBuf(array, 0, length); - } - else { + // this.kotaSortDynamicBuf(array, 0, length); + } else { this.kotaSort(array, 0, length); } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/LazierestSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/LazierestSort.java index b884680a..2d1c0dd5 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/LazierestSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/LazierestSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; import io.github.arrayv.utils.IndexedRotations; @@ -29,29 +30,22 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Lazierest Stable") public final class LazierestSort extends Sort { - public LazierestSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Lazierest Stable"); - this.setRunAllSortsName("Lazierest Stable Sort"); - this.setRunSortName("Lazierest Sort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public LazierestSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int ceilCbrt(int n) { int a = 0, b = Math.min(1291, n); - while(a < b) { - int m = (a+b)/2; + while (a < b) { + int m = (a + b) / 2; - if(m*m*m >= n) b = m; - else a = m+1; + if (m * m * m >= n) + b = m; + else + a = m + 1; } return a; @@ -60,118 +54,126 @@ private int ceilCbrt(int n) { private void insertTo(int[] array, int a, int b) { Highlights.clearMark(2); int temp = array[a]; - while(a > b) Writes.write(array, a, array[--a], 0.5, true, false); + while (a > b) + Writes.write(array, a, array[--a], 0.5, true, false); Writes.write(array, b, temp, 0.5, true, false); } private void multiSwap(int[] array, int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(array, a+i, b+i, 1, true, false); + for (int i = 0; i < len; i++) + Writes.swap(array, a + i, b + i, 1, true, false); } - private void rotate(int[] array, int a, int m, int b) { - int l = m-a, r = b-m; + private void rotate(int[] array, int a, int m, int b) { + int l = m - a, r = b - m; - while(l > 0 && r > 0) { - if(r < l) { - this.multiSwap(array, m-r, m, r); + while (l > 0 && r > 0) { + if (r < l) { + this.multiSwap(array, m - r, m, r); b -= r; m -= r; l -= r; - } - else { + } else { this.multiSwap(array, a, m, l); a += l; m += l; r -= l; - } - } - } + } + } + } - private int leftBinSearch(int[] array, int a, int b, int val) { - while(a < b) { - int m = a+(b-a)/2; + private int leftBinSearch(int[] array, int a, int b, int val) { + while (a < b) { + int m = a + (b - a) / 2; - if(Reads.compareValues(val, array[m]) <= 0) + if (Reads.compareValues(val, array[m]) <= 0) b = m; else - a = m+1; + a = m + 1; } return a; } + private int rightBinSearch(int[] array, int a, int b, int val) { - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; - if(Reads.compareValues(val, array[m]) < 0) + if (Reads.compareValues(val, array[m]) < 0) b = m; else - a = m+1; + a = m + 1; } return a; } - private int leftExpSearch(int[] array, int a, int b, int val) { - int i = 1; - while(a-1+i < b && Reads.compareValues(val, array[a-1+i]) > 0) i *= 2; + private int leftExpSearch(int[] array, int a, int b, int val) { + int i = 1; + while (a - 1 + i < b && Reads.compareValues(val, array[a - 1 + i]) > 0) + i *= 2; + + return this.leftBinSearch(array, a + i / 2, Math.min(b, a - 1 + i), val); + } - return this.leftBinSearch(array, a+i/2, Math.min(b, a-1+i), val); - } private int rightExpSearch(int[] array, int a, int b, int val) { - int i = 1; - while(b-i >= a && Reads.compareValues(val, array[b-i]) < 0) i *= 2; + int i = 1; + while (b - i >= a && Reads.compareValues(val, array[b - i]) < 0) + i *= 2; - return this.rightBinSearch(array, Math.max(a, b-i+1), b-i/2, val); - } + return this.rightBinSearch(array, Math.max(a, b - i + 1), b - i / 2, val); + } - private void binaryInsertion(int[] array, int a, int b) { - for(int i = a+1; i < b; i++) + private void binaryInsertion(int[] array, int a, int b) { + for (int i = a + 1; i < b; i++) this.insertTo(array, i, this.rightBinSearch(array, a, i, array[i])); - } + } - private void inPlaceMergeFW(int[] array, int a, int m, int b) { + private void inPlaceMergeFW(int[] array, int a, int m, int b) { int i = a, j = m, k; - while(i < j && j < b){ - if(Reads.compareValues(array[i], array[j]) == 1) { - k = this.leftExpSearch(array, j+1, b, array[i]); + while (i < j && j < b) { + if (Reads.compareValues(array[i], array[j]) == 1) { + k = this.leftExpSearch(array, j + 1, b, array[i]); IndexedRotations.cycleReverse(array, i, j, k, 0.75, true, false); - i += k-j; + i += k - j; j = k; - } - else i++; + } else + i++; } } + private void inPlaceMergeBW(int[] array, int a, int m, int b) { - int i = m-1, j = b-1, k; + int i = m - 1, j = b - 1, k; - while(j > i && i >= a){ - if(Reads.compareValues(array[i], array[j]) > 0) { + while (j > i && i >= a) { + if (Reads.compareValues(array[i], array[j]) > 0) { k = this.rightExpSearch(array, a, i, array[j]); - this.rotate(array, k, i+1, j+1); + this.rotate(array, k, i + 1, j + 1); - j -= (i+1)-k; - i = k-1; - } - else j--; + j -= (i + 1) - k; + i = k - 1; + } else + j--; } } + private void inPlaceMerge(int[] array, int a, int m, int b) { - if(b-m < m-a) this.inPlaceMergeBW(array, a, m, b); - else this.inPlaceMergeFW(array, a, m, b); + if (b - m < m - a) + this.inPlaceMergeBW(array, a, m, b); + else + this.inPlaceMergeFW(array, a, m, b); } private void fragmentedMerge(int[] array, int a, int m, int b, int s) { - int i = a+(m-a)%s; + int i = a + (m - a) % s; - while(i < m) { + while (i < m) { int j = this.leftExpSearch(array, m, b, array[i]); IndexedRotations.cycleReverse(array, i, m, j, 0.75, true, false); - int rLen = j-m; + int rLen = j - m; j = i; i += rLen; m += rLen; @@ -180,30 +182,32 @@ private void fragmentedMerge(int[] array, int a, int m, int b, int s) { a = i; i += s; } - this.inPlaceMerge(array, Math.max(a, i-s), i, b); + this.inPlaceMerge(array, Math.max(a, i - s), i, b); } public void lazierestStableSort(int[] array, int a, int b) { - int len = b-a, s = this.ceilCbrt(len), s1 = s*s; + int len = b - a, s = this.ceilCbrt(len), s1 = s * s; - for(int i = len%s; i <= b; i += s) - this.binaryInsertion(array, Math.max(a, i-s), i); + for (int i = len % s; i <= b; i += s) + this.binaryInsertion(array, Math.max(a, i - s), i); - for(int i = b-s, j = b; i > a; i -= s) { - if(j-i == s1) { + for (int i = b - s, j = b; i > a; i -= s) { + if (j - i == s1) { j -= s1; i -= s; } - this.inPlaceMergeFW(array, Math.max(a, i-s), i, j); + this.inPlaceMergeFW(array, Math.max(a, i - s), i, j); } - for(int i = b-s1; i > a; i -= s1) - this.fragmentedMerge(array, Math.max(a, i-s1), i, b, s); + for (int i = b - s1; i > a; i -= s1) + this.fragmentedMerge(array, Math.max(a, i - s1), i, b, s); } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - if(currentLength <= 16) this.binaryInsertion(array, 0, currentLength); - else this.lazierestStableSort(array, 0, currentLength); - } + @Override + public void runSort(int[] array, int currentLength, int bucketCount) { + if (currentLength <= 16) + this.binaryInsertion(array, 0, currentLength); + else + this.lazierestStableSort(array, 0, currentLength); + } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/LaziestSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/LaziestSort.java index bcfb5da3..7393242e 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/LaziestSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/LaziestSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,126 +29,118 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Laziest") public final class LaziestSort extends Sort { - public LaziestSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - this.setSortListName("Laziest Stable"); - this.setRunAllSortsName("Laziest Stable Sort"); - this.setRunSortName("Laziest Sort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public LaziestSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private void insertTo(int[] array, int a, int b) { Highlights.clearMark(2); int temp = array[a]; - while(a > b) Writes.write(array, a, array[--a], 0.5, true, false); + while (a > b) + Writes.write(array, a, array[--a], 0.5, true, false); Writes.write(array, b, temp, 0.5, true, false); } private void multiSwap(int[] array, int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(array, a+i, b+i, 1, true, false); + for (int i = 0; i < len; i++) + Writes.swap(array, a + i, b + i, 1, true, false); } - private void rotate(int[] array, int a, int m, int b) { - int l = m-a, r = b-m; + private void rotate(int[] array, int a, int m, int b) { + int l = m - a, r = b - m; - while(l > 0 && r > 0) { - if(r < l) { - this.multiSwap(array, m-r, m, r); + while (l > 0 && r > 0) { + if (r < l) { + this.multiSwap(array, m - r, m, r); b -= r; m -= r; l -= r; - } - else { + } else { this.multiSwap(array, a, m, l); a += l; m += l; r -= l; - } - } - } + } + } + } - private int leftBinSearch(int[] array, int a, int b, int val) { - while(a < b) { - int m = a+(b-a)/2; + private int leftBinSearch(int[] array, int a, int b, int val) { + while (a < b) { + int m = a + (b - a) / 2; - if(Reads.compareValues(val, array[m]) <= 0) + if (Reads.compareValues(val, array[m]) <= 0) b = m; else - a = m+1; + a = m + 1; } return a; } private int rightBinSearch(int[] array, int a, int b, int val) { - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; - if(Reads.compareValues(val, array[m]) < 0) + if (Reads.compareValues(val, array[m]) < 0) b = m; else - a = m+1; + a = m + 1; } return a; } - private int leftExpSearch(int[] array, int a, int b, int val) { - int i = 1; - while(a-1+i < b && Reads.compareValues(val, array[a-1+i]) > 0) i *= 2; + private int leftExpSearch(int[] array, int a, int b, int val) { + int i = 1; + while (a - 1 + i < b && Reads.compareValues(val, array[a - 1 + i]) > 0) + i *= 2; - return this.leftBinSearch(array, a+i/2, Math.min(b, a-1+i), val); - } + return this.leftBinSearch(array, a + i / 2, Math.min(b, a - 1 + i), val); + } - private void binaryInsertion(int[] array, int a, int b) { - for(int i = a+1; i < b; i++) + private void binaryInsertion(int[] array, int a, int b) { + for (int i = a + 1; i < b; i++) this.insertTo(array, i, this.rightBinSearch(array, a, i, array[i])); - } + } - private void inPlaceMerge(int[] array, int a, int m, int b) { + private void inPlaceMerge(int[] array, int a, int m, int b) { int i = a, j = m, k; - while(i < j && j < b){ - if(Reads.compareValues(array[i], array[j]) == 1) { - k = this.leftExpSearch(array, j+1, b, array[i]); + while (i < j && j < b) { + if (Reads.compareValues(array[i], array[j]) == 1) { + k = this.leftExpSearch(array, j + 1, b, array[i]); this.rotate(array, i, j, k); - i += k-j; + i += k - j; j = k; - } - else i++; + } else + i++; } } - protected void laziestStableSort(int[] array, int start, int end) { + protected void laziestStableSort(int[] array, int start, int end) { int len = end - start; - if(len <= 16) { + if (len <= 16) { this.binaryInsertion(array, start, end); return; } - int i, blockLen = Math.max(16, (int)Math.sqrt(len)); - for(i = start; i+2*blockLen < end; i+=blockLen) { - this.binaryInsertion(array, i, i+blockLen); + int i, blockLen = Math.max(16, (int) Math.sqrt(len)); + for (i = start; i + 2 * blockLen < end; i += blockLen) { + this.binaryInsertion(array, i, i + blockLen); } this.binaryInsertion(array, i, end); - while(i-blockLen >= start) { - this.inPlaceMerge(array, i-blockLen, i, end); - i-=blockLen; + while (i - blockLen >= start) { + this.inPlaceMerge(array, i - blockLen, i, end); + i -= blockLen; } } - @Override - public void runSort(int[] array, int currentLength, int bucketCount) { - this.laziestStableSort(array, 0, currentLength); - } + @Override + public void runSort(int[] array, int currentLength, int bucketCount) { + this.laziestStableSort(array, 0, currentLength); + } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/MedianMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/MedianMergeSort.java index 7bc22ad3..782048fc 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/MedianMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/MedianMergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.BinaryInsertionSort; import io.github.arrayv.sorts.insert.InsertionSort; import io.github.arrayv.sorts.templates.Sort; @@ -30,136 +31,133 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Median Merge") public final class MedianMergeSort extends Sort { - public MedianMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Median Merge"); - this.setRunAllSortsName("Median Mergesort"); - this.setRunSortName("Median Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public MedianMergeSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private InsertionSort insSort; private BinaryInsertionSort binInsSort; private void medianOfThree(int[] array, int a, int b) { - int m = a+(b-1-a)/2; + int m = a + (b - 1 - a) / 2; - if(Reads.compareIndices(array, a, m, 1, true) == 1) + if (Reads.compareIndices(array, a, m, 1, true) == 1) Writes.swap(array, a, m, 1, true, false); - if(Reads.compareIndices(array, m, b-1, 1, true) == 1) { - Writes.swap(array, m, b-1, 1, true, false); + if (Reads.compareIndices(array, m, b - 1, 1, true) == 1) { + Writes.swap(array, m, b - 1, 1, true, false); - if(Reads.compareIndices(array, a, m, 1, true) == 1) + if (Reads.compareIndices(array, a, m, 1, true) == 1) return; } Writes.swap(array, a, m, 1, true, false); } - //lite version + // lite version private void medianOfMedians(int[] array, int a, int b, int s) { int end = b, start = a, i, j; boolean ad = true; - while(end - start > 1) { + while (end - start > 1) { j = start; Highlights.markArray(2, j); - for(i = start; i+2*s <= end; i+=s) { - this.insSort.customInsertSort(array, i, i+s, 0.25, false); - Writes.swap(array, j++, i+s/2, 1, false, false); + for (i = start; i + 2 * s <= end; i += s) { + this.insSort.customInsertSort(array, i, i + s, 0.25, false); + Writes.swap(array, j++, i + s / 2, 1, false, false); Highlights.markArray(2, j); } - if(i < end) { + if (i < end) { this.insSort.customInsertSort(array, i, end, 0.25, false); - Writes.swap(array, j++, i+(end-(ad ? 1 : 0)-i)/2, 1, false, false); + Writes.swap(array, j++, i + (end - (ad ? 1 : 0) - i) / 2, 1, false, false); Highlights.markArray(2, j); - if((end-i)%2 == 0) ad = !ad; + if ((end - i) % 2 == 0) + ad = !ad; } end = j; } } public int partition(int[] array, int a, int b, int p) { - int i = a - 1; - int j = b; + int i = a - 1; + int j = b; Highlights.markArray(3, p); - while(true) { + while (true) { do { i++; - Highlights.markArray(1, i); - Delays.sleep(0.5); - } - while(i < j && Reads.compareIndices(array, i, p, 0, false) == -1); + Highlights.markArray(1, i); + Delays.sleep(0.5); + } while (i < j && Reads.compareIndices(array, i, p, 0, false) == -1); do { j--; - Highlights.markArray(2, j); - Delays.sleep(0.5); - } - while(j >= i && Reads.compareIndices(array, j, p, 0, false) == 1); + Highlights.markArray(2, j); + Delays.sleep(0.5); + } while (j >= i && Reads.compareIndices(array, j, p, 0, false) == 1); - if(i < j) Writes.swap(array, i, j, 1, true, false); - else return j; - } - } + if (i < j) + Writes.swap(array, i, j, 1, true, false); + else + return j; + } + } private void merge(int[] array, int a, int m, int b, int p) { int i = a, j = m; - while(i < m && j < b) { - if(Reads.compareIndices(array, i, j, 0, false) <= 0) + while (i < m && j < b) { + if (Reads.compareIndices(array, i, j, 0, false) <= 0) Writes.swap(array, p++, i++, 1, true, false); else Writes.swap(array, p++, j++, 1, true, false); } - while(i < m) Writes.swap(array, p++, i++, 1, true, false); - while(j < b) Writes.swap(array, p++, j++, 1, true, false); + while (i < m) + Writes.swap(array, p++, i++, 1, true, false); + while (j < b) + Writes.swap(array, p++, j++, 1, true, false); } public static int getMinLevel(int n) { - while(n >= 32) n = (n+3)/4; + while (n >= 32) + n = (n + 3) / 4; return n; } private void mergeSort(int[] array, int a, int b, int p) { - int length = b-a; - if(length < 2) return; + int length = b - a; + if (length < 2) + return; int i, pos, j = getMinLevel(length); - for(i = a; i+j <= b; i+=j) - this.binInsSort.customBinaryInsert(array, i, i+j, 0.25); + for (i = a; i + j <= b; i += j) + this.binInsSort.customBinaryInsert(array, i, i + j, 0.25); this.binInsSort.customBinaryInsert(array, i, b, 0.25); - while(j < length) { + while (j < length) { pos = p; - for(i = a; i+2*j <= b; i+=2*j, pos+=2*j) - this.merge(array, i, i+j, i+2*j, pos); - if(i + j < b) - this.merge(array, i, i+j, b, pos); + for (i = a; i + 2 * j <= b; i += 2 * j, pos += 2 * j) + this.merge(array, i, i + j, i + 2 * j, pos); + if (i + j < b) + this.merge(array, i, i + j, b, pos); else - while(i < b) Writes.swap(array, i++, pos++, 1, true, false); + while (i < b) + Writes.swap(array, i++, pos++, 1, true, false); j *= 2; pos = a; - for(i = p; i+2*j <= p+length; i+=2*j, pos+=2*j) - this.merge(array, i, i+j, i+2*j, pos); - if(i + j < p+length) - this.merge(array, i, i+j, p+length, pos); + for (i = p; i + 2 * j <= p + length; i += 2 * j, pos += 2 * j) + this.merge(array, i, i + j, i + 2 * j, pos); + if (i + j < p + length) + this.merge(array, i, i + j, p + length, pos); else - while(i < p+length) Writes.swap(array, i++, pos++, 1, true, false); + while (i < p + length) + Writes.swap(array, i++, pos++, 1, true, false); j *= 2; } @@ -169,36 +167,35 @@ private void medianMergeSort(int[] array, int a, int b) { int start = a, end = b; boolean badPartition = false, mom = false; - while(end - start > 16) { - if(badPartition) { + while (end - start > 16) { + if (badPartition) { this.medianOfMedians(array, start, end, 5); mom = true; - } - else this.medianOfThree(array, start, end); + } else + this.medianOfThree(array, start, end); - int p = this.partition(array, start+1, end, start); + int p = this.partition(array, start + 1, end, start); Writes.swap(array, start, p, 1, true, false); - int left = p-start; - int right = end-(p+1); - badPartition = !mom && ((left == 0 || right == 0) || (left/right >= 16 || right/left >= 16)); + int left = p - start; + int right = end - (p + 1); + badPartition = !mom && ((left == 0 || right == 0) || (left / right >= 16 || right / left >= 16)); - if(left <= right) { - this.mergeSort(array, start, p, p+1); - start = p+1; - } - else { - this.mergeSort(array, p+1, end, 2*p+1-end); + if (left <= right) { + this.mergeSort(array, start, p, p + 1); + start = p + 1; + } else { + this.mergeSort(array, p + 1, end, 2 * p + 1 - end); end = p; } } this.binInsSort.customBinaryInsert(array, start, end, 0.25); } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { this.insSort = new InsertionSort(this.arrayVisualizer); this.binInsSort = new BinaryInsertionSort(this.arrayVisualizer); this.medianMergeSort(array, 0, length); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/MergeInsertionSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/MergeInsertionSort.java index 67e72368..01fa82d8 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/MergeInsertionSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/MergeInsertionSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,36 +29,27 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Merge-Insertion") public final class MergeInsertionSort extends Sort { public MergeInsertionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Merge-Insertion");//aka ford-johnson algorithm (in place version) - this.setRunAllSortsName("Merge-Insertion Sort"); - this.setRunSortName("Merge-Insertsort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void blockSwap(int[] array, int a, int b, int s, double sleep) { - while(s-- > 0) Writes.swap(array, a--, b--, sleep, true, false); + while (s-- > 0) + Writes.swap(array, a--, b--, sleep, true, false); } private void blockInsert(int[] array, int a, int b, int s, double sleep) { - while(a-s >= b) { - this.blockSwap(array, a-s, a, s, sleep); + while (a - s >= b) { + this.blockSwap(array, a - s, a, s, sleep); a -= s; } } private void blockReversal(int[] array, int a, int b, int s, double sleep) { b -= s; - while(b > a) { + while (b > a) { this.blockSwap(array, a, b, s, sleep); a += s; b -= s; @@ -65,57 +57,57 @@ private void blockReversal(int[] array, int a, int b, int s, double sleep) { } private int blockSearch(int[] array, int a, int b, int s, int val) { - while(a < b) { - int m = a+(((b-a)/s)/2)*s; + while (a < b) { + int m = a + (((b - a) / s) / 2) * s; - if(Reads.compareValues(val, array[m]) < 0) + if (Reads.compareValues(val, array[m]) < 0) b = m; else - a = m+s; + a = m + s; } return a; } private void order(int[] array, int a, int b, int s, double sleep) { - for(int i = a, j = i+s; j < b; i+=s, j+=2*s) + for (int i = a, j = i + s; j < b; i += s, j += 2 * s) this.blockInsert(array, j, i, s, sleep); - int m = a+(((b-a)/s)/2)*s; + int m = a + (((b - a) / s) / 2) * s; this.blockReversal(array, m, b, s, 1); } @Override public void runSort(int[] array, int length, int bucketCount) { int k = 1; - while(2*k <= length) { - for(int i = 2*k-1; i < length; i+=2*k) - if(Reads.compareValues(array[i-k], array[i]) > 0) - this.blockSwap(array, i-k, i, k, 1); + while (2 * k <= length) { + for (int i = 2 * k - 1; i < length; i += 2 * k) + if (Reads.compareValues(array[i - k], array[i]) > 0) + this.blockSwap(array, i - k, i, k, 1); k *= 2; } double delay = 12; - while(k > 0) { - int a = k-1, i = a+2*k, g = 2, p = 4; + while (k > 0) { + int a = k - 1, i = a + 2 * k, g = 2, p = 4; double sleep = Math.min(1, delay); - while(i+2*k*g-k <= length) { - this.order(array, i, i+2*k*g-k, k, sleep); - int b = a+k*(p-1); + while (i + 2 * k * g - k <= length) { + this.order(array, i, i + 2 * k * g - k, k, sleep); + int b = a + k * (p - 1); - i += k*g-k; - for(int j = i; j < i+k*g; j+=k) + i += k * g - k; + for (int j = i; j < i + k * g; j += k) this.blockInsert(array, j, this.blockSearch(array, a, b, k, array[j]), k, sleep); - i += k*g+k; - g = p-g; + i += k * g + k; + g = p - g; p *= 2; } - while(i < length) { + while (i < length) { this.blockInsert(array, i, this.blockSearch(array, a, i, k, array[i]), k, sleep); - i += 2*k; + i += 2 * k; } k /= 2; diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedBottomUpMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedBottomUpMergeSort.java index 5bfcd73f..a5c477b2 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedBottomUpMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedBottomUpMergeSort.java @@ -1,65 +1,56 @@ package io.github.arrayv.sorts.hybrid; +import javax.xml.crypto.Data; + import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.BinaryInsertionSort; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Optimized Bottom-Up Merge") public final class OptimizedBottomUpMergeSort extends Sort { public OptimizedBottomUpMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Optimized Bottom-Up Merge"); - //this.setRunAllID("Bottom-Up Merge Sort w/ Binary Insert (std::stable_sort)"); - this.setRunAllSortsName("Optimized Bottom-Up Merge Sort [std::stable_sort]"); - this.setRunSortName("Bottom-Up Mergesort w/ Binary Insert"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } /** - * Iterative merge sort algorithm --- as a static method - - * @author: Sartaj Sahni, ported to Java by Timothy Rolfe - - * @see Data Structures, Algorithms, and Applications in C++, - * pp. 680-81 (the original in C++ has a memory leak, but - * that is not a problem in Java due to garbage collection) - - * Minor revision by Timothy Rolfe (tjr) --- saves a comparison + * Iterative merge sort algorithm --- as a static method + * + * @author: Sartaj Sahni, ported to Java by Timothy Rolfe + * + * @see Data Structures, Algorithms, and Applications in C++, + * pp. 680-81 (the original in C++ has a memory leak, but + * that is not a problem in Java due to garbage collection) + * + * Minor revision by Timothy Rolfe (tjr) --- saves a comparison */ - //retrieved from http://penguin.ewu.edu/cscd300/Topic/AdvSorting/MergeSorts/MergeIter.html - private void merge (int[] c, int[] d, int lt, int md, int rt, boolean activeSound) { + // retrieved from + // http://penguin.ewu.edu/cscd300/Topic/AdvSorting/MergeSorts/MergeIter.html + private void merge(int[] c, int[] d, int lt, int md, int rt, boolean activeSound) { // Merge c[lt:md] and c[md+1:rt] to d[lt:rt] - int i = lt, // cursor for first segment - j = md+1, // cursor for second - k = lt; // cursor for result + int i = lt, // cursor for first segment + j = md + 1, // cursor for second + k = lt; // cursor for result // merge until i or j exits its segment - while ( (i <= md) && (j <= rt) ) { + while ((i <= md) && (j <= rt)) { if (Reads.compareValues(c[i], c[j]) <= 0) { - if(activeSound) { + if (activeSound) { Writes.write(d, k++, c[i++], 0.5, false, true); Highlights.markArray(1, i); Highlights.markArray(2, j); - } - else { + } else { Writes.write(d, k++, c[i++], 0.5, false, false); Highlights.markArray(1, k - 1); Highlights.clearMark(2); } - } - else { - if(activeSound) { + } else { + if (activeSound) { Writes.write(d, k++, c[j++], 0.5, false, true); Highlights.markArray(1, j); Highlights.markArray(2, i); - } - else { + } else { Writes.write(d, k++, c[j++], 0.5, false, false); Highlights.markArray(1, k - 1); Highlights.clearMark(2); @@ -67,75 +58,70 @@ private void merge (int[] c, int[] d, int lt, int md, int rt, boolean activeSoun } Delays.sleep(0.5); } - // take care of left overs --- tjr code: only one while loop actually runs - while ( i <= md ) { + // take care of left overs --- tjr code: only one while loop actually runs + while (i <= md) { Writes.write(d, k++, c[i++], 1, true, activeSound); } - while ( j <= rt ) { + while (j <= rt) { Writes.write(d, k++, c[j++], 1, true, activeSound); } } // end merge() - /** - * Perform one pass through the two arrays, invoking Merge() above - */ - private void mergePass (int[] x, int[] y, int s, int n, boolean activeSound) - {// Merge adjacent segments of size s. - int i = 0; - - while (i <= n - 2 * s) - {//Merge two adjacent segments of size s - this.merge (x, y, i, i+s-1, i+2*s-1, activeSound); - i = i + 2*s; - } - // fewer than 2s elements remain - if (i + s < n) { - this.merge (x, y, i, i+s-1, n-1, activeSound); - } - else - for (int j = i; j <= n-1; j++) { - Writes.write(y, j, x[j], 1, false, activeSound); // copy last segment to y - Highlights.markArray(1, j); - Highlights.clearMark(2); - } - - - }// end mergePass() + /** + * Perform one pass through the two arrays, invoking Merge() above + */ + private void mergePass(int[] x, int[] y, int s, int n, boolean activeSound) {// Merge adjacent segments of size s. + int i = 0; + + while (i <= n - 2 * s) {// Merge two adjacent segments of size s + this.merge(x, y, i, i + s - 1, i + 2 * s - 1, activeSound); + i = i + 2 * s; + } + // fewer than 2s elements remain + if (i + s < n) { + this.merge(x, y, i, i + s - 1, n - 1, activeSound); + } else + for (int j = i; j <= n - 1; j++) { + Writes.write(y, j, x[j], 1, false, activeSound); // copy last segment to y + Highlights.markArray(1, j); + Highlights.clearMark(2); + } + + }// end mergePass() /** * Entry point for merge sort */ - private void stableSort (int[] a, int n) { - BinaryInsertionSort binaryInserter = new BinaryInsertionSort(this.arrayVisualizer); - - if(n < 16) { - binaryInserter.customBinaryInsert(a, 0, 16, 0.35); - return; - } - - // Sort a[0:n-1] using merge sort. - int s = 16; // segment size - int[] b = Writes.createExternalArray(n); - int i; - - for(i = 0; i <= n - 16; i += 16) { - binaryInserter.customBinaryInsert(a, i, i + 16, 0.35); - } - binaryInserter.customBinaryInsert(a, i, n, 0.35); - - while (s < n) - { - this.mergePass (a, b, s, n, true); // merge from a to b - s += s; // double the segment size - this.mergePass (b, a, s, n, false); // merge from b to a - s += s; // again, double the segment size - } // end while - // in C/C++, return the scratch array b by free/delete --- tjr + private void stableSort(int[] a, int n) { + BinaryInsertionSort binaryInserter = new BinaryInsertionSort(this.arrayVisualizer); + + if (n < 16) { + binaryInserter.customBinaryInsert(a, 0, 16, 0.35); + return; + } + + // Sort a[0:n-1] using merge sort. + int s = 16; // segment size + int[] b = Writes.createExternalArray(n); + int i; + + for (i = 0; i <= n - 16; i += 16) { + binaryInserter.customBinaryInsert(a, i, i + 16, 0.35); + } + binaryInserter.customBinaryInsert(a, i, n, 0.35); + + while (s < n) { + this.mergePass(a, b, s, n, true); // merge from a to b + s += s; // double the segment size + this.mergePass(b, a, s, n, false); // merge from b to a + s += s; // again, double the segment size + } // end while + // in C/C++, return the scratch array b by free/delete --- tjr // end mergeSort - Writes.deleteExternalArray(b); - }// end MergeArray class + Writes.deleteExternalArray(b); + }// end MergeArray class @Override public void runSort(int[] array, int length, int bucketCount) { diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedDualPivotQuickSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedDualPivotQuickSort.java index b3ada1e1..798276df 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedDualPivotQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedDualPivotQuickSort.java @@ -1,35 +1,25 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.InsertionSort; import io.github.arrayv.sorts.templates.Sort; // code retrieved from https://codeblab.com/wp-content/uploads/2009/09/DualPivotQuicksort.pdf // written by Vladimir Yaroslavskiy - +@SortMeta(name = "Optimized Dual-Pivot Quick") public final class OptimizedDualPivotQuickSort extends Sort { private InsertionSort insertSorter; public OptimizedDualPivotQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Optimized Dual-Pivot Quick"); - //this.setRunAllID("Optimized Dual-Pivot Quick Sort"); - this.setRunAllSortsName("Optimized Dual-Pivot Quick Sort [Arrays.sort]"); - this.setRunSortName("Optimized Dual-Pivot Quicksort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void dualPivot(int[] array, int left, int right, int divisor) { int length = right - left; // insertion sort for tiny array - if(length < 27) { + if (length < 27) { Highlights.clearMark(2); insertSorter.customInsertSort(array, left, right + 1, 0.333, false); return; @@ -38,22 +28,21 @@ private void dualPivot(int[] array, int left, int right, int divisor) { int third = length / divisor; // "medians" - int med1 = left + third; + int med1 = left + third; int med2 = right - third; - if(med1 <= left) { + if (med1 <= left) { med1 = left + 1; } - if(med2 >= right) { + if (med2 >= right) { med2 = right - 1; } - if(Reads.compareIndices(array, med1, med2, 1, true) == -1) { - Writes.swap(array, med1, left, 1, true, false); + if (Reads.compareIndices(array, med1, med2, 1, true) == -1) { + Writes.swap(array, med1, left, 1, true, false); Writes.swap(array, med2, right, 1, true, false); - } - else { + } else { Writes.swap(array, med1, right, 1, true, false); - Writes.swap(array, med2, left, 1, true, false); + Writes.swap(array, med2, left, 1, true, false); } // pivots @@ -61,20 +50,19 @@ private void dualPivot(int[] array, int left, int right, int divisor) { int pivot2 = array[right]; // pointers - int less = left + 1; + int less = left + 1; int great = right - 1; Highlights.markArray(2, less); Highlights.markArray(3, great); // sorting - for(int k = less; k <= great; k++) { - if(Reads.compareIndexValue(array, k, pivot1, 0.5, true) == -1) { + for (int k = less; k <= great; k++) { + if (Reads.compareIndexValue(array, k, pivot1, 0.5, true) == -1) { Writes.swap(array, k, less++, 0.5, false, false); Highlights.markArray(2, less); - } - else if(Reads.compareIndexValue(array, k, pivot2, 0.5, true) == 1) { - while(k < great && Reads.compareIndexValue(array, great, pivot2, 0.5, false) == 1) { + } else if (Reads.compareIndexValue(array, k, pivot2, 0.5, true) == 1) { + while (k < great && Reads.compareIndexValue(array, great, pivot2, 0.5, false) == 1) { great--; Highlights.markArray(3, great); Delays.sleep(0.5); @@ -82,7 +70,7 @@ else if(Reads.compareIndexValue(array, k, pivot2, 0.5, true) == 1) { Writes.swap(array, k, great--, 0.5, false, false); Highlights.markArray(3, great); - if(Reads.compareIndexValue(array, k, pivot1, 0.5, true) == -1) { + if (Reads.compareIndexValue(array, k, pivot1, 0.5, true) == -1) { Writes.swap(array, k, less++, 0.5, false, false); Highlights.markArray(2, less); } @@ -93,31 +81,30 @@ else if(Reads.compareIndexValue(array, k, pivot2, 0.5, true) == 1) { // swaps int dist = great - less; - if(dist < 13) { + if (dist < 13) { divisor++; } - Writes.swap(array, less - 1, left, 1, true, false); + Writes.swap(array, less - 1, left, 1, true, false); Writes.swap(array, great + 1, right, 1, true, false); // subarrays - this.dualPivot(array, left, less - 2, divisor); + this.dualPivot(array, left, less - 2, divisor); this.dualPivot(array, great + 2, right, divisor); Highlights.markArray(2, less); Highlights.markArray(3, great); // equal elements - if(dist > length - 13 && pivot1 != pivot2) { - for(int k = less; k <= great; k++) { - if(Reads.compareIndexValue(array, k, pivot1, 0.5, true) == 0) { + if (dist > length - 13 && pivot1 != pivot2) { + for (int k = less; k <= great; k++) { + if (Reads.compareIndexValue(array, k, pivot1, 0.5, true) == 0) { Writes.swap(array, k, less++, 0.5, false, false); Highlights.markArray(2, less); - } - else if(Reads.compareIndexValue(array, k, pivot2, 0.5, true) == 0) { + } else if (Reads.compareIndexValue(array, k, pivot2, 0.5, true) == 0) { Writes.swap(array, k, great--, 0.5, false, false); Highlights.markArray(3, great); - if(Reads.compareIndexValue(array, k, pivot1, 0.5, true) == 0) { + if (Reads.compareIndexValue(array, k, pivot1, 0.5, true) == 0) { Writes.swap(array, k, less++, 0.5, false, false); Highlights.markArray(2, less); } @@ -127,7 +114,7 @@ else if(Reads.compareIndexValue(array, k, pivot2, 0.5, true) == 0) { Highlights.clearAllMarks(); // subarray - if(pivot1 < pivot2) { + if (pivot1 < pivot2) { this.dualPivot(array, less, great, divisor); } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedLazyStableSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedLazyStableSort.java index 686b0585..54ad909e 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedLazyStableSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedLazyStableSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.GrailSorting; /* @@ -37,36 +38,28 @@ this software and associated documentation files (the "Software"), to deal in /* methods copied from Grail Sort */ /* */ /*****************************************/ - +@SortMeta(name = "Optimized Lazy Stable") public final class OptimizedLazyStableSort extends GrailSorting { public OptimizedLazyStableSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Optimized Lazy Stable"); - this.setRunAllSortsName("Optimized Lazy Stable Sort"); - this.setRunSortName("Optimized Lazy Stable Sort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } public void insertionSort(int[] array, int a, int b, double sleep, boolean auxwrite) { int i = a + 1; - if(Reads.compareIndices(array, i - 1, i++, sleep, true) == 1) { - while(i < b && Reads.compareIndices(array, i - 1, i, sleep, true) == 1) i++; + if (Reads.compareIndices(array, i - 1, i++, sleep, true) == 1) { + while (i < b && Reads.compareIndices(array, i - 1, i, sleep, true) == 1) + i++; Writes.reversal(array, a, i - 1, sleep, true, auxwrite); - } - else while(i < b && Reads.compareIndices(array, i - 1, i, sleep, true) <= 0) i++; + } else + while (i < b && Reads.compareIndices(array, i - 1, i, sleep, true) <= 0) + i++; Highlights.clearMark(2); - while(i < b) { + while (i < b) { int current = array[i]; int pos = i - 1; - while(pos >= a && Reads.compareValues(array[pos], current) > 0){ + while (pos >= a && Reads.compareValues(array[pos], current) > 0) { Writes.write(array, pos + 1, array[pos], sleep, true, auxwrite); pos--; } @@ -76,6 +69,7 @@ public void insertionSort(int[] array, int a, int b, double sleep, boolean auxwr } } + @Override protected void grailLazyStableSort(int[] arr, int pos, int len) { int dist; for (dist = 0; dist + 16 < len; dist += 16) @@ -83,17 +77,17 @@ protected void grailLazyStableSort(int[] arr, int pos, int len) { if (dist < len) insertionSort(arr, pos + dist, pos + len, 1, false); - for(int part = 16; part < len; part *= 2) { + for (int part = 16; part < len; part *= 2) { int left = 0; int right = len - 2 * part; - while(left <= right) { + while (left <= right) { this.grailMergeWithoutBuffer(arr, pos + left, part, part); left += 2 * part; } int rest = len - left; - if(rest > part) { + if (rest > part) { this.grailMergeWithoutBuffer(arr, pos + left, part, rest - part); } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedRotateMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedRotateMergeSort.java index b747c5ac..a9ab04f4 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedRotateMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedRotateMergeSort.java @@ -4,12 +4,7 @@ import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; -@SortMeta( - name = "Optimized Rotate Merge", - category = "Hybrid Sorts", - question = "How many items should the temp array contain? (must be a power of two) (default: 64)", - defaultAnswer = 64 -) +@SortMeta(name = "Optimized Rotate Merge", question = "How many items should the temp array contain? (must be a power of two) (default: 64)", defaultAnswer = 64) public final class OptimizedRotateMergeSort extends Sort { final int MIN_RUN = 32; @@ -20,12 +15,13 @@ public OptimizedRotateMergeSort(ArrayVisualizer arrayVisualizer) { } protected void rotateInPlace(int[] array, int pos, int lenA, int lenB) { - if (lenA < 1 || lenB < 1) return; + if (lenA < 1 || lenB < 1) + return; int a = pos, - b = pos + lenA - 1, - c = pos + lenA, - d = pos + lenA + lenB - 1; + b = pos + lenA - 1, + c = pos + lenA, + d = pos + lenA + lenB - 1; int tmp; while (a < b && c < d) { @@ -33,28 +29,29 @@ protected void rotateInPlace(int[] array, int pos, int lenA, int lenB) { Writes.write(array, b--, array[a], 0.5, true, false); Writes.write(array, a++, array[c], 0.5, true, false); Writes.write(array, c++, array[d], 0.5, true, false); - Writes.write(array, d--, tmp, 0.5, true, false); + Writes.write(array, d--, tmp, 0.5, true, false); } while (a < b) { tmp = array[b]; Writes.write(array, b--, array[a], 0.5, true, false); Writes.write(array, a++, array[d], 0.5, true, false); - Writes.write(array, d--, tmp, 0.5, true, false); + Writes.write(array, d--, tmp, 0.5, true, false); } while (c < d) { tmp = array[c]; Writes.write(array, c++, array[d], 0.5, true, false); Writes.write(array, d--, array[a], 0.5, true, false); - Writes.write(array, a++, tmp, 0.5, true, false); + Writes.write(array, a++, tmp, 0.5, true, false); } - if (a < d) { //dont count reversals that dont do anything + if (a < d) { // dont count reversals that dont do anything Writes.reversal(array, a, d, 1, true, false); Highlights.clearMark(2); } } protected void rotate(int[] array, int pos, int left, int right) { - if (left < 1 || right < 1) return; + if (left < 1 || right < 1) + return; int pta = pos, ptb = pos + left, ptc = pos + right, ptd = ptb + right; @@ -73,7 +70,7 @@ protected void rotate(int[] array, int pos, int left, int right) { while (loop-- > 0) { Writes.write(array, --ptc, array[--ptd], 0.5, true, false); - Writes.write(array, ptd, array[--ptb], 0.5, true, false); + Writes.write(array, ptd, array[--ptb], 0.5, true, false); } Writes.arraycopy(tmp, 0, array, pta, bridge, 1, true, false); } else { @@ -86,7 +83,7 @@ protected void rotate(int[] array, int pos, int left, int right) { Writes.arraycopy(array, ptb, array, pta, right, 1, true, false); Writes.arraycopy(tmp, 0, array, ptc, left, 1, true, false); } - } else if(right < left) { + } else if (right < left) { int bridge = left - right; if (bridge < right) { @@ -99,8 +96,8 @@ protected void rotate(int[] array, int pos, int left, int right) { Writes.arraycopy(array, ptc, tmp, 0, bridge, 1, true, true); - while(loop-- > 0) { - Writes.write(array, ptc++, array[pta], 0.5, true, false); + while (loop-- > 0) { + Writes.write(array, ptc++, array[pta], 0.5, true, false); Writes.write(array, pta++, array[ptb++], 0.5, true, false); } Writes.arraycopy(tmp, 0, array, ptd - bridge, bridge, 1, true, false); @@ -115,8 +112,7 @@ protected void rotate(int[] array, int pos, int left, int right) { Writes.write(array, --ptd, array[--ptb], 1, true, false); Writes.arraycopy(tmp, 0, array, pta, right, 1, true, false); } - } - else { + } else { while (left-- > 0) Writes.swap(array, pta++, ptb++, 1, true, false); Highlights.clearMark(2); @@ -213,22 +209,26 @@ private int monoboundRight(int[] array, int start, int end, int value) { private int leftExpSearch(int[] array, int a, int b, int val) { int i = 1; - while (a - 1 + i < b && Reads.compareValueIndex(array, val, a - 1 + i, 0.5, true) >= 0) i *= 2; + while (a - 1 + i < b && Reads.compareValueIndex(array, val, a - 1 + i, 0.5, true) >= 0) + i *= 2; return this.monoboundRight(array, a + i / 2, Math.min(b, a - 1 + i), val); } private int rightExpSearch(int[] array, int a, int b, int val) { int i = 1; - while (b - i >= a && Reads.compareValueIndex(array, val, b - i, 0.5, true) <= 0) i *= 2; + while (b - i >= a && Reads.compareValueIndex(array, val, b - i, 0.5, true) <= 0) + i *= 2; return this.monoboundLeft(array, Math.max(a, b - i + 1), b - i / 2, val); } protected void merge(int[] array, int start, int mid, int end) { - if (start >= mid) return; + if (start >= mid) + return; end = rightExpSearch(array, mid, end, array[mid - 1]); - if (end < mid) return; + if (end < mid) + return; start = leftExpSearch(array, start, mid, array[mid]); if (Reads.compareIndices(array, start, end - 1, 1, true) > 0) { rotate(array, start, mid - start, end - mid); @@ -261,10 +261,12 @@ protected void merge(int[] array, int start, int mid, int end) { public void insertionSort(int[] array, int a, int b, double sleep, boolean auxwrite) { int i = a + 1; if (Reads.compareIndices(array, i - 1, i++, sleep, true) == 1) { - while (i < b && Reads.compareIndices(array, i - 1, i, sleep, true) == 1) i++; + while (i < b && Reads.compareIndices(array, i - 1, i, sleep, true) == 1) + i++; Writes.reversal(array, a, i - 1, sleep, true, auxwrite); - } - else while (i < b && Reads.compareIndices(array, i - 1, i, sleep, true) <= 0) i++; + } else + while (i < b && Reads.compareIndices(array, i - 1, i, sleep, true) <= 0) + i++; Highlights.clearMark(2); diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedWeaveMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedWeaveMergeSort.java index d9aeadd2..0a234f5b 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedWeaveMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/OptimizedWeaveMergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,44 +29,34 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Optimized Weave Merge") public final class OptimizedWeaveMergeSort extends Sort { public OptimizedWeaveMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Optimized Weave Merge"); - this.setRunAllSortsName("Optimized Weave Merge Sort"); - this.setRunSortName("Optimized Weave Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void insertTo(int[] array, int a, int b) { int temp = array[a]; - while(a > b) Writes.write(array, a, array[--a], 0.25, true, false); + while (a > b) + Writes.write(array, a, array[--a], 0.25, true, false); Writes.write(array, b, temp, 0.25, true, false); } private void multiSwap(int[] array, int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(array, a+i, b+i, 1, true, false); + for (int i = 0; i < len; i++) + Writes.swap(array, a + i, b + i, 1, true, false); } private void rotate(int[] array, int a, int m, int b) { - int l = m-a, r = b-m; + int l = m - a, r = b - m; - while(l > 0 && r > 0) { - if(r < l) { - this.multiSwap(array, m-r, m, r); + while (l > 0 && r > 0) { + if (r < l) { + this.multiSwap(array, m - r, m, r); b -= r; m -= r; l -= r; - } - else { + } else { this.multiSwap(array, a, m, l); a += l; m += l; @@ -74,35 +65,33 @@ private void rotate(int[] array, int a, int m, int b) { } } - //pow of 2 only (O(n)) + // pow of 2 only (O(n)) private void bitReversal(int[] array, int a, int b) { - int len = b-a, m = 0; - int d1 = len>>1, d2 = d1+(d1>>1); + int len = b - a, m = 0; + int d1 = len >> 1, d2 = d1 + (d1 >> 1); - for(int i = 1; i < len-1; i++) { + for (int i = 1; i < len - 1; i++) { int j = d1; - for( - int k = i, n = d2; - (k&1) == 0; - j -= n, k >>= 1, n >>= 1 - ); + for (int k = i, n = d2; (k & 1) == 0; j -= n, k >>= 1, n >>= 1) + ; m += j; - if(m > i) Writes.swap(array, a+i, a+m, 1, true, false); + if (m > i) + Writes.swap(array, a + i, a + m, 1, true, false); } } private void weaveInsert(int[] array, int a, int b, boolean right) { - int i = a, j = i+1; + int i = a, j = i + 1; - while(j < b) { - while(i < j && Reads.compareIndices(array, i, j, 0, true) < (right ? 1 : 0)) i++; + while (j < b) { + while (i < j && Reads.compareIndices(array, i, j, 0, true) < (right ? 1 : 0)) + i++; - if(i == j) { + if (i == j) { right = !right; j++; - } - else { + } else { this.insertTo(array, j, i++); j += 2; } @@ -110,30 +99,31 @@ private void weaveInsert(int[] array, int a, int b, boolean right) { Highlights.clearMark(3); } - //000111 -> 010101 T - //00011 -> 01010 T - //00111 -> 10101 F + // 000111 -> 010101 T + // 00011 -> 01010 T + // 00111 -> 10101 F private void weaveMerge(int[] array, int a, int m, int b) { - if(b-a < 2) return; + if (b - a < 2) + return; int a1 = a, b1 = b; boolean right = true; - if((b-a)%2 == 1) { - if(m-a < b-m) { + if ((b - a) % 2 == 1) { + if (m - a < b - m) { a1--; right = false; - } - else b1++; + } else + b1++; } - for(int e = b1, f; e-a1 > 2; e = f) { - m = (a1+e)/2; - int p = 1 << (int)(Math.log(m-a1)/Math.log(2)); + for (int e = b1, f; e - a1 > 2; e = f) { + m = (a1 + e) / 2; + int p = 1 << (int) (Math.log(m - a1) / Math.log(2)); - this.rotate(array, m-p, m, e-p); - m = e-p; - f = m-p; + this.rotate(array, m - p, m, e - p); + m = e - p; + f = m - p; this.bitReversal(array, f, m); this.bitReversal(array, m, e); @@ -145,21 +135,21 @@ private void weaveMerge(int[] array, int a, int m, int b) { @Override public void runSort(int[] array, int currentLength, int bucketCount) { - int n = currentLength, d = 1 << (int)(Math.log(n-1)/Math.log(2) + 1); + int n = currentLength, d = 1 << (int) (Math.log(n - 1) / Math.log(2) + 1); - while(d > 1) { + while (d > 1) { int i = 0, dec = 0; - while(i < n) { + while (i < n) { int j = i; dec += n; - while(dec >= d) { + while (dec >= d) { dec -= d; j++; } int k = j; dec += n; - while(dec >= d) { + while (dec >= d) { dec -= d; k++; } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/PDQBranchedSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/PDQBranchedSort.java index 45c507b6..2dd3fa87 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/PDQBranchedSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/PDQBranchedSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.select.MaxHeapSort; import io.github.arrayv.sorts.templates.PDQSorting; @@ -20,20 +21,10 @@ 3. This notice may not be removed or altered from any source distribution. * */ - +@SortMeta(name = "Pattern-Defeating Quick") public final class PDQBranchedSort extends PDQSorting { public PDQBranchedSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Pattern-Defeating Quick (PDQ)"); - this.setRunAllSortsName("Pattern-Defeating Quick Sort"); - this.setRunSortName("Pattern-Defeating Quicksort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } public void customSort(int[] array, int low, int high) { diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/PDQBranchlessSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/PDQBranchlessSort.java index cdb9c739..1bcc2090 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/PDQBranchlessSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/PDQBranchlessSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.select.MaxHeapSort; import io.github.arrayv.sorts.templates.PDQSorting; @@ -20,20 +21,10 @@ 3. This notice may not be removed or altered from any source distribution. * */ - +@SortMeta(listName = "Pattern-Defeating Quick (Branchless)", runName = "Branchless Pattern-Defeating Quick Sort") public final class PDQBranchlessSort extends PDQSorting { public PDQBranchlessSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Pattern-Defeating Quick (Branchless PDQ)"); - this.setRunAllSortsName("Branchless Pattern-Defeating Quick Sort"); - this.setRunSortName("Branchless Pattern-Defeating Quicksort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/ParallelBlockMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/ParallelBlockMergeSort.java index 14936f8e..54e55db5 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/ParallelBlockMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/ParallelBlockMergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.BinaryInsertionSort; import io.github.arrayv.sorts.templates.Sort; @@ -29,21 +30,11 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Parallel Block Merge", unreasonableLimit = 4096) public final class ParallelBlockMergeSort extends Sort { - public ParallelBlockMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Parallel Block Merge"); - this.setRunAllSortsName("Parallel Block Merge Sort"); - this.setRunSortName("Parallel Block Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public ParallelBlockMergeSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int[] array; @@ -54,6 +45,8 @@ private class BlockMergeSort extends Thread { this.a = a; this.b = b; } + + @Override public void run() { ParallelBlockMergeSort.this.blockMergeSort(a, b); } @@ -62,113 +55,122 @@ public void run() { private int sqrt(int n) { int a = 0, b = Math.min(46341, n); - while(a < b) { - int m = (a+b)/2; + while (a < b) { + int m = (a + b) / 2; - if(m*m >= n) b = m; - else a = m+1; + if (m * m >= n) + b = m; + else + a = m + 1; } return a; } private void multiSwap(int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(array, a+i, b+i, 1, true, false); + for (int i = 0; i < len; i++) + Writes.swap(array, a + i, b + i, 1, true, false); } - private void rotate(int a, int m, int b) { - int l = m-a, r = b-m; + private void rotate(int a, int m, int b) { + int l = m - a, r = b - m; - while(l > 0 && r > 0) { - if(r < l) { - this.multiSwap(m-r, m, r); + while (l > 0 && r > 0) { + if (r < l) { + this.multiSwap(m - r, m, r); b -= r; m -= r; l -= r; - } - else { + } else { this.multiSwap(a, m, l); a += l; m += l; r -= l; - } - } - } + } + } + } private void inPlaceMergeFW(int a, int m, int b) { int i = a, j = m, k; - while(i < j && j < b) { - if(Reads.compareValues(array[i], array[j]) > 0) { + while (i < j && j < b) { + if (Reads.compareValues(array[i], array[j]) > 0) { k = j; - while(++k < b && Reads.compareIndices(array, i, k, 0, false) > 0); + while (++k < b && Reads.compareIndices(array, i, k, 0, false) > 0) + ; this.rotate(i, j, k); - i += k-j; + i += k - j; j = k; - } - else i++; + } else + i++; } } + private void inPlaceMergeBW(int a, int m, int b) { - int i = m-1, j = b-1, k; + int i = m - 1, j = b - 1, k; - while(j > i && i >= a){ - if(Reads.compareValues(array[i], array[j]) > 0) { + while (j > i && i >= a) { + if (Reads.compareValues(array[i], array[j]) > 0) { k = i; - while(--k >= a && Reads.compareIndices(array, k, j, 0, false) > 0); + while (--k >= a && Reads.compareIndices(array, k, j, 0, false) > 0) + ; - this.rotate(k+1, i+1, j+1); + this.rotate(k + 1, i + 1, j + 1); - j -= i-k; + j -= i - k; i = k; - } - else j--; + } else + j--; } } private void mergeFW(int p, int a, int m, int b) { - int len2 = m-a, pEnd = p+len2; + int len2 = m - a, pEnd = p + len2; this.multiSwap(p, a, len2); - while(p < pEnd && m < b) { - if(Reads.compareValues(array[p], array[m]) <= 0) + while (p < pEnd && m < b) { + if (Reads.compareValues(array[p], array[m]) <= 0) Writes.swap(array, a++, p++, 1, true, false); - else Writes.swap(array, a++, m++, 1, true, false); + else + Writes.swap(array, a++, m++, 1, true, false); } - while(p < pEnd) + while (p < pEnd) Writes.swap(array, a++, p++, 1, true, false); } + private void mergeBW(int p, int a, int m, int b) { - int len2 = b-m, pEnd = p+len2-1; + int len2 = b - m, pEnd = p + len2 - 1; this.multiSwap(p, m, len2); m--; - while(pEnd >= p && m >= a) { - if(Reads.compareValues(array[pEnd], array[m]) >= 0) + while (pEnd >= p && m >= a) { + if (Reads.compareValues(array[pEnd], array[m]) >= 0) Writes.swap(array, --b, pEnd--, 1, true, false); - else Writes.swap(array, --b, m--, 1, true, false); + else + Writes.swap(array, --b, m--, 1, true, false); } - while(pEnd >= p) + while (pEnd >= p) Writes.swap(array, --b, pEnd--, 1, true, false); } private int findKeys(int a, int b, int n) { - int p = a, found = 1, pEnd = p+found, i = pEnd; + int p = a, found = 1, pEnd = p + found, i = pEnd; - while(found < n) { - while(i < b && Reads.compareIndices(array, pEnd-1, i, 1, true) == 0) i++; - if(i == b) break; + while (found < n) { + while (i < b && Reads.compareIndices(array, pEnd - 1, i, 1, true) == 0) + i++; + if (i == b) + break; this.rotate(p, pEnd, i); - p += i-pEnd; + p += i - pEnd; pEnd = ++i; found++; @@ -180,143 +182,143 @@ private int findKeys(int a, int b, int n) { private int selectMin(int a, int b, int bLen) { int min = a; - for(int i = min+bLen; i < b; i += bLen) - if(Reads.compareValues(array[i], array[min]) < 0) + for (int i = min + bLen; i < b; i += bLen) + if (Reads.compareValues(array[i], array[min]) < 0) min = i; return min; } private void blockMerge(int a, int m, int b) { - if(Reads.compareValues(array[m-1], array[m]) <= 0) return; + if (Reads.compareValues(array[m - 1], array[m]) <= 0) + return; - else if(Reads.compareValues(array[a], array[b-1]) > 0) { + else if (Reads.compareValues(array[a], array[b - 1]) > 0) { this.rotate(a, m, b); return; } - int len1 = m-a; + int len1 = m - a; int bLen = this.sqrt(len1); - int tLen = len1/bLen; - int idl = bLen+tLen; + int tLen = len1 / bLen; + int idl = bLen + tLen; int keys = this.findKeys(a, m, idl); - int a1 = a+keys; + int a1 = a + keys; len1 -= keys; - if(keys == idl) { - int b1 = b-(b-m)%bLen; + if (keys == idl) { + int b1 = b - (b - m) % bLen; - int t = a; - int p = a+tLen; + int t = a; + int p = a + tLen; - int i = a1+(len1-1)%bLen+1; + int i = a1 + (len1 - 1) % bLen + 1; - for(int j = i, k = t; j < m; j += bLen, k++) + for (int j = i, k = t; j < m; j += bLen, k++) Writes.swap(array, j, k, 10, true, false); - while(i < m && m < b1) { - if(Reads.compareValues(array[i-1], array[m+bLen-1]) > 0) { + while (i < m && m < b1) { + if (Reads.compareValues(array[i - 1], array[m + bLen - 1]) > 0) { this.multiSwap(i, m, bLen); - this.mergeBW(p, a1, i, i+bLen); + this.mergeBW(p, a1, i, i + bLen); m += bLen; - } - else { + } else { int min = this.selectMin(i, m, bLen); - if(min != i) this.multiSwap(i, min, bLen); + if (min != i) + this.multiSwap(i, min, bLen); Writes.swap(array, t++, i, 1, true, false); } i += bLen; } - if(i < m) { + if (i < m) { do { int min = this.selectMin(i, m, bLen); this.multiSwap(i, min, bLen); Writes.swap(array, t++, i, 1, true, false); i += bLen; - } - while(i < m); + } while (i < m); this.mergeBW(p, a1, b1, b); - } - else { - while(m < b1 && Reads.compareValues(array[m-bLen], array[m]) > 0) { - this.mergeBW(p, a1, m, m+bLen); + } else { + while (m < b1 && Reads.compareValues(array[m - bLen], array[m]) > 0) { + this.mergeBW(p, a1, m, m + bLen); m += bLen; } - if(m == b1) this.mergeBW(p, a1, b1, b); - else this.mergeFW(p, m-bLen+1, m, b); + if (m == b1) + this.mergeBW(p, a1, b1, b); + else + this.mergeFW(p, m - bLen + 1, m, b); } BinaryInsertionSort insertion = new BinaryInsertionSort(this.arrayVisualizer); insertion.customBinaryInsert(array, p, a1, 0.5); - this.inPlaceMergeFW(a, a+keys, b); - } - else if(keys > 1) { - bLen = (len1-1)/keys+1; - int b1 = b-(b-m)%bLen; + this.inPlaceMergeFW(a, a + keys, b); + } else if (keys > 1) { + bLen = (len1 - 1) / keys + 1; + int b1 = b - (b - m) % bLen; - int t = a; - int i = a1+(len1-1)%bLen+1; + int t = a; + int i = a1 + (len1 - 1) % bLen + 1; - for(int j = i, k = t; j < m; j += bLen, k++) + for (int j = i, k = t; j < m; j += bLen, k++) Writes.swap(array, j, k, 10, true, false); - while(i < m && m < b1) { - if(Reads.compareValues(array[i-1], array[m+bLen-1]) > 0) { + while (i < m && m < b1) { + if (Reads.compareValues(array[i - 1], array[m + bLen - 1]) > 0) { this.multiSwap(i, m, bLen); - this.inPlaceMergeBW(a1, i, i+bLen); + this.inPlaceMergeBW(a1, i, i + bLen); m += bLen; - } - else { + } else { int min = this.selectMin(i, m, bLen); - if(min != i) this.multiSwap(i, min, bLen); + if (min != i) + this.multiSwap(i, min, bLen); Writes.swap(array, t++, i, 1, true, false); } i += bLen; } - if(i < m) { + if (i < m) { do { int min = this.selectMin(i, m, bLen); this.multiSwap(i, min, bLen); Writes.swap(array, t++, i, 1, true, false); i += bLen; - } - while(i < m); + } while (i < m); this.inPlaceMergeBW(a1, b1, b); - } - else { - while(m < b1 && Reads.compareValues(array[m-bLen], array[m]) > 0) { - this.inPlaceMergeBW(a1, m, m+bLen); + } else { + while (m < b1 && Reads.compareValues(array[m - bLen], array[m]) > 0) { + this.inPlaceMergeBW(a1, m, m + bLen); m += bLen; } - if(m == b1) this.inPlaceMergeBW(a1, b1, b); - else this.inPlaceMergeFW(m-bLen+1, m, b); + if (m == b1) + this.inPlaceMergeBW(a1, b1, b); + else + this.inPlaceMergeFW(m - bLen + 1, m, b); } - this.inPlaceMergeFW(a, a+keys, b); - } - else this.inPlaceMergeFW(a, m, b); + this.inPlaceMergeFW(a, a + keys, b); + } else + this.inPlaceMergeFW(a, m, b); } private void blockMergeSort(int a, int b) { - if(b-a < 32) { + if (b - a < 32) { BinaryInsertionSort insertion = new BinaryInsertionSort(this.arrayVisualizer); insertion.customBinaryInsert(array, a, b, 0.5); return; } - int m = a+(b-a)/2; + int m = a + (b - a) / 2; - BlockMergeSort left = new BlockMergeSort(a, m); + BlockMergeSort left = new BlockMergeSort(a, m); BlockMergeSort right = new BlockMergeSort(m, b); left.start(); right.start(); @@ -324,17 +326,16 @@ private void blockMergeSort(int a, int b) { try { left.join(); right.join(); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } this.blockMerge(a, m, b); } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { this.array = array; this.blockMergeSort(0, length); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/ParallelGrailSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/ParallelGrailSort.java index c7524f83..3ef6b7d5 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/ParallelGrailSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/ParallelGrailSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,21 +29,11 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Parallel Grail", unreasonableLimit = 4096) public final class ParallelGrailSort extends Sort { - public ParallelGrailSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Parallel Grail"); - this.setRunAllSortsName("Parallel Grail Sort"); - this.setRunSortName("Parallel Grailsort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public ParallelGrailSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int[] array; @@ -54,6 +45,8 @@ private class GrailCommonSort extends Thread { this.b = b; this.nKeys = nKeys; } + + @Override public void run() { ParallelGrailSort.this.grailCommonSort(a, b, nKeys); } @@ -66,6 +59,8 @@ private class LazyStableSort extends Thread { this.a = a; this.b = b; } + + @Override public void run() { ParallelGrailSort.this.lazyStableSort(a, b); } @@ -79,10 +74,13 @@ private class RedistFW extends Thread { this.m = m; this.b = b; } + + @Override public void run() { ParallelGrailSort.this.redistFW(a, m, b); } } + private class RedistBW extends Thread { private int a, m, b; @@ -91,6 +89,8 @@ private class RedistBW extends Thread { this.m = m; this.b = b; } + + @Override public void run() { ParallelGrailSort.this.redistBW(a, m, b); } @@ -99,96 +99,104 @@ public void run() { private int sqrt(int n) { int a = 0, b = Math.min(46341, n); - while(a < b) { - int m = (a+b)/2; + while (a < b) { + int m = (a + b) / 2; - if(m*m >= n) b = m; - else a = m+1; + if (m * m >= n) + b = m; + else + a = m + 1; } return a; } private void shiftFW(int a, int m, int b) { - while(m < b) Writes.swap(array, a++, m++, 1, true, false); + while (m < b) + Writes.swap(array, a++, m++, 1, true, false); } + private void shiftBW(int a, int m, int b) { - while(m > a) Writes.swap(array, --b, --m, 1, true, false); + while (m > a) + Writes.swap(array, --b, --m, 1, true, false); } private void multiSwap(int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(array, a+i, b+i, 1, true, false); + for (int i = 0; i < len; i++) + Writes.swap(array, a + i, b + i, 1, true, false); } - private void rotate(int a, int m, int b) { - int l = m-a, r = b-m; + private void rotate(int a, int m, int b) { + int l = m - a, r = b - m; - while(l > 0 && r > 0) { - if(r < l) { - this.multiSwap(m-r, m, r); + while (l > 0 && r > 0) { + if (r < l) { + this.multiSwap(m - r, m, r); b -= r; m -= r; l -= r; - } - else { + } else { this.multiSwap(a, m, l); a += l; m += l; r -= l; - } - } - } + } + } + } - private void insertTo(int a, int b) { + private void insertTo(int a, int b) { Highlights.clearMark(2); int temp = array[a]; - while(a > b) Writes.write(array, a, array[--a], 0.5, true, false); + while (a > b) + Writes.write(array, a, array[--a], 0.5, true, false); Writes.write(array, b, temp, 0.5, true, false); } private int leftBinSearch(int a, int b, int val) { - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; - if(Reads.compareValues(val, array[m]) <= 0) + if (Reads.compareValues(val, array[m]) <= 0) b = m; else - a = m+1; + a = m + 1; } return a; } - private int rightBinSearch(int a, int b, int val) { - while(a < b) { - int m = a+(b-a)/2; - if(Reads.compareValues(val, array[m]) < 0) + private int rightBinSearch(int a, int b, int val) { + while (a < b) { + int m = a + (b - a) / 2; + + if (Reads.compareValues(val, array[m]) < 0) b = m; else - a = m+1; + a = m + 1; } return a; } private void binaryInsertion(int a, int b) { - for(int i = a+1; i < b; i++) + for (int i = a + 1; i < b; i++) this.insertTo(i, this.rightBinSearch(a, i, array[i])); - } + } private int mergeFW(int p, int a, int m, int b, boolean fwEq) { int i = a, j = m; - while(i < m && j < b) { - if(Reads.compareValues(array[i], array[j]) < (fwEq ? 1 : 0)) + while (i < m && j < b) { + if (Reads.compareValues(array[i], array[j]) < (fwEq ? 1 : 0)) Writes.swap(array, p++, i++, 1, true, false); - else Writes.swap(array, p++, j++, 1, true, false); + else + Writes.swap(array, p++, j++, 1, true, false); } int f = i < m ? i : j; - if(i < m && p < i) this.shiftFW(p, i, m); + if (i < m && p < i) + this.shiftFW(p, i, m); return f; } @@ -196,52 +204,53 @@ private int mergeFW(int p, int a, int m, int b, boolean fwEq) { private int inPlaceMergeFW(int a, int m, int b, boolean fwEq) { int i = a, j = m, k; - while(i < j && j < b) { - if(Reads.compareValues(array[i], array[j]) > (fwEq ? 0 : -1)) { - k = fwEq ? this.leftBinSearch(j+1, b, array[i]) - : this.rightBinSearch(j+1, b, array[i]); + while (i < j && j < b) { + if (Reads.compareValues(array[i], array[j]) > (fwEq ? 0 : -1)) { + k = fwEq ? this.leftBinSearch(j + 1, b, array[i]) + : this.rightBinSearch(j + 1, b, array[i]); this.rotate(i, j, k); - i += k-j; + i += k - j; j = k; - } - else i++; + } else + i++; } return i; } + private void inPlaceMergeBW(int a, int m, int b, boolean fwEq) { - int i = m-1, j = b-1, k; + int i = m - 1, j = b - 1, k; - while(j > i && i >= a){ - if(Reads.compareValues(array[i], array[j]) > (fwEq ? 0 : -1)) { + while (j > i && i >= a) { + if (Reads.compareValues(array[i], array[j]) > (fwEq ? 0 : -1)) { k = fwEq ? this.rightBinSearch(a, i, array[j]) - : this.leftBinSearch(a, i, array[j]); + : this.leftBinSearch(a, i, array[j]); - this.rotate(k, i+1, j+1); + this.rotate(k, i + 1, j + 1); - j -= (i+1)-k; - i = k-1; - } - else j--; + j -= (i + 1) - k; + i = k - 1; + } else + j--; } } private int findKeys(int a, int b, int n) { - int p = a, nKeys = 1, pEnd = a+nKeys; + int p = a, nKeys = 1, pEnd = a + nKeys; Highlights.clearMark(2); - for(int i = pEnd; i < b && nKeys < n; i++) { + for (int i = pEnd; i < b && nKeys < n; i++) { Highlights.markArray(1, i); Delays.sleep(1); int loc = this.leftBinSearch(p, pEnd, array[i]); - if(pEnd == loc || Reads.compareValues(array[i], array[loc]) != 0) { + if (pEnd == loc || Reads.compareValues(array[i], array[loc]) != 0) { this.rotate(p, pEnd, i); - int inc = i-pEnd; - loc += inc; - p += inc; + int inc = i - pEnd; + loc += inc; + p += inc; pEnd += inc; this.insertTo(pEnd, loc); @@ -254,120 +263,131 @@ private int findKeys(int a, int b, int n) { } private void blockSelect(int a, int b, int t, int bLen) { - for(int j = a; j < b; j += bLen) { + for (int j = a; j < b; j += bLen) { int min = j; - for(int i = min+bLen; i < b; i += bLen) { + for (int i = min + bLen; i < b; i += bLen) { int cmp = Reads.compareValues(array[i], array[min]); - if(cmp < 0 || (cmp == 0 && Reads.compareValues(array[t+(i-a)/bLen], array[t+(min-a)/bLen]) < 0)) + if (cmp < 0 || (cmp == 0 + && Reads.compareValues(array[t + (i - a) / bLen], array[t + (min - a) / bLen]) < 0)) min = i; } - if(min != j) { + if (min != j) { this.multiSwap(j, min, bLen); - Writes.swap(array, t+(j-a)/bLen, t+(min-a)/bLen, 1, true, false); + Writes.swap(array, t + (j - a) / bLen, t + (min - a) / bLen, 1, true, false); } } } private void blockMerge(int t, int a, int m, int b, int bLen) { - int a1 = a+(m-a)%bLen; - int b1 = b-(b-m)%bLen; - int i = a1, l = i-bLen, r = m; + int a1 = a + (m - a) % bLen; + int b1 = b - (b - m) % bLen; + int i = a1, l = i - bLen, r = m; - int mKey = array[t+(m-i)/bLen]; + int mKey = array[t + (m - i) / bLen]; int f = a; boolean frag = true; this.blockSelect(a1, b1, t, bLen); - while(l < m && r < b1) { + while (l < m && r < b1) { boolean curr = Reads.compareValues(array[t++], mKey) < 0; - if(frag != curr) { - f = this.mergeFW(f-bLen, f, i, i+bLen, frag); + if (frag != curr) { + f = this.mergeFW(f - bLen, f, i, i + bLen, frag); - if(f < i) { - this.shiftBW(f, i, i+bLen); + if (f < i) { + this.shiftBW(f, i, i + bLen); f += bLen; - } - else frag = curr; + } else + frag = curr; - if(frag) r += bLen; - else l += bLen; - } - else { - this.shiftFW(f-bLen, f, i); + if (frag) + r += bLen; + else + l += bLen; + } else { + this.shiftFW(f - bLen, f, i); f = i; - if(frag) l += bLen; - else r += bLen; + if (frag) + l += bLen; + else + r += bLen; } i += bLen; } - if(l < m) { - f = this.mergeFW(f-bLen, f, b1, b, true); - if(f >= b1) this.shiftFW(f-bLen, f, b); - } - else this.shiftFW(f-bLen, f, b); + if (l < m) { + f = this.mergeFW(f - bLen, f, b1, b, true); + if (f >= b1) + this.shiftFW(f - bLen, f, b); + } else + this.shiftFW(f - bLen, f, b); } + private void blockMergeFewKeys(int t, int a, int m, int b, int bLen) { - int a1 = a+(m-a)%bLen; - int b1 = b-(b-m)%bLen; - int i = a1, l = i-bLen, r = m; + int a1 = a + (m - a) % bLen; + int b1 = b - (b - m) % bLen; + int i = a1, l = i - bLen, r = m; - int mKey = array[t+(m-i)/bLen]; + int mKey = array[t + (m - i) / bLen]; int f = a; boolean frag = true; this.blockSelect(a1, b1, t, bLen); - while(l < m && r < b1) { + while (l < m && r < b1) { boolean curr = Reads.compareValues(array[t++], mKey) < 0; - if(frag != curr) { + if (frag != curr) { boolean tmp = frag; - if(f == i || Reads.compareValues(array[i-1], array[i+bLen-1]) < (frag ? 1 : 0)) + if (f == i || Reads.compareValues(array[i - 1], array[i + bLen - 1]) < (frag ? 1 : 0)) frag = curr; - f = this.inPlaceMergeFW(f, i, i+bLen, tmp); + f = this.inPlaceMergeFW(f, i, i + bLen, tmp); - if(frag) r += bLen; - else l += bLen; - } - else { + if (frag) + r += bLen; + else + l += bLen; + } else { f = i; - if(frag) l += bLen; - else r += bLen; + if (frag) + l += bLen; + else + r += bLen; } i += bLen; } - if(l < m) this.inPlaceMergeBW(f, b1, b, true); + if (l < m) + this.inPlaceMergeBW(f, b1, b, true); } private void redistFW(int a, int m, int b) { this.binaryInsertion(a, m); this.inPlaceMergeFW(a, m, b, true); } + private void redistBW(int a, int m, int b) { this.binaryInsertion(m, b); this.inPlaceMergeBW(a, m, b, false); } private void lazyStableSort(int a, int b) { - if(b-a <= 16) { + if (b - a <= 16) { this.binaryInsertion(a, b); return; } - int m = (a+b)/2; + int m = (a + b) / 2; - LazyStableSort left = new LazyStableSort(a, m); + LazyStableSort left = new LazyStableSort(a, m); LazyStableSort right = new LazyStableSort(m, b); left.start(); right.start(); @@ -375,8 +395,7 @@ private void lazyStableSort(int a, int b) { try { left.join(); right.join(); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } @@ -384,26 +403,27 @@ private void lazyStableSort(int a, int b) { } private void grailCommonSort(int a, int b, int nKeys) { - int len = b-a; + int len = b - a; - if(len <= 16) { + if (len <= 16) { this.binaryInsertion(a, b); return; } int bLen = sqrt(len); - int tLen = len/bLen; + int tLen = len / bLen; - int idl = bLen+tLen; + int idl = bLen + tLen; boolean strat1 = nKeys >= idl; - if(!strat1) idl = nKeys; + if (!strat1) + idl = nKeys; int keys = this.findKeys(a, b, idl); - int a1 = a+keys; - int m = (a1+b)/2; + int a1 = a + keys; + int m = (a1 + b) / 2; - if(strat1 && keys == idl) { - GrailCommonSort left = new GrailCommonSort(a1, m, keys); + if (strat1 && keys == idl) { + GrailCommonSort left = new GrailCommonSort(a1, m, keys); GrailCommonSort right = new GrailCommonSort(m, b, keys); left.start(); right.start(); @@ -411,32 +431,29 @@ private void grailCommonSort(int a, int b, int nKeys) { try { left.join(); right.join(); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } this.blockMerge(a, a1, m, b, bLen); - m = this.leftBinSearch(a+tLen, b-bLen, array[a+tLen-1]); + m = this.leftBinSearch(a + tLen, b - bLen, array[a + tLen - 1]); - RedistFW kBuf = new RedistFW(a, a+tLen, m); - RedistBW mBuf = new RedistBW(m, b-bLen, b); + RedistFW kBuf = new RedistFW(a, a + tLen, m); + RedistBW mBuf = new RedistBW(m, b - bLen, b); kBuf.start(); mBuf.start(); try { kBuf.join(); mBuf.join(); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } - } - else if(keys > 4) { - bLen = (b-a1-1)/(keys-keys%2)+1; + } else if (keys > 4) { + bLen = (b - a1 - 1) / (keys - keys % 2) + 1; - GrailCommonSort left = new GrailCommonSort(a1, m, keys); + GrailCommonSort left = new GrailCommonSort(a1, m, keys); GrailCommonSort right = new GrailCommonSort(m, b, keys); left.start(); right.start(); @@ -444,20 +461,19 @@ else if(keys > 4) { try { left.join(); right.join(); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } this.blockMergeFewKeys(a, a1, m, b, bLen); this.redistFW(a, a1, b); - } - else if(keys > 1) this.lazyStableSort(a, b); + } else if (keys > 1) + this.lazyStableSort(a, b); } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { this.array = array; this.grailCommonSort(0, length, 46341); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/RemiSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/RemiSort.java index e135528f..ed3ce7bd 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/RemiSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/RemiSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.MultiWayMergeSorting; /* @@ -28,33 +29,25 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Remi") public final class RemiSort extends MultiWayMergeSorting { public RemiSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Remi"); - this.setRunAllSortsName("Remi Sort"); - this.setRunSortName("Remisort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - //stable sorting algorithm that guarantees worst case performance of - //O(n log n) comparisons and O(n) moves in O(n^2/3) memory + // stable sorting algorithm that guarantees worst case performance of + // O(n log n) comparisons and O(n) moves in O(n^2/3) memory private int ceilCbrt(int n) { int a = 0, b = Math.min(1291, n); - while(a < b) { - int m = (a+b)/2; + while (a < b) { + int m = (a + b) / 2; - if(m*m*m >= n) b = m; - else a = m+1; + if (m * m * m >= n) + b = m; + else + a = m + 1; } return a; @@ -63,23 +56,24 @@ private int ceilCbrt(int n) { private void siftDown(int[] array, int[] keys, int r, int len, int a, int t) { int j = r; - while(2*j + 1 < len) { - j = 2*j + 1; + while (2 * j + 1 < len) { + j = 2 * j + 1; - if(j+1 < len) { - int cmp = Reads.compareIndices(array, a+keys[j+1], a+keys[j], 0.2, true); + if (j + 1 < len) { + int cmp = Reads.compareIndices(array, a + keys[j + 1], a + keys[j], 0.2, true); - if(cmp > 0 || (cmp == 0 && Reads.compareOriginalValues(keys[j+1], keys[j]) > 0)) j++; + if (cmp > 0 || (cmp == 0 && Reads.compareOriginalValues(keys[j + 1], keys[j]) > 0)) + j++; } } - for(int cmp = Reads.compareIndices(array, a+t, a+keys[j], 0.2, true); + for (int cmp = Reads.compareIndices(array, a + t, a + keys[j], 0.2, true); - cmp > 0 || (cmp == 0 && Reads.compareOriginalValues(t, keys[j]) > 0); + cmp > 0 || (cmp == 0 && Reads.compareOriginalValues(t, keys[j]) > 0); - j = (j-1)/2, - cmp = Reads.compareIndices(array, a+t, a+keys[j], 0.2, true)); + j = (j - 1) / 2, cmp = Reads.compareIndices(array, a + t, a + keys[j], 0.2, true)) + ; - for(int t2; j > r; j = (j-1)/2) { + for (int t2; j > r; j = (j - 1) / 2) { t2 = keys[j]; Highlights.markArray(3, j); Writes.write(keys, j, t, 0.2, false, true); @@ -90,12 +84,12 @@ private void siftDown(int[] array, int[] keys, int r, int len, int a, int t) { } private void tableSort(int[] array, int[] keys, int a, int b) { - int len = b-a; + int len = b - a; - for(int i = (len-1)/2; i >= 0; i--) + for (int i = (len - 1) / 2; i >= 0; i--) this.siftDown(array, keys, i, len, a, keys[i]); - for(int i = len-1; i > 0; i--) { + for (int i = len - 1; i > 0; i--) { int t = keys[i]; Highlights.markArray(3, i); Writes.write(keys, i, keys[0], 1, false, true); @@ -103,22 +97,21 @@ private void tableSort(int[] array, int[] keys, int a, int b) { } Highlights.clearMark(3); - for(int i = 0; i < len; i++) { + for (int i = 0; i < len; i++) { Highlights.markArray(2, i); - if(Reads.compareOriginalValues(i, keys[i]) != 0) { - int t = array[a+i]; + if (Reads.compareOriginalValues(i, keys[i]) != 0) { + int t = array[a + i]; int j = i, next = keys[i]; do { - Writes.write(array, a+j, array[a+next], 1, true, false); + Writes.write(array, a + j, array[a + next], 1, true, false); Writes.write(keys, j, j, 1, true, true); j = next; next = keys[next]; - } - while(Reads.compareOriginalValues(next, i) != 0); + } while (Reads.compareOriginalValues(next, i) != 0); - Writes.write(array, a+j, t, 1, true, false); + Writes.write(array, a + j, t, 1, true, false); Writes.write(keys, j, j, 1, true, true); } } @@ -126,49 +119,51 @@ private void tableSort(int[] array, int[] keys, int a, int b) { } private void blockCycle(int[] array, int[] buf, int[] keys, int a, int bLen, int bCnt) { - for(int i = 0; i < bCnt; i++) { - if(Reads.compareOriginalValues(i, keys[i]) != 0) { - Writes.arraycopy(array, a + i*bLen, buf, 0, bLen, 1, true, true); + for (int i = 0; i < bCnt; i++) { + if (Reads.compareOriginalValues(i, keys[i]) != 0) { + Writes.arraycopy(array, a + i * bLen, buf, 0, bLen, 1, true, true); int j = i, next = keys[i]; do { - Writes.arraycopy(array, a + next*bLen, array, a + j*bLen, bLen, 1, true, false); + Writes.arraycopy(array, a + next * bLen, array, a + j * bLen, bLen, 1, true, false); Writes.write(keys, j, j, 1, true, true); j = next; next = keys[next]; - } - while(Reads.compareOriginalValues(next, i) != 0); + } while (Reads.compareOriginalValues(next, i) != 0); - Writes.arraycopy(buf, 0, array, a + j*bLen, bLen, 1, true, false); + Writes.arraycopy(buf, 0, array, a + j * bLen, bLen, 1, true, false); Writes.write(keys, j, j, 1, true, true); } } } - private void kWayMerge(int[] array, int[] buf, int[] keys, int[] heap, int b, int[] pa, int[] p, int bLen, int rLen) { + + private void kWayMerge(int[] array, int[] buf, int[] keys, int[] heap, int b, int[] pa, int[] p, int bLen, + int rLen) { int k = p.length, size = k, a = pa[0], a1 = pa[1]; - for(int i = 0; i < k; i++) + for (int i = 0; i < k; i++) Writes.write(heap, i, i, 0, false, true); - for(int i = (k-1)/2; i >= 0; i--) + for (int i = (k - 1) / 2; i >= 0; i--) this.siftDown(array, heap, pa, heap[i], i, k); - for(int i = 0; i < rLen; i++) { + for (int i = 0; i < rLen; i++) { int min = heap[0]; Highlights.markArray(2, pa[min]); Writes.write(buf, i, array[pa[min]], 0, false, true); - Writes.write(pa, min, pa[min]+1, 1, false, true); + Writes.write(pa, min, pa[min] + 1, 1, false, true); - if(pa[min] == Math.min(a + (min+1)*rLen, b)) + if (pa[min] == Math.min(a + (min + 1) * rLen, b)) this.siftDown(array, heap, pa, heap[--size], 0, size); else this.siftDown(array, heap, pa, heap[0], 0, size); } int t = 0, cnt = 0, c = 0; - while(pa[c]-p[c] < bLen) c++; + while (pa[c] - p[c] < bLen) + c++; do { int min = heap[0]; @@ -177,49 +172,51 @@ private void kWayMerge(int[] array, int[] buf, int[] keys, int[] heap, int b, in Highlights.markArray(3, p[c]); Writes.write(array, p[c], array[pa[min]], 0, false, false); - Writes.write(pa, min, pa[min]+1, 0, false, true); - Writes.write(p, c, p[c]+1, 1, false, true); + Writes.write(pa, min, pa[min] + 1, 0, false, true); + Writes.write(p, c, p[c] + 1, 1, false, true); - if(pa[min] == Math.min(a + (min+1)*rLen, b)) + if (pa[min] == Math.min(a + (min + 1) * rLen, b)) this.siftDown(array, heap, pa, heap[--size], 0, size); else this.siftDown(array, heap, pa, heap[0], 0, size); - if(++cnt == bLen) { - Writes.write(keys, t++, (c > 0) ? p[c]/bLen-bLen-1 : -1, 0, false, true); + if (++cnt == bLen) { + Writes.write(keys, t++, (c > 0) ? p[c] / bLen - bLen - 1 : -1, 0, false, true); c = cnt = 0; - while(pa[c]-p[c] < bLen) c++; + while (pa[c] - p[c] < bLen) + c++; } - } - while(size > 0); + } while (size > 0); Highlights.clearAllMarks(); - while(cnt-- > 0) { - Writes.write(p, c, p[c]-1, 0, false, true); + while (cnt-- > 0) { + Writes.write(p, c, p[c] - 1, 0, false, true); Writes.write(array, --b, array[p[c]], 1, true, false); } - Writes.write(pa, k-1, b, 0, false, true); - Writes.write(keys, keys.length-1, -1, 0, false, true); + Writes.write(pa, k - 1, b, 0, false, true); + Writes.write(keys, keys.length - 1, -1, 0, false, true); t = 0; - while(keys[t] != -1) t++; + while (keys[t] != -1) + t++; - for(int i = 1, j = a; j < p[0]; i++) { - while(p[i] < pa[i]) { - Writes.write(keys, t++, p[i]/bLen-bLen, 0, false, true); - while(keys[t] != -1) t++; + for (int i = 1, j = a; j < p[0]; i++) { + while (p[i] < pa[i]) { + Writes.write(keys, t++, p[i] / bLen - bLen, 0, false, true); + while (keys[t] != -1) + t++; Writes.arraycopy(array, j, array, p[i], bLen, 1, true, false); - Writes.write(p, i, p[i]+bLen, 0, false, true); + Writes.write(p, i, p[i] + bLen, 0, false, true); j += bLen; } } Writes.arraycopy(buf, 0, array, a, rLen, 1, true, false); - this.blockCycle(array, buf, keys, a1, bLen, (b-a1)/bLen); + this.blockCycle(array, buf, keys, a1, bLen, (b - a1) / bLen); } @Override @@ -227,13 +224,13 @@ public void runSort(int[] array, int length, int bucketCount) { int a = 0, b = length; int bLen = this.ceilCbrt(length); - int rLen = bLen*bLen; - int rCnt = (length-1)/rLen + 1; + int rLen = bLen * bLen; + int rCnt = (length - 1) / rLen + 1; - if(rCnt < 2) { + if (rCnt < 2) { int[] keys = Writes.createExternalArray(length); - for(int i = 0; i < keys.length; i++) + for (int i = 0; i < keys.length; i++) Writes.write(keys, i, i, 1, true, true); this.tableSort(array, keys, a, b); @@ -243,20 +240,20 @@ public void runSort(int[] array, int length, int bucketCount) { } int[] keys = Writes.createExternalArray(rLen); - int[] buf = Writes.createExternalArray(rLen); + int[] buf = Writes.createExternalArray(rLen); int[] heap = new int[rCnt]; - int[] p = new int[rCnt]; - int[] pa = new int[rCnt]; + int[] p = new int[rCnt]; + int[] pa = new int[rCnt]; - int alloc = 3*rCnt; + int alloc = 3 * rCnt; Writes.changeAllocAmount(alloc); - for(int i = 0; i < keys.length; i++) + for (int i = 0; i < keys.length; i++) Writes.write(keys, i, i, 1, true, true); - for(int i = a, j = 0; i < b; i += rLen, j++) { - this.tableSort(array, keys, i, Math.min(i+rLen, b)); + for (int i = a, j = 0; i < b; i += rLen, j++) { + this.tableSort(array, keys, i, Math.min(i + rLen, b)); Writes.write(pa, j, i, 0, false, true); } Writes.arraycopy(pa, 0, p, 0, rCnt, 0, false, true); diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/SqrtSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/SqrtSort.java index bc443103..cb572f85 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/SqrtSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/SqrtSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.InsertionSort; import io.github.arrayv.sorts.templates.Sort; @@ -60,23 +61,12 @@ protected int getLeftOverFrag() { } } +@SortMeta(name = "Sqrt") public final class SqrtSort extends Sort { private InsertionSort insertSorter; public SqrtSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Sqrt"); - //this.setRunAllID("Square Root Sort (Block Merge Sort)"); - //this.setRunAllSortsName("Square Root Sort [Block Merge Sort]"); - this.setRunAllSortsName("Sqrtsort"); - this.setRunSortName("Sqrtsort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void sqrtSwap(int[] arr, int a, int b, boolean auxwrite) { @@ -85,7 +75,7 @@ private void sqrtSwap(int[] arr, int a, int b, boolean auxwrite) { } private void sqrtMultiSwap(int[] arr, int a, int b, int swapsLeft, boolean auxwrite) { - while(swapsLeft != 0) { + while (swapsLeft != 0) { this.sqrtSwap(arr, a++, b++, auxwrite); swapsLeft--; } @@ -100,20 +90,20 @@ private void sqrtMergeRight(int[] arr, int pos, int leftLen, int rightLen, int d int right = leftLen + rightLen - 1; int left = leftLen - 1; - while(left >= 0) { + while (left >= 0) { Highlights.markArray(2, pos + left); Highlights.markArray(3, pos + right); - if(right < leftLen || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { + if (right < leftLen || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { Writes.write(arr, pos + (mergedPos--), arr[pos + (left--)], 1, true, auxwrite); - } - else Writes.write(arr, pos + (mergedPos--), arr[pos + (right--)], 1, true, auxwrite); + } else + Writes.write(arr, pos + (mergedPos--), arr[pos + (right--)], 1, true, auxwrite); } Highlights.clearMark(3); - if(right != mergedPos) { - while(right >= leftLen) { + if (right != mergedPos) { + while (right >= leftLen) { Writes.write(arr, pos + (mergedPos--), arr[pos + (right--)], 1, true, auxwrite); Highlights.markArray(2, pos + right); } @@ -122,18 +112,19 @@ private void sqrtMergeRight(int[] arr, int pos, int leftLen, int rightLen, int d Highlights.clearMark(2); } - // arr[dist..-1] - free, arr[0, leftEnd - 1] ++ arr[leftEnd, leftEnd + rightEnd - 1] + // arr[dist..-1] - free, arr[0, leftEnd - 1] ++ arr[leftEnd, leftEnd + rightEnd + // - 1] // -> arr[dist, dist + leftEnd + rightEnd - 1] private void sqrtMergeLeftWithXBuf(int[] arr, int pos, int leftEnd, int rightEnd, int dist, boolean auxwrite) { int left = 0; int right = leftEnd; rightEnd += leftEnd; - while(right < rightEnd) { - if(left == leftEnd || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { + while (right < rightEnd) { + if (left == leftEnd || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { Writes.write(arr, pos + dist++, arr[pos + right++], 1, true, auxwrite); - } - else Writes.write(arr, pos + dist++, arr[pos + left++], 1, true, auxwrite); + } else + Writes.write(arr, pos + dist++, arr[pos + left++], 1, true, auxwrite); Highlights.markArray(2, pos + left); Highlights.markArray(3, pos + right); @@ -141,8 +132,8 @@ private void sqrtMergeLeftWithXBuf(int[] arr, int pos, int leftEnd, int rightEnd Highlights.clearMark(3); - if(dist != left) { - while(left < leftEnd) { + if (dist != left) { + while (left < leftEnd) { Writes.write(arr, pos + dist++, arr[pos + left++], 1, true, auxwrite); Highlights.markArray(2, pos + left); } @@ -151,16 +142,17 @@ private void sqrtMergeLeftWithXBuf(int[] arr, int pos, int leftEnd, int rightEnd Highlights.clearMark(2); } - // arr[0,L1-1] ++ arr2[0,L2-1] -> arr[-L1,L2-1], arr2 is "before" arr1 - private void sqrtMergeDown(int[] arr, int arrPos, int[] buffer, int bufPos, int leftLen, int rightLen, boolean auxwrite) { + // arr[0,L1-1] ++ arr2[0,L2-1] -> arr[-L1,L2-1], arr2 is "before" arr1 + private void sqrtMergeDown(int[] arr, int arrPos, int[] buffer, int bufPos, int leftLen, int rightLen, + boolean auxwrite) { int arrMerge = 0, bufMerge = 0; int dist = 0 - rightLen; - while(bufMerge < rightLen) { - if(arrMerge == leftLen || Reads.compareValues(arr[arrPos + arrMerge], buffer[bufPos + bufMerge]) >= 0) { + while (bufMerge < rightLen) { + if (arrMerge == leftLen || Reads.compareValues(arr[arrPos + arrMerge], buffer[bufPos + bufMerge]) >= 0) { Writes.write(arr, arrPos + dist++, buffer[bufPos + bufMerge++], 1, true, auxwrite); - } - else Writes.write(arr, arrPos + dist++, arr[arrPos + arrMerge++], 1, true, auxwrite); + } else + Writes.write(arr, arrPos + dist++, arr[arrPos + arrMerge++], 1, true, auxwrite); Highlights.markArray(2, arrPos + arrMerge); Highlights.markArray(3, bufPos + bufMerge); @@ -168,8 +160,8 @@ private void sqrtMergeDown(int[] arr, int arrPos, int[] buffer, int bufPos, int Highlights.clearMark(3); - if(dist != arrMerge) { - while(arrMerge < leftLen) { + if (dist != arrMerge) { + while (arrMerge < leftLen) { Writes.write(arr, arrPos + dist++, arr[arrPos + arrMerge++], 1, true, auxwrite); Highlights.markArray(2, arrPos + arrMerge); } @@ -178,16 +170,17 @@ private void sqrtMergeDown(int[] arr, int arrPos, int[] buffer, int bufPos, int Highlights.clearMark(2); } - //returns the leftover length, then the leftover fragment - private SqrtState sqrtSmartMergeWithXBuf(int[] arr, int pos, int leftOverLen, int leftOverFrag, int blockLen, boolean auxwrite) { + // returns the leftover length, then the leftover fragment + private SqrtState sqrtSmartMergeWithXBuf(int[] arr, int pos, int leftOverLen, int leftOverFrag, int blockLen, + boolean auxwrite) { int dist = 0 - blockLen, left = 0, right = leftOverLen, leftEnd = right, rightEnd = right + blockLen; - int typeFrag = 1 - leftOverFrag; // 1 if inverted + int typeFrag = 1 - leftOverFrag; // 1 if inverted - while(left < leftEnd && right < rightEnd) { - if(Reads.compareValues(arr[pos + left], arr[pos + right]) - typeFrag < 0) { + while (left < leftEnd && right < rightEnd) { + if (Reads.compareValues(arr[pos + left], arr[pos + right]) - typeFrag < 0) { Writes.write(arr, pos + dist++, arr[pos + left++], 1, true, auxwrite); - } - else Writes.write(arr, pos + dist++, arr[pos + right++], 1, true, auxwrite); + } else + Writes.write(arr, pos + dist++, arr[pos + right++], 1, true, auxwrite); Highlights.markArray(2, pos + left); Highlights.markArray(3, pos + right); @@ -197,15 +190,14 @@ private SqrtState sqrtSmartMergeWithXBuf(int[] arr, int pos, int leftOverLen, in int length, fragment = leftOverFrag; - if(left < leftEnd) { + if (left < leftEnd) { length = leftEnd - left; - while(left < leftEnd) { + while (left < leftEnd) { Writes.write(arr, pos + --rightEnd, arr[pos + --leftEnd], 1, true, auxwrite); Highlights.markArray(2, pos + leftEnd); } - } - else { + } else { length = rightEnd - right; fragment = typeFrag; } @@ -216,15 +208,20 @@ private SqrtState sqrtSmartMergeWithXBuf(int[] arr, int pos, int leftOverLen, in } // arr - starting array. arr[0 - regBlockLen..-1] - buffer (if havebuf). - // regBlockLen - length of regular blocks. First blockCount blocks are stable sorted by 1st elements and key-coded - // keysPos - where keys are in array, in same order as blocks. keysPos < midkey means stream A + // regBlockLen - length of regular blocks. First blockCount blocks are stable + // sorted by 1st elements and key-coded + // keysPos - where keys are in array, in same order as blocks. keysPos < midkey + // means stream A // aBlockCount are regular blocks from stream A. - // lastLen is length of last (irregular) block from stream B, that should go before aCountBlock blocks. - // lastLen = 0 requires aBlockCount = 0 (no irregular blocks). lastLen > 0, aBlockCount = 0 is possible. - private void sqrtMergeBuffersLeftWithXBuf(int[] keys, int midkey, int[] arr, int pos, int blockCount, int regBlockLen, - int aBlockCount, int lastLen, boolean auxwrite) { - - if(blockCount == 0) { + // lastLen is length of last (irregular) block from stream B, that should go + // before aCountBlock blocks. + // lastLen = 0 requires aBlockCount = 0 (no irregular blocks). lastLen > 0, + // aBlockCount = 0 is possible. + private void sqrtMergeBuffersLeftWithXBuf(int[] keys, int midkey, int[] arr, int pos, int blockCount, + int regBlockLen, + int aBlockCount, int lastLen, boolean auxwrite) { + + if (blockCount == 0) { int aBlocksLen = aBlockCount * regBlockLen; this.sqrtMergeLeftWithXBuf(arr, pos, aBlocksLen, lastLen, 0 - regBlockLen, auxwrite); return; @@ -236,18 +233,19 @@ private void sqrtMergeBuffersLeftWithXBuf(int[] keys, int midkey, int[] arr, int int restToProcess; - for(int keyIndex = 1; keyIndex < blockCount; keyIndex++, processIndex += regBlockLen) { + for (int keyIndex = 1; keyIndex < blockCount; keyIndex++, processIndex += regBlockLen) { restToProcess = processIndex - leftOverLen; int nextFrag = Reads.compareOriginalValues(keys[keyIndex], midkey) < 0 ? 0 : 1; - if(nextFrag == leftOverFrag) { - Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, auxwrite); + if (nextFrag == leftOverFrag) { + Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, + auxwrite); restToProcess = processIndex; leftOverLen = regBlockLen; - } - else { - SqrtState results = this.sqrtSmartMergeWithXBuf(arr, pos + restToProcess, leftOverLen, leftOverFrag, regBlockLen, auxwrite); + } else { + SqrtState results = this.sqrtSmartMergeWithXBuf(arr, pos + restToProcess, leftOverLen, leftOverFrag, + regBlockLen, auxwrite); leftOverLen = results.getLeftOverLen(); leftOverFrag = results.getLeftOverFrag(); @@ -256,57 +254,60 @@ private void sqrtMergeBuffersLeftWithXBuf(int[] keys, int midkey, int[] arr, int restToProcess = processIndex - leftOverLen; - if(lastLen != 0) { - if(leftOverFrag != 0) { - Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, auxwrite); + if (lastLen != 0) { + if (leftOverFrag != 0) { + Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, + auxwrite); restToProcess = processIndex; leftOverLen = regBlockLen * aBlockCount; leftOverFrag = 0; - } - else { + } else { leftOverLen += regBlockLen * aBlockCount; } this.sqrtMergeLeftWithXBuf(arr, pos + restToProcess, leftOverLen, lastLen, 0 - regBlockLen, auxwrite); - } - else { - Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, auxwrite); + } else { + Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, + auxwrite); } } // build blocks of length buildLen // input: [-buildLen,-1] elements are buffer - // output: first buildLen elements are buffer, blocks 2 * buildLen and last subblock sorted + // output: first buildLen elements are buffer, blocks 2 * buildLen and last + // subblock sorted private void sqrtBuildBlocks(int[] arr, int pos, int len, int buildLen, boolean auxwrite) { int extraDist, part; - for(int dist = 1; dist < len; dist += 2) { + for (int dist = 1; dist < len; dist += 2) { extraDist = 0; - if(Reads.compareValues(arr[pos + (dist - 1)], arr[pos + dist]) > 0) extraDist = 1; + if (Reads.compareValues(arr[pos + (dist - 1)], arr[pos + dist]) > 0) + extraDist = 1; Writes.write(arr, pos + dist - 3, arr[pos + dist - 1 + extraDist], 1, true, auxwrite); Writes.write(arr, pos + dist - 2, arr[pos + dist - extraDist], 1, true, auxwrite); } - if(len % 2 != 0) Writes.write(arr, pos + len - 3, arr[pos + len - 1], 1, true, auxwrite); + if (len % 2 != 0) + Writes.write(arr, pos + len - 3, arr[pos + len - 1], 1, true, auxwrite); pos -= 2; - for(part = 2; part < buildLen; part *= 2) { + for (part = 2; part < buildLen; part *= 2) { int left = 0; int right = len - 2 * part; - while(left <= right) { + while (left <= right) { this.sqrtMergeLeftWithXBuf(arr, pos + left, part, part, 0 - part, auxwrite); left += 2 * part; } int rest = len - left; - if(rest > part) { + if (rest > part) { this.sqrtMergeLeftWithXBuf(arr, pos + left, part, rest - part, 0 - part, auxwrite); - } - else { - while(left < len) Writes.write(arr, pos + left - part, arr[pos + left++], 1, true, auxwrite); + } else { + while (left < len) + Writes.write(arr, pos + left - part, arr[pos + left++], 1, true, auxwrite); } pos -= part; @@ -314,82 +315,94 @@ private void sqrtBuildBlocks(int[] arr, int pos, int len, int buildLen, boolean int restToBuild = len % (2 * buildLen); int leftOverPos = len - restToBuild; - if(restToBuild <= buildLen) { + if (restToBuild <= buildLen) { Writes.arraycopy(arr, pos + leftOverPos, arr, pos + leftOverPos + buildLen, restToBuild, 1, true, auxwrite); - } - else this.sqrtMergeRight(arr, pos + leftOverPos, buildLen, restToBuild - buildLen, buildLen, auxwrite); + } else + this.sqrtMergeRight(arr, pos + leftOverPos, buildLen, restToBuild - buildLen, buildLen, auxwrite); - while(leftOverPos > 0) { + while (leftOverPos > 0) { leftOverPos -= 2 * buildLen; this.sqrtMergeRight(arr, pos + leftOverPos, buildLen, buildLen, buildLen, auxwrite); } } - // keys are on the left of arr. Blocks of length buildLen combined. We'll combine them in pairs - // buildLen and numKeys are powers of 2. (2 * buildLen / regBlockLen) keys are guaranteed - private void sqrtCombineBlocks(int[] arr, int pos, int len, int buildLen, int regBlockLen, int[] tags, boolean auxwrite) { + // keys are on the left of arr. Blocks of length buildLen combined. We'll + // combine them in pairs + // buildLen and numKeys are powers of 2. (2 * buildLen / regBlockLen) keys are + // guaranteed + private void sqrtCombineBlocks(int[] arr, int pos, int len, int buildLen, int regBlockLen, int[] tags, + boolean auxwrite) { int combineLen = len / (2 * buildLen); int leftOver = len % (2 * buildLen); - if(leftOver <= buildLen) { + if (leftOver <= buildLen) { len -= leftOver; leftOver = 0; } int leftIndex = 0; - for(int i = 0; i <= combineLen; i++) { - if(i == combineLen && leftOver == 0) break; + for (int i = 0; i <= combineLen; i++) { + if (i == combineLen && leftOver == 0) + break; int blockPos = pos + i * 2 * buildLen; int blockCount = (i == combineLen ? leftOver : 2 * buildLen) / regBlockLen; int tagIndex = blockCount + (i == combineLen ? 1 : 0); - for(int j = 0; j <= tagIndex; j++) Writes.write(tags, j, j, 1, true, true); + for (int j = 0; j <= tagIndex; j++) + Writes.write(tags, j, j, 1, true, true); int midkey = buildLen / regBlockLen; - for(tagIndex = 1; tagIndex < blockCount; tagIndex++) { + for (tagIndex = 1; tagIndex < blockCount; tagIndex++) { leftIndex = tagIndex - 1; - for(int rightIndex = tagIndex; rightIndex < blockCount; rightIndex++) { + for (int rightIndex = tagIndex; rightIndex < blockCount; rightIndex++) { int rightComp = Reads.compareValues(arr[blockPos + leftIndex * regBlockLen], - arr[blockPos + rightIndex * regBlockLen]); - if(rightComp > 0 || (rightComp == 0 && tags[leftIndex] > tags[rightIndex])) leftIndex = rightIndex; + arr[blockPos + rightIndex * regBlockLen]); + if (rightComp > 0 || (rightComp == 0 && tags[leftIndex] > tags[rightIndex])) + leftIndex = rightIndex; } - if(leftIndex != tagIndex - 1) { - this.sqrtMultiSwap(arr, blockPos + (tagIndex - 1) * regBlockLen, blockPos + leftIndex * regBlockLen, regBlockLen, auxwrite); + if (leftIndex != tagIndex - 1) { + this.sqrtMultiSwap(arr, blockPos + (tagIndex - 1) * regBlockLen, blockPos + leftIndex * regBlockLen, + regBlockLen, auxwrite); this.sqrtSwap(tags, tagIndex - 1, leftIndex, true); } } int aBlockCount = 0; int lastLen = 0; - if(i == combineLen) lastLen = leftOver % regBlockLen; + if (i == combineLen) + lastLen = leftOver % regBlockLen; - if(lastLen != 0) { - while(aBlockCount < blockCount && Reads.compareValues(arr[blockPos + blockCount * regBlockLen], + if (lastLen != 0) { + while (aBlockCount < blockCount && Reads.compareValues(arr[blockPos + blockCount * regBlockLen], arr[blockPos + (blockCount - aBlockCount - 1) * regBlockLen]) < 0) { aBlockCount++; } } - this.sqrtMergeBuffersLeftWithXBuf(tags, midkey, arr, blockPos, blockCount - aBlockCount, regBlockLen, aBlockCount, lastLen, auxwrite); + this.sqrtMergeBuffersLeftWithXBuf(tags, midkey, arr, blockPos, blockCount - aBlockCount, regBlockLen, + aBlockCount, lastLen, auxwrite); } - for(leftIndex = len - 1; leftIndex >= 0; leftIndex--) Writes.write(arr, pos + leftIndex, arr[pos + leftIndex - regBlockLen], 1, true, auxwrite); + for (leftIndex = len - 1; leftIndex >= 0; leftIndex--) + Writes.write(arr, pos + leftIndex, arr[pos + leftIndex - regBlockLen], 1, true, auxwrite); } - private void sqrtCommonSort(int[] arr, int pos, int len, int[] extBuf, int extBufPos, int[] tags, boolean auxwrite) { + private void sqrtCommonSort(int[] arr, int pos, int len, int[] extBuf, int extBufPos, int[] tags, + boolean auxwrite) { insertSorter = new InsertionSort(this.arrayVisualizer); - if(len <= 16) { + if (len <= 16) { this.sqrtInsertSort(arr, pos, len, auxwrite); Highlights.clearAllMarks(); return; } int blockLen = 1; - while((blockLen * blockLen) < len) blockLen *= 2; + while ((blockLen * blockLen) < len) + blockLen *= 2; Writes.arraycopy(arr, pos, extBuf, extBufPos, blockLen, 1, true, auxwrite); @@ -399,7 +412,7 @@ private void sqrtCommonSort(int[] arr, int pos, int len, int[] extBuf, int extBu int buildLen = blockLen; - while(len > (buildLen *= 2)) { + while (len > (buildLen *= 2)) { this.sqrtCombineBlocks(arr, pos + blockLen, len - blockLen, buildLen, blockLen, tags, auxwrite); } this.sqrtMergeDown(arr, pos + blockLen, extBuf, extBufPos, len - blockLen, blockLen, auxwrite); @@ -411,7 +424,8 @@ private void sqrtCommonSort(int[] arr, int pos, int len, int[] extBuf, int extBu public void runSort(int[] array, int len, int bucketCount) { int bufferLen = 1; - while(bufferLen * bufferLen < len) bufferLen *= 2; + while (bufferLen * bufferLen < len) + bufferLen *= 2; int numKeys = (len - 1) / bufferLen + 2; int[] extBuf = Writes.createExternalArray(bufferLen); diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/StacklessDualPivotQuickSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/StacklessDualPivotQuickSort.java index 862f3e53..437855eb 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/StacklessDualPivotQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/StacklessDualPivotQuickSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.BinaryInsertionSort; import io.github.arrayv.sorts.templates.Sort; @@ -29,52 +30,40 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Stackless Dual-Pivot Quick") public final class StacklessDualPivotQuickSort extends Sort { public StacklessDualPivotQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Stackless Dual-Pivot Quick"); - this.setRunAllSortsName("Stackless Dual-Pivot Quicksort"); - this.setRunSortName("Stackless Dual-Pivot Quicksort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private int partition(int[] array, int a, int b, int p) { - int m1 = (a+a+b)/3, m2 = (a+b+b)/3; + int m1 = (a + a + b) / 3, m2 = (a + b + b) / 3; - if(Reads.compareIndices(array, m1, m2, 1, true) > 0) { + if (Reads.compareIndices(array, m1, m2, 1, true) > 0) { Writes.swap(array, m1, a, 1, true, false); Writes.swap(array, m2, --b, 1, true, false); - } - else { + } else { Writes.swap(array, m2, a, 1, true, false); Writes.swap(array, m1, --b, 1, true, false); } int i = a, j = b; - for(int k = i+1; k < j; k++) { - if(Reads.compareValues(array[k], array[b]) < 0) + for (int k = i + 1; k < j; k++) { + if (Reads.compareValues(array[k], array[b]) < 0) Writes.swap(array, k, ++i, 1, true, false); - else if(Reads.compareValues(array[k], array[a]) >= 0) { + else if (Reads.compareValues(array[k], array[a]) >= 0) { do { j--; Highlights.markArray(3, j); Delays.sleep(1); - } - while(j > k && Reads.compareValues(array[j], array[a]) >= 0); + } while (j > k && Reads.compareValues(array[j], array[a]) >= 0); Writes.swap(array, k, j, 1, true, false); Highlights.clearMark(3); - if(Reads.compareValues(array[k], array[b]) < 0) + if (Reads.compareValues(array[k], array[b]) < 0) Writes.swap(array, k, ++i, 1, true, false); } } @@ -89,13 +78,13 @@ else if(Reads.compareValues(array[k], array[a]) >= 0) { } private int leftBinSearch(int[] array, int a, int b, int p) { - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; - if(Reads.compareIndices(array, p, m, 1, true) <= 0) + if (Reads.compareIndices(array, p, m, 1, true) <= 0) b = m; else - a = m+1; + a = m + 1; } return a; @@ -104,49 +93,52 @@ private int leftBinSearch(int[] array, int a, int b, int p) { private void quickSort(int[] array, int a, int b) { int max = array[a]; - for(int i = a+1; i < b; i++) { + for (int i = a + 1; i < b; i++) { Highlights.markArray(1, i); Delays.sleep(0.5); - if(Reads.compareValues(array[i], max) > 0) max = array[i]; + if (Reads.compareValues(array[i], max) > 0) + max = array[i]; } - for(int i = b-1; i >= 0; i--) { + for (int i = b - 1; i >= 0; i--) { Highlights.markArray(1, i); Delays.sleep(0.5); - if(Reads.compareValues(array[i], max) == 0) + if (Reads.compareValues(array[i], max) == 0) Writes.swap(array, i, --b, 1, true, false); } int b1 = b; - boolean med = true; //flag to improve pivot selection in the case of many similar elements + boolean med = true; // flag to improve pivot selection in the case of many similar elements BinaryInsertionSort smallSort = new BinaryInsertionSort(this.arrayVisualizer); do { - while(b1-a > 24) { - if(!med) Writes.swap(array, a, (a+a+b1)/3, 1, true, false); + while (b1 - a > 24) { + if (!med) + Writes.swap(array, a, (a + a + b1) / 3, 1, true, false); b1 = this.partition(array, a, b1, b); } smallSort.customBinaryInsert(array, a, b1, 0.25); - a = b1+1; - if(a >= b) { - if(a-1 < b) Writes.swap(array, a-1, b, 1, true, false); + a = b1 + 1; + if (a >= b) { + if (a - 1 < b) + Writes.swap(array, a - 1, b, 1, true, false); return; } - b1 = this.leftBinSearch(array, a, b, a-1); - Writes.swap(array, a-1, b, 1, true, false); + b1 = this.leftBinSearch(array, a, b, a - 1); + Writes.swap(array, a - 1, b, 1, true, false); med = true; - while(a < b1 && Reads.compareIndices(array, a-1, a, 0.5, true) == 0) { + while (a < b1 && Reads.compareIndices(array, a - 1, a, 0.5, true) == 0) { med = false; a++; } - if(a == b1) med = true; - } - while(true); + if (a == b1) + med = true; + } while (true); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/StacklessHybridQuickSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/StacklessHybridQuickSort.java index f301aee9..59f376a1 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/StacklessHybridQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/StacklessHybridQuickSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.BinaryInsertionSort; import io.github.arrayv.sorts.templates.Sort; @@ -29,32 +30,22 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Stackless Hybrid Quick") public final class StacklessHybridQuickSort extends Sort { public StacklessHybridQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Stackless Hybrid Quick"); - this.setRunAllSortsName("Stackless Hybrid Quicksort"); - this.setRunSortName("Stackless Hybrid Quicksort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void medianOfThree(int[] array, int a, int b) { - int m = a+(b-1-a)/2; + int m = a + (b - 1 - a) / 2; - if(Reads.compareIndices(array, a, m, 1, true) == 1) + if (Reads.compareIndices(array, a, m, 1, true) == 1) Writes.swap(array, a, m, 1, true, false); - if(Reads.compareIndices(array, m, b-1, 1, true) == 1) { - Writes.swap(array, m, b-1, 1, true, false); + if (Reads.compareIndices(array, m, b - 1, 1, true) == 1) { + Writes.swap(array, m, b - 1, 1, true, false); - if(Reads.compareIndices(array, a, m, 1, true) == 1) + if (Reads.compareIndices(array, a, m, 1, true) == 1) return; } @@ -72,34 +63,32 @@ private int partition(int[] array, int a, int b) { i++; Highlights.markArray(1, i); Delays.sleep(0.5); - } - while(i < j && Reads.compareIndices(array, i, a, 0, false) < 0); + } while (i < j && Reads.compareIndices(array, i, a, 0, false) < 0); do { j--; Highlights.markArray(2, j); Delays.sleep(0.5); - } - while(j >= i && Reads.compareIndices(array, j, a, 0, false) >= 0); + } while (j >= i && Reads.compareIndices(array, j, a, 0, false) >= 0); - if(i < j) Writes.swap(array, i, j, 1, true, false); + if (i < j) + Writes.swap(array, i, j, 1, true, false); else { Writes.swap(array, a, j, 1, true, false); Highlights.clearMark(3); return j; } - } - while(true); + } while (true); } private int leftBinSearch(int[] array, int a, int b, int p) { - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; - if(Reads.compareIndices(array, p, m, 1, true) <= 0) + if (Reads.compareIndices(array, p, m, 1, true) <= 0) b = m; else - a = m+1; + a = m + 1; } return a; @@ -108,27 +97,29 @@ private int leftBinSearch(int[] array, int a, int b, int p) { private void quickSort(int[] array, int a, int b) { int max = array[a]; - for(int i = a+1; i < b; i++) { + for (int i = a + 1; i < b; i++) { Highlights.markArray(1, i); Delays.sleep(0.5); - if(Reads.compareValues(array[i], max) > 0) max = array[i]; + if (Reads.compareValues(array[i], max) > 0) + max = array[i]; } - for(int i = b-1; i >= 0; i--) { + for (int i = b - 1; i >= 0; i--) { Highlights.markArray(1, i); Delays.sleep(0.5); - if(Reads.compareValues(array[i], max) == 0) + if (Reads.compareValues(array[i], max) == 0) Writes.swap(array, i, --b, 1, true, false); } int b1 = b; - boolean med = true; //flag to improve pivot selection in the case of many similar elements + boolean med = true; // flag to improve pivot selection in the case of many similar elements BinaryInsertionSort smallSort = new BinaryInsertionSort(this.arrayVisualizer); do { - while(b1-a > 16) { - if(med) this.medianOfThree(array, a, b1); + while (b1 - a > 16) { + if (med) + this.medianOfThree(array, a, b1); int p = this.partition(array, a, b1); Writes.swap(array, p, b, 1, true, false); @@ -137,23 +128,24 @@ private void quickSort(int[] array, int a, int b) { } smallSort.customBinaryInsert(array, a, b1, 0.25); - a = b1+1; - if(a >= b) { - if(a-1 < b) Writes.swap(array, a-1, b, 1, true, false); + a = b1 + 1; + if (a >= b) { + if (a - 1 < b) + Writes.swap(array, a - 1, b, 1, true, false); return; } - b1 = this.leftBinSearch(array, a, b, a-1); - Writes.swap(array, a-1, b, 1, true, false); + b1 = this.leftBinSearch(array, a, b, a - 1); + Writes.swap(array, a - 1, b, 1, true, false); med = true; - while(a < b1 && Reads.compareIndices(array, a-1, a, 0.5, true) == 0) { + while (a < b1 && Reads.compareIndices(array, a - 1, a, 0.5, true) == 0) { med = false; a++; } - if(a == b1) med = true; - } - while(true); + if (a == b1) + med = true; + } while (true); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/SynchronousSqrtSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/SynchronousSqrtSort.java index fc8b1a18..44654210 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/SynchronousSqrtSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/SynchronousSqrtSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BlockMergeSorting; /* @@ -28,159 +29,164 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Synchronous Sqrt") public final class SynchronousSqrtSort extends BlockMergeSorting { public SynchronousSqrtSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Synchronous Sqrt"); - this.setRunAllSortsName("Synchronous Sqrt Sort"); - this.setRunSortName("Synchronous Sqrtsort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private int smartMergeBW(int[] array, int a, int m, int b, int p, boolean rev) { - int i = m-1, j = b-1; + int i = m - 1, j = b - 1; int cmp = rev ? -1 : 0; - while(i >= a && j >= m) { + while (i >= a && j >= m) { Highlights.markArray(2, i); - if(Reads.compareValues(array[i], array[j]) > cmp) + if (Reads.compareValues(array[i], array[j]) > cmp) Writes.write(array, --p, array[i--], 1, true, false); else Writes.write(array, --p, array[j--], 1, true, false); } - return i+1; + return i + 1; } private void blockSelection(int[] array, int[] tags, int a, int b, int bLen, int t, int tj) { - for(int i = 0; i < Math.min(tj+1, tags.length-t); i++) - Writes.write(tags, t+i, i + (i <= tj/2 ? 0 : tags.length), 1, true, true); + for (int i = 0; i < Math.min(tj + 1, tags.length - t); i++) + Writes.write(tags, t + i, i + (i <= tj / 2 ? 0 : tags.length), 1, true, true); - for(int j = a, p = a; j < b-bLen; j+=bLen) { - int min = p == j ? j+bLen : j; + for (int j = a, p = a; j < b - bLen; j += bLen) { + int min = p == j ? j + bLen : j; - for(int i = min+bLen; i < b; i+=bLen) { - if(i != p) { + for (int i = min + bLen; i < b; i += bLen) { + if (i != p) { int cmp = Reads.compareValues(array[i], array[min]); - if(cmp == -1 || (cmp == 0 && Reads.compareOriginalValues(tags[t + (i-a)/bLen], tags[t + (min-a)/bLen]) == -1)) + if (cmp == -1 || (cmp == 0 + && Reads.compareOriginalValues(tags[t + (i - a) / bLen], tags[t + (min - a) / bLen]) == -1)) min = i; } } - if(min > j) { - if(p == j) { + if (min > j) { + if (p == j) { Writes.arraycopy(array, min, array, j, bLen, 1, true, false); - Writes.write(tags, t + (j-a)/bLen, tags[t + (min-a)/bLen], 1, true, false); + Writes.write(tags, t + (j - a) / bLen, tags[t + (min - a) / bLen], 1, true, false); p = min; - } - else { + } else { this.multiSwap(array, j, min, bLen); - Writes.swap(tags, t + (j-a)/bLen, t + (min-a)/bLen, 1, true, false); + Writes.swap(tags, t + (j - a) / bLen, t + (min - a) / bLen, 1, true, false); } } } } + private void mergeBlocksBW(int[] array, int[] tags, int a, int b, int ti, int tb, int bLen) { - int tj = tb-1, mkv = tags.length; - int f = b, a1 = f-bLen; + int tj = tb - 1, mkv = tags.length; + int f = b, a1 = f - bLen; boolean rev = Reads.compareOriginalValues(tags[tj], mkv) < 0; - while(true) { + while (true) { do { tj--; a1 -= bLen; - } - while(tj >= ti && (rev ? Reads.compareOriginalValues(tags[tj], mkv) < 0 - : Reads.compareOriginalValues(tags[tj], mkv) >= 0)); - if(tj < ti) { - this.shiftBWExt(array, a, f, f+bLen); + } while (tj >= ti && (rev ? Reads.compareOriginalValues(tags[tj], mkv) < 0 + : Reads.compareOriginalValues(tags[tj], mkv) >= 0)); + if (tj < ti) { + this.shiftBWExt(array, a, f, f + bLen); break; } - f = this.smartMergeBW(array, a1, a1+bLen, f, f+bLen, rev); + f = this.smartMergeBW(array, a1, a1 + bLen, f, f + bLen, rev); rev = !rev; } } @Override public void runSort(int[] array, int length, int bucketCount) { - if(length <= 16) { + if (length <= 16) { this.binaryInsertion(array, 0, length); return; } int bLen = 1; - while(bLen*bLen < length) bLen *= 2; - int mod = length%bLen; + while (bLen * bLen < length) + bLen *= 2; + int mod = length % bLen; - int a = bLen+mod, b = length, len = b-a; + int a = bLen + mod, b = length, len = b - a; int i, j = 1; - int[] temp = Writes.createExternalArray(bLen+mod); - int[] tags = Writes.createExternalArray((length-1)/bLen+1); + int[] temp = Writes.createExternalArray(bLen + mod); + int[] tags = Writes.createExternalArray((length - 1) / bLen + 1); this.binaryInsertion(array, 0, a); Writes.arraycopy(array, 0, temp, 0, a, 1, true, true); - for(; j < bLen; j *= 2) { + for (; j < bLen; j *= 2) { int p = Math.max(2, j); - for(i = a; i+2*j < b; i += 2*j) - this.mergeWithBufFWExt(array, i, i+j, i+2*j, i-p); + for (i = a; i + 2 * j < b; i += 2 * j) + this.mergeWithBufFWExt(array, i, i + j, i + 2 * j, i - p); - if(i+j < b) this.mergeWithBufFWExt(array, i, i+j, b, i-p); - else this.shiftFWExt(array, i-p, i, b); + if (i + j < b) + this.mergeWithBufFWExt(array, i, i + j, b, i - p); + else + this.shiftFWExt(array, i - p, i, b); - a -= p; b -= p; + a -= p; + b -= p; } - int p = len%(2*j); - i = b-p; + int p = len % (2 * j); + i = b - p; - if(i+j < b) this.mergeWithBufBWExt(array, i, i+j, b, b+j); - else this.shiftBWExt(array, i, b, b+j); + if (i + j < b) + this.mergeWithBufBWExt(array, i, i + j, b, b + j); + else + this.shiftBWExt(array, i, b, b + j); - for(i -= 2*j; i >= a; i -= 2*j) - this.mergeWithBufBWExt(array, i, i+j, i+2*j, i+3*j); + for (i -= 2 * j; i >= a; i -= 2 * j) + this.mergeWithBufBWExt(array, i, i + j, i + 2 * j, i + 3 * j); - a += j; b += j; j *= 2; + a += j; + b += j; + j *= 2; - for(int ti, tj = 4; j < len; j *= 2, tj *= 2) { - for(i = a, ti = 0; i+2*j < b; i += 2*j, ti += tj) - this.blockSelection(array, tags, i-bLen, i+2*j, bLen, ti, tj); + for (int ti, tj = 4; j < len; j *= 2, tj *= 2) { + for (i = a, ti = 0; i + 2 * j < b; i += 2 * j, ti += tj) + this.blockSelection(array, tags, i - bLen, i + 2 * j, bLen, ti, tj); - boolean noFrag = i+j < b; - p = (b-i)/bLen; + boolean noFrag = i + j < b; + p = (b - i) / bLen; - if(noFrag) this.blockSelection(array, tags, i-bLen, b, bLen, ti, tj); + if (noFrag) + this.blockSelection(array, tags, i - bLen, b, bLen, ti, tj); - a -= bLen; b -= bLen; i -= bLen; + a -= bLen; + b -= bLen; + i -= bLen; - if(noFrag) this.mergeBlocksBW(array, tags, i, b, ti, ti+p, bLen); + if (noFrag) + this.mergeBlocksBW(array, tags, i, b, ti, ti + p, bLen); - for(i -= 2*j, ti -= tj; i >= a; i -= 2*j, ti -= tj) - this.mergeBlocksBW(array, tags, i, i+2*j, ti, ti+tj, bLen); + for (i -= 2 * j, ti -= tj; i >= a; i -= 2 * j, ti -= tj) + this.mergeBlocksBW(array, tags, i, i + 2 * j, ti, ti + tj, bLen); - a += bLen; b += bLen; + a += bLen; + b += bLen; } - p = 0; i = 0; j = a; + p = 0; + i = 0; + j = a; - while(i < a && j < b) { + while (i < a && j < b) { Highlights.markArray(2, i); - if(Reads.compareValues(temp[i], array[j]) <= 0) + if (Reads.compareValues(temp[i], array[j]) <= 0) Writes.write(array, p++, temp[i++], 1, true, false); else Writes.write(array, p++, array[j++], 1, true, false); } - while(i < a) { + while (i < a) { Highlights.markArray(2, i); Writes.write(array, p++, temp[i++], 1, true, false); } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/TimSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/TimSort.java index 12e3b60a..22c9d52d 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/TimSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/TimSort.java @@ -21,15 +21,16 @@ * limitations under the License. */ -@SortMeta( - name = "Tim", - category = "Hybrid Sorts" -) +@SortMeta(name = "Tim") public class TimSort extends Sort { - private TimSorting timSortInstance; // TimSort cannot be simply written off as an abstract class, as it creates an instance of itself - // in order to track its state. Plus, it contains both instance and static methods, requiring even - // more refactoring, which would be just doing unnecessary busy work. Instead of what we've done for - // the rest of the algorithms, we'll favor composition over inheritance here and pass "util" objects + private TimSorting timSortInstance; // TimSort cannot be simply written off as an abstract class, as it creates an + // instance of itself + // in order to track its state. Plus, it contains both instance and static + // methods, requiring even + // more refactoring, which would be just doing unnecessary busy work. Instead of + // what we've done for + // the rest of the algorithms, we'll favor composition over inheritance here and + // pass "util" objects // to it. public TimSort(ArrayVisualizer arrayVisualizer) { diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/UnstableGrailSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/UnstableGrailSort.java index 336c94e0..e3a66d96 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/UnstableGrailSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/UnstableGrailSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.UnstableGrailSorting; /* @@ -46,22 +47,10 @@ this software and associated documentation files (the "Software"), to deal in /* use GrailSortWithDynBuffer() */ /* */ /*********************************************************/ - +@SortMeta(name = "Unstable Grail") public final class UnstableGrailSort extends UnstableGrailSorting { public UnstableGrailSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Unstable Grail"); - //this.setRunAllID("Grail Sort (Block Merge Sort)"); - //this.setRunAllSortsName("Grail Sort [Block Merge Sort]"); - this.setRunAllSortsName("Unstable Grailsort"); - this.setRunSortName("Unstable Grailsort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/WeaveMergeSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/WeaveMergeSort.java index 56b7a3bf..87067721 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/WeaveMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/WeaveMergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,32 +29,22 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Weave Merge") public final class WeaveMergeSort extends Sort { public WeaveMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Weave Merge"); - this.setRunAllSortsName("Weave Merge Sort"); - this.setRunSortName("Weave Mergesort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void weaveInsert(int[] arr, int start, int end) { int pos; - for(int j = start; j < end; j++){ + for (int j = start; j < end; j++) { pos = j; Highlights.markArray(1, j); Highlights.clearMark(2); - while(pos > start && Reads.compareValues(arr[pos], arr[pos - 1]) < 1) { + while (pos > start && Reads.compareValues(arr[pos], arr[pos - 1]) < 1) { Writes.swap(arr, pos, pos - 1, 0.2, true, false); pos--; } @@ -64,7 +55,7 @@ private void weaveMerge(int[] arr, int min, int max, int mid) { int i = 1; int target = (mid - min); - while(i <= target) { + while (i <= target) { Writes.multiSwap(arr, mid + i, min + (i * 2) - 1, 0.05, true, false); i++; } @@ -73,20 +64,18 @@ private void weaveMerge(int[] arr, int min, int max, int mid) { } private void weaveMergeSort(int[] array, int min, int max) { - if(max - min == 0) { //only one element. - Delays.sleep(1); //no swap - } - else if(max - min == 1) { //only two elements and swaps them - if(Reads.compareValues(array[min], array[max]) == 1) { + if (max - min == 0) { // only one element. + Delays.sleep(1); // no swap + } else if (max - min == 1) { // only two elements and swaps them + if (Reads.compareValues(array[min], array[max]) == 1) { Writes.swap(array, min, max, 0.01, true, false); } - } - else { - int mid = (int) Math.floor((min + max) / 2); //The midpoint + } else { + int mid = (int) Math.floor((min + max) / 2); // The midpoint - this.weaveMergeSort(array, min, mid); //sort the left side - this.weaveMergeSort(array, mid + 1, max); //sort the right side - this.weaveMerge(array, min, max, mid); //combines them + this.weaveMergeSort(array, min, mid); // sort the left side + this.weaveMergeSort(array, mid + 1, max); // sort the right side + this.weaveMerge(array, min, max, mid); // combines them } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/WikiSort.java b/src/main/java/io/github/arrayv/sorts/hybrid/WikiSort.java index 454aa6f4..37f25b53 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/WikiSort.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/WikiSort.java @@ -35,17 +35,16 @@ * */ -@SortMeta( - name = "Wiki", - category = "Hybrid Sorts", - question = "Enter external buffer size (0 for in-place):", - defaultAnswer = 0 -) +@SortMeta(name = "Wiki", question = "Enter external buffer size (0 for in-place):", defaultAnswer = 0) public class WikiSort extends Sort { - private WikiSorting wikiSortInstance; // Just like TimSort, WikiSort cannot be simply written off as an abstract class, as it creates an - // instance of itself in order to track its state. Plus, it contains both instance and static methods, - // requiring even more refactoring, which would be just doing unnecessary busy work. Instead of what - // we've done for the rest of the algorithms, we'll favor composition over inheritance here and pass + private WikiSorting wikiSortInstance; // Just like TimSort, WikiSort cannot be simply written off as an abstract + // class, as it creates an + // instance of itself in order to track its state. Plus, it contains both + // instance and static methods, + // requiring even more refactoring, which would be just doing unnecessary busy + // work. Instead of what + // we've done for the rest of the algorithms, we'll favor composition over + // inheritance here and pass // "util" objects to it. private InsertionSort insertionSort; @@ -53,7 +52,8 @@ public class WikiSort extends Sort { // Cache sizes for WikiSort // final private static int halfSize = (currentLen + 1) / 2; - // final private static int squareRoot = (int) (Math.sqrt((currentLen + 1) / 2) + 1); + // final private static int squareRoot = (int) (Math.sqrt((currentLen + 1) / 2) + // + 1); // final private static int staticBuffer = 32; // final private static int noBuffer = 0; diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/YujisBufferedMergeSort2.java b/src/main/java/io/github/arrayv/sorts/hybrid/YujisBufferedMergeSort2.java index 2a942aba..ab929a69 100644 --- a/src/main/java/io/github/arrayv/sorts/hybrid/YujisBufferedMergeSort2.java +++ b/src/main/java/io/github/arrayv/sorts/hybrid/YujisBufferedMergeSort2.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.hybrid; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,110 +29,102 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - - +@SortMeta(name = "Optimized Andrey/Yuji") public final class YujisBufferedMergeSort2 extends Sort { - public YujisBufferedMergeSort2(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Optimized A/Y Sort"); - this.setRunAllSortsName("Optimized Andrey/Yuji Sort"); - this.setRunSortName("Optimized Andrey/Yuji Sort"); - this.setCategory("Hybrid Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } public static int ceilLog(int n) { - int i; - for(i = 0; (1 << i) < n; i++); - return i; - } + int i; + for (i = 0; (1 << i) < n; i++) + ; + return i; + } private void multiSwap(int[] array, int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(array, a+i, b+i, 1, true, false); + for (int i = 0; i < len; i++) + Writes.swap(array, a + i, b + i, 1, true, false); } private void insertTo(int[] array, int a, int b) { Highlights.clearMark(2); int temp = array[a]; - while(a > b) Writes.write(array, a, array[(a--)-1], 0.5, true, false); + while (a > b) + Writes.write(array, a, array[(a--) - 1], 0.5, true, false); Writes.write(array, b, temp, 0.5, true, false); } private int binarySearch(int[] array, int start, int end, int value, boolean left) { int a = start, b = end; - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; boolean comp; - if(left) comp = Reads.compareValues(value, array[m]) <= 0; - else comp = Reads.compareValues(value, array[m]) < 0; + if (left) + comp = Reads.compareValues(value, array[m]) <= 0; + else + comp = Reads.compareValues(value, array[m]) < 0; - if(comp) b = m; - else a = m+1; + if (comp) + b = m; + else + a = m + 1; } return a; } private void binaryInsertion(int[] array, int a, int b) { - for(int i = a+1; i < b; i++) + for (int i = a + 1; i < b; i++) this.insertTo(array, i, this.binarySearch(array, a, i, array[i], false)); - } - + } private void mergeWithBufStatic(int[] array, int a, int m, int b, int p, boolean useBinarySearch) { int i = 0, j = m, k = a; - if(useBinarySearch) { - while(i < m-a && j < b) { - if(Reads.compareValues(array[j], array[p+i]) == -1) { - int q = this.binarySearch(array, j, b, array[p+i], true); - while(j < q) Writes.swap(array, k++, j++, 1, true, false); + if (useBinarySearch) { + while (i < m - a && j < b) { + if (Reads.compareValues(array[j], array[p + i]) == -1) { + int q = this.binarySearch(array, j, b, array[p + i], true); + while (j < q) + Writes.swap(array, k++, j++, 1, true, false); } - Writes.swap(array, k++, p+(i++), 1, true, false); + Writes.swap(array, k++, p + (i++), 1, true, false); } - while(i < m-a) { - Writes.swap(array, k++, p+(i++), 1, true, false); + while (i < m - a) { + Writes.swap(array, k++, p + (i++), 1, true, false); } - } - else { - while(i < m-a && j < b) { - if(Reads.compareValues(array[p+i], array[j]) <= 0) { - Writes.swap(array, k++, p+(i++), 1, true, false); - } - else { + } else { + while (i < m - a && j < b) { + if (Reads.compareValues(array[p + i], array[j]) <= 0) { + Writes.swap(array, k++, p + (i++), 1, true, false); + } else { Writes.swap(array, k++, j++, 1, true, false); } } - while(i < m-a) { - Writes.swap(array, k++, p+(i++), 1, true, false); + while (i < m - a) { + Writes.swap(array, k++, p + (i++), 1, true, false); } } } private int merge(int[] array, int a, int m, int b, int p) { int i = a, j = m; - while(i < m && j < b) { - if(Reads.compareIndices(array, i, j, 0, false) <= 0) + while (i < m && j < b) { + if (Reads.compareIndices(array, i, j, 0, false) <= 0) Writes.swap(array, p++, i++, 1, true, false); else Writes.swap(array, p++, j++, 1, true, false); } int leftover = 0; - while(i < m) { + while (i < m) { Writes.swap(array, p++, i++, 1, true, false); } - while(j < b) { + while (j < b) { Writes.swap(array, p++, j++, 1, true, false); leftover++; } @@ -141,62 +134,63 @@ private int merge(int[] array, int a, int m, int b, int p) { private void mergeSort(int[] array, int a, int p, int length) { int i, j = 16, pos, ceilLog = ceilLog(length); - if(length > 16 && (ceilLog & 1) == 1) + if (length > 16 && (ceilLog & 1) == 1) pos = p; else pos = a; - for(i = pos; i+16 <= pos+length; i+=16) - this.binaryInsertion(array, i, i+16); - this.binaryInsertion(array, i, pos+length); + for (i = pos; i + 16 <= pos + length; i += 16) + this.binaryInsertion(array, i, i + 16); + this.binaryInsertion(array, i, pos + length); int next = pos, posNext; - while(j < length) { + while (j < length) { pos = next; next ^= a ^ p; posNext = next; - for(i = pos; i+2*j <= pos+length; i+=2*j, posNext+=2*j) - this.merge(array, i, i+j, i+2*j, posNext); - if(i + j < pos+length) - this.merge(array, i, i+j, pos+length, posNext); + for (i = pos; i + 2 * j <= pos + length; i += 2 * j, posNext += 2 * j) + this.merge(array, i, i + j, i + 2 * j, posNext); + if (i + j < pos + length) + this.merge(array, i, i + j, pos + length, posNext); else - while(i < pos+length) Writes.swap(array, i++, posNext++, 1, true, false); + while (i < pos + length) + Writes.swap(array, i++, posNext++, 1, true, false); j *= 2; } } private void bufferedMerge(int[] array, int a, int b) { - if(b-a <= 16) { + if (b - a <= 16) { this.binaryInsertion(array, a, b); return; } - int m = (a+b+1)/2; - this.mergeSort(array, m, 2*m-b, b-m); + int m = (a + b + 1) / 2; + this.mergeSort(array, m, 2 * m - b, b - m); - int n = (a+m+1)/2; - //The 16 means that it will recursively sort 1/16 of the array. It's interesting to change that number and see how it affects performance - int limit = (b-a)/16; - while(m-a > limit) { - this.mergeSort(array, 2*n-m, n, m-n); - this.mergeWithBufStatic(array, n, m, b, 2*n-m, (b-m)/(m-n) >= ceilLog(n-a)); + int n = (a + m + 1) / 2; + // The 16 means that it will recursively sort 1/16 of the array. It's + // interesting to change that number and see how it affects performance + int limit = (b - a) / 16; + while (m - a > limit) { + this.mergeSort(array, 2 * n - m, n, m - n); + this.mergeWithBufStatic(array, n, m, b, 2 * n - m, (b - m) / (m - n) >= ceilLog(n - a)); m = n; - n = (a+m+1)/2; + n = (a + m + 1) / 2; } // the same as Andreysort's buffer redistribution this.bufferedMerge(array, a, m); - this.multiSwap(array, a, b-(m-a), m-a); - int s = this.merge(array, m, b-(m-a), b, a); - this.bufferedMerge(array, b-(m-a)-s, b); + this.multiSwap(array, a, b - (m - a), m - a); + int s = this.merge(array, m, b - (m - a), b, a); + this.bufferedMerge(array, b - (m - a) - s, b); } - - @Override - public void runSort(int[] array, int length, int bucketCount) { - this.bufferedMerge(array, 0, length); - } + @Override + public void runSort(int[] array, int length, int bucketCount) { + this.bufferedMerge(array, 0, length); + } } diff --git a/src/main/java/io/github/arrayv/sorts/hybrid/package-info.java b/src/main/java/io/github/arrayv/sorts/hybrid/package-info.java new file mode 100644 index 00000000..f7fd9436 --- /dev/null +++ b/src/main/java/io/github/arrayv/sorts/hybrid/package-info.java @@ -0,0 +1,2 @@ +@io.github.arrayv.sortdata.SortPackageMeta(category = "Hybrid Sorts") +package io.github.arrayv.sorts.hybrid; diff --git a/src/main/java/io/github/arrayv/sorts/select/BadSort.java b/src/main/java/io/github/arrayv/sorts/impractical/BadSort.java similarity index 67% rename from src/main/java/io/github/arrayv/sorts/select/BadSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/BadSort.java index 421a67ab..b49a8032 100644 --- a/src/main/java/io/github/arrayv/sorts/select/BadSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/BadSort.java @@ -1,26 +1,17 @@ -package io.github.arrayv.sorts.select; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* * This example of an O(n^3) sorting algorithm may be found here, written by James Jensen (StriplingWarrayior on StackOverflow): * https://stackoverflow.com/questions/27389344/is-there-a-sorting-algorithm-with-a-worst-case-time-complexity-of-n3 */ - +@SortMeta(name = "Bad", slowSort = true, unreasonableLimit = 2048) public final class BadSort extends Sort { public BadSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Bad"); - this.setRunAllSortsName("Bad Sort"); - this.setRunSortName("Badsort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(2048); - this.setBogoSort(false); } @Override @@ -35,15 +26,13 @@ public void runSort(int[] array, int currentLen, int bucketCount) { boolean isShortest = true; for (int k = j + 1; k < currentLen; k++) { - Highlights.markArray(2, k); - Delays.sleep(0.05); - if (Reads.compareValues(array[j], array[k]) == 1) { + if (Reads.compareIndices(array, j, k, 0.05, true) == 1) { isShortest = false; break; } } - if(isShortest) { + if (isShortest) { shortest = j; break; } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/BogoBogoSort.java b/src/main/java/io/github/arrayv/sorts/impractical/BogoBogoSort.java similarity index 63% rename from src/main/java/io/github/arrayv/sorts/distribute/BogoBogoSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/BogoBogoSort.java index 8e146067..920fe3f8 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/BogoBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/BogoBogoSort.java @@ -1,6 +1,7 @@ -package io.github.arrayv.sorts.distribute; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; /* @@ -32,44 +33,40 @@ of this software and associated documentation files (the "Software"), to deal /** * Implements https://www.dangermouse.net/esoteric/bogobogosort.html. *

- * Bogobogosort is like Bogosort, but in order to check whether the array is sorted, it performs the following procedure: + * Bogobogosort is like Bogosort, but in order to check whether the array is + * sorted, it performs the following procedure: *

    - *
  • It makes a copy, then shuffles it and sorts all but the last element using Bogobogosort. - *
  • If the last element of the sorted section is no greater than the last element of the copy, - * then the copy is sorted. - *
  • Otherwise, the shuffling-sorting process is repeated. - *
  • The original array is then compared to the copy to determine whether the array is sorted. + *
  • It makes a copy, then shuffles it and sorts all but the last element + * using Bogobogosort. + *
  • If the last element of the sorted section is no greater than the last + * element of the copy, + * then the copy is sorted. + *
  • Otherwise, the shuffling-sorting process is repeated. + *
  • The original array is then compared to the copy to determine whether the + * array is sorted. *
- * Like in Bogosort, if the array is not sorted, it shuffles it and repeats the entire process. + * Like in Bogosort, if the array is not sorted, it shuffles it and repeats the + * entire process. */ +@SortMeta(name = "BogoBogo", slowSort = true, bogoSort = true, unreasonableLimit = 5) public final class BogoBogoSort extends BogoSorting { public BogoBogoSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Bogo Bogo"); - this.setRunAllSortsName("Bogo Bogo Sort"); - this.setRunSortName("Bogobogosort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(5); - this.setBogoSort(true); } - private int[][] tmp; //fix seizure aux using 2d array + private int[][] tmp; // fix seizure aux using 2d array private boolean bogoBogoIsSorted(int[] array, int length) { if (length == 1) return true; - int idx = length-2; + int idx = length - 2; Writes.arraycopy(array, 0, tmp[idx], 0, length, this.delay, true, true); - bogoBogo(tmp[idx], length-1, true); - while (Reads.compareValues(tmp[idx][length-2], tmp[idx][length-1]) > 0) { + bogoBogo(tmp[idx], length - 1, true); + while (Reads.compareValues(tmp[idx][length - 2], tmp[idx][length - 1]) > 0) { this.bogoSwap(tmp[idx], 0, length, true); - bogoBogo(tmp[idx], length-1, true); + bogoBogo(tmp[idx], length - 1, true); } for (int i = 0; i < length; ++i) { @@ -89,14 +86,14 @@ private void bogoBogo(int[] array, int length, boolean aux) { @Override public void runSort(int[] array, int length, int bucketCount) { - tmp = new int[length-1][]; + tmp = new int[length - 1][]; - for(int i = length; i > 1; i--) - tmp[i-2] = Writes.createExternalArray(i); + for (int i = length; i > 1; i--) + tmp[i - 2] = Writes.createExternalArray(i); bogoBogo(array, length, false); - for(int i = length; i > 1; i--) - Writes.deleteExternalArray(tmp[i-2]); + for (int i = length; i > 1; i--) + Writes.deleteExternalArray(tmp[i - 2]); } } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/BogoSort.java b/src/main/java/io/github/arrayv/sorts/impractical/BogoSort.java similarity index 77% rename from src/main/java/io/github/arrayv/sorts/distribute/BogoSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/BogoSort.java index 93d275cb..d8b6c415 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/BogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/BogoSort.java @@ -1,6 +1,7 @@ -package io.github.arrayv.sorts.distribute; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; /* @@ -32,24 +33,15 @@ of this software and associated documentation files (the "Software"), to deal /** * Bogosort randomly shuffles the array until it is sorted. */ +@SortMeta(name = "Bogo", slowSort = true, bogoSort = true, unreasonableLimit = 10) public final class BogoSort extends BogoSorting { public BogoSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Bogo"); - this.setRunAllSortsName("Bogo Sort"); - this.setRunSortName("Bogosort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(10); - this.setBogoSort(true); } @Override public void runSort(int[] array, int length, int bucketCount) { - while(!this.isArraySorted(array, length)) + while (!this.isArraySorted(array, length)) this.bogoSwap(array, 0, length, false); } } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/BozoSort.java b/src/main/java/io/github/arrayv/sorts/impractical/BozoSort.java similarity index 59% rename from src/main/java/io/github/arrayv/sorts/distribute/BozoSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/BozoSort.java index 9fa6fcb1..76355acd 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/BozoSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/BozoSort.java @@ -1,24 +1,16 @@ -package io.github.arrayv.sorts.distribute; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; /** * Bozosort randomly swaps any two elements until the array is sorted. */ +@SortMeta(name = "Bozo", slowSort = true, bogoSort = true, unreasonableLimit = 11) public final class BozoSort extends BogoSorting { public BozoSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Bozo"); - this.setRunAllSortsName("Bozo Sort"); - this.setRunSortName("Bozosort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(11); - this.setBogoSort(true); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/exchange/BubbleBogoSort.java b/src/main/java/io/github/arrayv/sorts/impractical/BubbleBogoSort.java similarity index 69% rename from src/main/java/io/github/arrayv/sorts/exchange/BubbleBogoSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/BubbleBogoSort.java index 21827d54..eadec6fe 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/BubbleBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/BubbleBogoSort.java @@ -1,6 +1,7 @@ -package io.github.arrayv.sorts.exchange; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; /* @@ -30,30 +31,22 @@ of this software and associated documentation files (the "Software"), to deal */ /** - * Bubble Bogosort is like Bubble Sort, but randomly sorts adjacent pairs of elements until the array is sorted. + * Bubble Bogosort is like Bubble Sort, but randomly sorts adjacent pairs of + * elements until the array is sorted. */ +@SortMeta(name = "Bubble Bogo", slowSort = true, bogoSort = true, unreasonableLimit = 1024) public final class BubbleBogoSort extends BogoSorting { public BubbleBogoSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Bubble Bogo"); - this.setRunAllSortsName("Bubble Bogo Sort"); - this.setRunSortName("Bubble Bogosort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(1024); - this.setBogoSort(true); } @Override public void runSort(int[] array, int length, int bucketCount) { while (!this.isRangeSorted(array, 0, length, false, true)) { - int index = BogoSorting.randInt(0, length-1); + int index = BogoSorting.randInt(0, length - 1); - if (Reads.compareIndices(array, index, index+1, this.delay, true) > 0) - Writes.swap(array, index, index+1, this.delay, true, false); + if (Reads.compareIndices(array, index, index + 1, this.delay, true) > 0) + Writes.swap(array, index, index + 1, this.delay, true, false); } } } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/CocktailBogoSort.java b/src/main/java/io/github/arrayv/sorts/impractical/CocktailBogoSort.java similarity index 63% rename from src/main/java/io/github/arrayv/sorts/distribute/CocktailBogoSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/CocktailBogoSort.java index dbc69fd5..a64f1e15 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/CocktailBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/CocktailBogoSort.java @@ -1,26 +1,19 @@ -package io.github.arrayv.sorts.distribute; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; /** * Cocktail Bogosort is a bidirectional variation of Less Bogosort. * It repeatedly shuffles the array, - * dropping first and last remaining elements when they are in the correct place. + * dropping first and last remaining elements when they are in the correct + * place. */ +@SortMeta(name = "Cocktail Bogo", slowSort = true, bogoSort = true, unreasonableLimit = 1024) public final class CocktailBogoSort extends BogoSorting { public CocktailBogoSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Cocktail Bogo"); - this.setRunAllSortsName("Cocktail Bogo Sort"); - this.setRunSortName("Cocktail Bogosort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(1024); - this.setBogoSort(true); } @Override @@ -28,14 +21,14 @@ public void runSort(int[] array, int length, int bucketCount) { int min = 0; int max = length; - while (min < max-1) { + while (min < max - 1) { if (this.isMinSorted(array, min, max)) { Highlights.markArray(3, min); ++min; continue; } if (this.isMaxSorted(array, min, max)) { - Highlights.markArray(4, max-1); + Highlights.markArray(4, max - 1); --max; continue; } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/DeterministicBogoSort.java b/src/main/java/io/github/arrayv/sorts/impractical/DeterministicBogoSort.java similarity index 71% rename from src/main/java/io/github/arrayv/sorts/distribute/DeterministicBogoSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/DeterministicBogoSort.java index 58ea48d7..b67585f4 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/DeterministicBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/DeterministicBogoSort.java @@ -1,6 +1,7 @@ -package io.github.arrayv.sorts.distribute; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; /* MIT License @@ -28,36 +29,27 @@ of this software and associated documentation files (the "Software"), to deal *

* Uses Heap's algorithm. */ +@SortMeta(name = "Deterministic Bogo", slowSort = true, unreasonableLimit = 11) public final class DeterministicBogoSort extends BogoSorting { public DeterministicBogoSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Deterministic Bogo"); - this.setRunAllSortsName("Deterministic Bogo Sort"); - this.setRunSortName("Deterministic Bogosort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(11); - this.setBogoSort(true); } private boolean permutationSort(int[] array, int depth, int length) { - if (depth >= length-1) + if (depth >= length - 1) return this.isArraySorted(array, length); - for (int i = length-1; i > depth; --i) { - if (permutationSort(array, depth+1, length)) + for (int i = length - 1; i > depth; --i) { + if (permutationSort(array, depth + 1, length)) return true; - if ((length-depth)%2 == 0) + if ((length - depth) % 2 == 0) Writes.swap(array, depth, i, this.delay, true, false); else - Writes.swap(array, depth, length-1, this.delay, true, false); + Writes.swap(array, depth, length - 1, this.delay, true, false); } - return permutationSort(array, depth+1, length); + return permutationSort(array, depth + 1, length); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/exchange/ExchangeBogoSort.java b/src/main/java/io/github/arrayv/sorts/impractical/ExchangeBogoSort.java similarity index 62% rename from src/main/java/io/github/arrayv/sorts/exchange/ExchangeBogoSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/ExchangeBogoSort.java index 7fbde59d..dd525cf2 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/ExchangeBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/ExchangeBogoSort.java @@ -1,31 +1,23 @@ -package io.github.arrayv.sorts.exchange; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; /** * Exchange Bogosort randomly sorts any two elements until the array is sorted. */ +@SortMeta(name = "Exchange Bogo", slowSort = true, bogoSort = true, unreasonableLimit = 512) public final class ExchangeBogoSort extends BogoSorting { public ExchangeBogoSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Exchange Bogo"); - this.setRunAllSortsName("Exchange Bogo Sort"); - this.setRunSortName("Exchange Bogosort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(512); - this.setBogoSort(true); } @Override public void runSort(int[] array, int length, int bucketCount) { while (!this.isRangeSorted(array, 0, length, false, true)) { int index1 = BogoSorting.randInt(0, length), - index2 = BogoSorting.randInt(0, length); + index2 = BogoSorting.randInt(0, length); int comp = Reads.compareIndices(array, index1, index2, this.delay, true); if (index1 < index2 ? comp > 0 : comp < 0) diff --git a/src/main/java/io/github/arrayv/sorts/distribute/GuessSort.java b/src/main/java/io/github/arrayv/sorts/impractical/GuessSort.java similarity index 84% rename from src/main/java/io/github/arrayv/sorts/distribute/GuessSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/GuessSort.java index 340c12bf..734bd564 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/GuessSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/GuessSort.java @@ -1,23 +1,17 @@ -package io.github.arrayv.sorts.distribute; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; +@SortMeta(name = "Guess", slowSort = true, unreasonableLimit = 7) public final class GuessSort extends BogoSorting { public GuessSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - this.setSortListName("Guess"); - this.setRunAllSortsName("Guess Sort"); - this.setRunSortName("Guess Sort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(7); - this.setBogoSort(false); } - // PROGRAMMER'S NOTE: This sort is intentionally bad, it is purposefully un-optimized. + // PROGRAMMER'S NOTE: This sort is intentionally bad, it is purposefully + // un-optimized. @Override public void runSort(int[] array, int length, int bucketCount) { // "nested for-loop" with depth `length` to iterate over all n-tuples of indices diff --git a/src/main/java/io/github/arrayv/sorts/insert/HanoiSort.java b/src/main/java/io/github/arrayv/sorts/impractical/HanoiSort.java similarity index 63% rename from src/main/java/io/github/arrayv/sorts/insert/HanoiSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/HanoiSort.java index 849eddaa..4314d31d 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/HanoiSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/HanoiSort.java @@ -1,32 +1,46 @@ -package io.github.arrayv.sorts.insert; +package io.github.arrayv.sorts.impractical; import java.util.Stack; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /** - * Hanoi Sort, a sort inspired by the classic Tower of Hanoi puzzle.

+ * Hanoi Sort, a sort inspired by the classic Tower of Hanoi puzzle. + *

* - * This sort started as a random idea I had, with a vague idea of how I could approach - * the problem. And this is, in fact, the first complete implementation that I know of. - * However, I was greatly helped by two people before me. The first was Andrei "Mrrl" - * Astrelin (rip), who wrote some pseudocode for this sort that helped solidify the - * ideas that I'd been having. However, this pseudocode failed to explain how to shift - * more than one element from one stack to another without violating the traditional - * rules of the Tower of Hanoi puzzle. Since the sort didn't know the recursion depth - * that would be required, an iterative shift would be necessary; I found a simple - * algorithm for this at Stack Overflow. There were still loose ends I had to wrap up; - * in particular, for the aforementioned iterative hanoi function to work, I had to - * ensure all consecutive identical items were moved together. But I made it work, and + * This sort started as a random idea I had, with a vague idea of how I could + * approach + * the problem. And this is, in fact, the first complete implementation that I + * know of. + * However, I was greatly helped by two people before me. The first was Andrei + * "Mrrl" + * Astrelin (rip), who wrote some pseudocode for this sort that helped solidify + * the + * ideas that I'd been having. However, this pseudocode failed to explain how to + * shift + * more than one element from one stack to another without violating the + * traditional + * rules of the Tower of Hanoi puzzle. Since the sort didn't know the recursion + * depth + * that would be required, an iterative shift would be necessary; I found a + * simple + * algorithm for this at Stack Overflow. There were still loose ends I had to + * wrap up; + * in particular, for the aforementioned iterative hanoi function to work, I had + * to + * ensure all consecutive identical items were moved together. But I made it + * work, and * thus here I present the first implementation of this sort that I am aware of. * * @author Sam Walko (Anonymous0726) * @see - * Mrrl's Hanoi Sort pseudocode + * Mrrl's Hanoi Sort pseudocode * @see - * Iterative algorithm for Tower of Hanoi problem + * Iterative algorithm for Tower of Hanoi problem */ +@SortMeta(name = "Hanoi", slowSort = true, unreasonableLimit = 32) public final class HanoiSort extends Sort { // main array private int[] array; @@ -44,16 +58,6 @@ public final class HanoiSort extends Sort { public HanoiSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Hanoi"); - this.setRunAllSortsName("Hanoi Sort"); - this.setRunSortName("Hanoi sort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(32); - this.setBogoSort(false); } /** @@ -72,7 +76,7 @@ private void removeFromMainStack() { Highlights.clearAllMarks(); Highlights.markArray(1, sp); - if(evenHeight) // Move smaller elements to stack3, if necessary + if (evenHeight) // Move smaller elements to stack3, if necessary hanoi(1, true, 2); unsorted += moveFromMain(stack2, false); // Move next element(s) to stack2 hanoi(3, evenHeight, 2); // Move smaller elements back to stack2 @@ -86,7 +90,7 @@ private void removeFromMainStack() { private void returnToMainStack() { int moves = hanoi(2, true, 3); int height = getHeight(moves + 1); - if(height % 2 == 1) { // Odd height case: moved to stack3 + if (height % 2 == 1) { // Odd height case: moved to stack3 targetMoves = moves; hanoi(3, true, 2); } // In even case, it's already on main stack, and we need not do anything @@ -98,87 +102,93 @@ private void returnToMainStack() { * cases we do not know the initial recursion depth. * * @param startStack Which stack we wish to move a tower from - * @param goRight Whether the smallest disk should go right on the pegs - * (1->2, 2->3, 3->1) or left (1->3, 2->1, 3->2) - * @param endCon Used to determine when to end this function + * @param goRight Whether the smallest disk should go right on the pegs + * (1->2, 2->3, 3->1) or left (1->3, 2->1, 3->2) + * @param endCon Used to determine when to end this function * @return The number of moves performed */ private int hanoi(int startStack, boolean goRight, int endCon) { int moves = 0; int minPoleLoc = startStack; - if(!endConMet(endCon, moves)) { + if (!endConMet(endCon, moves)) { moves++; - switch(minPoleLoc) { - case 1: - if(goRight) { - moveFromMain(stack2, true); - minPoleLoc = 2; - } else { - moveFromMain(stack3, true); - minPoleLoc = 3; - } break; - case 2: - if(goRight) { - moveBetweenStacks(stack2, stack3); - minPoleLoc = 3; - } else { - moveToMain(stack2); - minPoleLoc = 1; - } break; - case 3: - if(goRight) { - moveToMain(stack3); - minPoleLoc = 1; - } else { - moveBetweenStacks(stack3, stack2); - minPoleLoc = 2; - } break; + switch (minPoleLoc) { + case 1: + if (goRight) { + moveFromMain(stack2, true); + minPoleLoc = 2; + } else { + moveFromMain(stack3, true); + minPoleLoc = 3; + } + break; + case 2: + if (goRight) { + moveBetweenStacks(stack2, stack3); + minPoleLoc = 3; + } else { + moveToMain(stack2); + minPoleLoc = 1; + } + break; + case 3: + if (goRight) { + moveToMain(stack3); + minPoleLoc = 1; + } else { + moveBetweenStacks(stack3, stack2); + minPoleLoc = 2; + } + break; } } - while(!endConMet(endCon, moves)) { + while (!endConMet(endCon, moves)) { moves += 2; - switch(minPoleLoc) { - case 1: - if(!stack2.isEmpty() && - (stack3.isEmpty() || Reads.compareValues(stack2.peek(), stack3.peek()) < 0)) - moveBetweenStacks(stack2, stack3); - else - moveBetweenStacks(stack3, stack2); - if(goRight) { - moveFromMain(stack2, true); - minPoleLoc = 2; - } else { - moveFromMain(stack3, true); - minPoleLoc = 3; - } break; - case 2: - if(stack3.isEmpty() || - (sp < unsorted && Reads.compareValues(array[sp], stack3.peek()) < 0)) - moveFromMain(stack3, true); - else - moveToMain(stack3); - if(goRight) { - moveBetweenStacks(stack2, stack3); - minPoleLoc = 3; - } else { - moveToMain(stack2); - minPoleLoc = 1; - } break; - case 3: - if(stack2.isEmpty() || - (sp < unsorted && Reads.compareValues(array[sp], stack2.peek()) < 0)) - moveFromMain(stack2, true); - else - moveToMain(stack2); - if(goRight) { - moveToMain(stack3); - minPoleLoc = 1; - } else { - moveBetweenStacks(stack3, stack2); - minPoleLoc = 2; - } break; + switch (minPoleLoc) { + case 1: + if (!stack2.isEmpty() && + (stack3.isEmpty() || Reads.compareValues(stack2.peek(), stack3.peek()) < 0)) + moveBetweenStacks(stack2, stack3); + else + moveBetweenStacks(stack3, stack2); + if (goRight) { + moveFromMain(stack2, true); + minPoleLoc = 2; + } else { + moveFromMain(stack3, true); + minPoleLoc = 3; + } + break; + case 2: + if (stack3.isEmpty() || + (sp < unsorted && Reads.compareValues(array[sp], stack3.peek()) < 0)) + moveFromMain(stack3, true); + else + moveToMain(stack3); + if (goRight) { + moveBetweenStacks(stack2, stack3); + minPoleLoc = 3; + } else { + moveToMain(stack2); + minPoleLoc = 1; + } + break; + case 3: + if (stack2.isEmpty() || + (sp < unsorted && Reads.compareValues(array[sp], stack2.peek()) < 0)) + moveFromMain(stack2, true); + else + moveToMain(stack2); + if (goRight) { + moveToMain(stack3); + minPoleLoc = 1; + } else { + moveBetweenStacks(stack3, stack2); + minPoleLoc = 2; + } + break; } } @@ -188,19 +198,20 @@ private int hanoi(int startStack, boolean goRight, int endCon) { /** * Determines whether or not the hanoi function should end now * - * @param endCon Which ending condition is required for the hanoi function to end - * @param moves the moves completed by the hanoi function so far + * @param endCon Which ending condition is required for the hanoi function to + * end + * @param moves the moves completed by the hanoi function so far * @return Whether or not the end condition has been met */ private boolean endConMet(int endCon, int moves) { - if(!validNumberMoves(moves)) + if (!validNumberMoves(moves)) return false; - switch (endCon) { - case 1: return (stack2.isEmpty() || Reads.compareValues(target, stack2.peek()) <= 0); - case 2: return moves == targetMoves; - case 3: return stack2.isEmpty(); - default: throw new IllegalArgumentException(); - } + return switch (endCon) { + case 1 -> (stack2.isEmpty() || Reads.compareValues(target, stack2.peek()) <= 0); + case 2 -> moves == targetMoves; + case 3 -> stack2.isEmpty(); + default -> throw new IllegalArgumentException(); + }; } /** @@ -208,11 +219,11 @@ private boolean endConMet(int endCon, int moves) { * @return If the moves is of the form (2^n)-1 */ private boolean validNumberMoves(int moves) { - if(moves == 0) + if (moves == 0) return true; - if(moves % 2 == 0) + if (moves % 2 == 0) return false; - return validNumberMoves(moves/2); + return validNumberMoves(moves / 2); } /** @@ -222,7 +233,7 @@ private boolean validNumberMoves(int moves) { * @return The height of the pyramid moved (equal to log_2(moves + 1)) */ private int getHeight(int movesPlus1) { - if(movesPlus1 == 1) + if (movesPlus1 == 1) return 0; return getHeight(movesPlus1 / 2) + 1; } @@ -231,11 +242,11 @@ private int getHeight(int movesPlus1) { * Moves an element from the main array to another stack, * then moves any consecutive duplicates of that element with it * - * @param stack The stack to move the element(s) from the main array to + * @param stack The stack to move the element(s) from the main array to * @param checkUnsorted Whether or not it is safe to remove elements in - * the unsorted portion of the main array + * the unsorted portion of the main array * @return duplicates The number of consecutive identical elements - * that were popped off the main array in the current "move" + * that were popped off the main array in the current "move" */ private int moveFromMain(Stack stack, boolean checkUnsorted) { int duplicates = 1; @@ -250,7 +261,7 @@ private int moveFromMain(Stack stack, boolean checkUnsorted) { // Move any duplicates (endOnLength indicates the relevant portion of // the main stack is "empty") boolean endOnLength = (sp >= length) || (checkUnsorted && sp >= unsorted); - while(!endOnLength && Reads.compareValues(array[sp], stack.peek()) == 0) { + while (!endOnLength && Reads.compareValues(array[sp], stack.peek()) == 0) { duplicates++; Writes.changeAuxWrites(1); Writes.startLap(); @@ -276,7 +287,7 @@ private void moveToMain(Stack stack) { Highlights.markArray(1, sp); Writes.write(array, sp, stack.pop(), 0.25, false, false); // Move any duplicates - while(!stack.isEmpty() && Reads.compareValues(stack.peek(), array[sp]) == 0) { + while (!stack.isEmpty() && Reads.compareValues(stack.peek(), array[sp]) == 0) { sp--; Highlights.markArray(1, sp); Writes.write(array, sp, stack.pop(), 0.25, false, false); @@ -288,7 +299,7 @@ private void moveToMain(Stack stack) { * then moves any consecutive duplicates of that element with it * * @param from the stack to move the element(s) from - * @param to the stack to move the element(s) to + * @param to the stack to move the element(s) to */ private void moveBetweenStacks(Stack from, Stack to) { // Move element @@ -298,7 +309,7 @@ private void moveBetweenStacks(Stack from, Stack to) { Writes.stopLap(); Delays.sleep(0.25); // Move any duplicates - while(!from.isEmpty() && Reads.compareValues(from.peek(), to.peek()) == 0) { + while (!from.isEmpty() && Reads.compareValues(from.peek(), to.peek()) == 0) { Writes.changeAuxWrites(1); Writes.startLap(); to.push(from.pop()); @@ -307,7 +318,6 @@ private void moveBetweenStacks(Stack from, Stack to) { } } - @Override public void runSort(int[] array, int length, int bucketCount) { // Initialize local variables @@ -318,7 +328,7 @@ public void runSort(int[] array, int length, int bucketCount) { sp = 0; unsorted = 0; - while(unsorted < length) + while (unsorted < length) removeFromMainStack(); returnToMainStack(); diff --git a/src/main/java/io/github/arrayv/sorts/distribute/LessBogoSort.java b/src/main/java/io/github/arrayv/sorts/impractical/LessBogoSort.java similarity index 62% rename from src/main/java/io/github/arrayv/sorts/distribute/LessBogoSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/LessBogoSort.java index 47b90c35..92fd6088 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/LessBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/LessBogoSort.java @@ -1,25 +1,17 @@ -package io.github.arrayv.sorts.distribute; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; /** * Less Bogosort repeatedly shuffles the array, * dropping the first remaining element when it is in the correct place. */ +@SortMeta(name = "Less Bogo", slowSort = true, bogoSort = true, unreasonableLimit = 512) public final class LessBogoSort extends BogoSorting { public LessBogoSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Less Bogo"); - this.setRunAllSortsName("Less Bogo Sort"); - this.setRunSortName("Less Bogosort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(512); - this.setBogoSort(true); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/distribute/MedianQuickBogoSort.java b/src/main/java/io/github/arrayv/sorts/impractical/MedianQuickBogoSort.java similarity index 78% rename from src/main/java/io/github/arrayv/sorts/distribute/MedianQuickBogoSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/MedianQuickBogoSort.java index 32161e42..23b36fd6 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/MedianQuickBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/MedianQuickBogoSort.java @@ -1,6 +1,7 @@ -package io.github.arrayv.sorts.distribute; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; /* @@ -30,29 +31,21 @@ of this software and associated documentation files (the "Software"), to deal */ /** - * Median Quick Bogosort repeatedly shuffles the array until the left and right halves are split. + * Median Quick Bogosort repeatedly shuffles the array until the left and right + * halves are split. * It then recursively sorts each half. */ +@SortMeta(name = "Median Quick Bogo", slowSort = true, bogoSort = true, unreasonableLimit = 23) public final class MedianQuickBogoSort extends BogoSorting { public MedianQuickBogoSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Median Quick Bogo"); - this.setRunAllSortsName("Median Quick Bogo Sort"); - this.setRunSortName("Median Quick Bogosort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(23); - this.setBogoSort(true); } private void medianQuickBogo(int[] array, int start, int end) { - if (start >= end-1) + if (start >= end - 1) return; - int mid = (start+end)/2; + int mid = (start + end) / 2; while (!isRangeSplit(array, start, mid, end)) this.bogoSwap(array, start, end, false); diff --git a/src/main/java/io/github/arrayv/sorts/distribute/MergeBogoSort.java b/src/main/java/io/github/arrayv/sorts/impractical/MergeBogoSort.java similarity index 79% rename from src/main/java/io/github/arrayv/sorts/distribute/MergeBogoSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/MergeBogoSort.java index ba74ac23..37dfb1a7 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/MergeBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/MergeBogoSort.java @@ -1,6 +1,7 @@ -package io.github.arrayv.sorts.distribute; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; /* @@ -33,23 +34,14 @@ of this software and associated documentation files (the "Software"), to deal * Merge Bogosort is like Merge Sort, but when merging, * it randomly weaves the two subarrays together until they are sorted. */ +@SortMeta(name = "Merge Bogo", slowSort = true, bogoSort = true, unreasonableLimit = 22) public final class MergeBogoSort extends BogoSorting { public MergeBogoSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Merge Bogo"); - this.setRunAllSortsName("Merge Bogo Sort"); - this.setRunSortName("Merge Bogosort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(22); - this.setBogoSort(true); } private void bogoWeave(int[] array, int[] tmp, int start, int mid, int end) { - this.bogoCombo(array, start, end, end-mid, false); + this.bogoCombo(array, start, end, end - mid, false); int low = start; int high = mid; @@ -63,13 +55,14 @@ private void bogoWeave(int[] array, int[] tmp, int start, int mid, int end) { } private void mergeBogo(int[] array, int[] tmp, int start, int end) { - if (start >= end-1) return; + if (start >= end - 1) + return; - int mid = (start+end)/2; + int mid = (start + end) / 2; mergeBogo(array, tmp, start, mid); mergeBogo(array, tmp, mid, end); - Writes.arraycopy(array, start, tmp, start, end-start, this.delay, true, true); + Writes.arraycopy(array, start, tmp, start, end - start, this.delay, true, true); while (!this.isRangeSorted(array, start, end)) bogoWeave(array, tmp, start, mid, end); diff --git a/src/main/java/io/github/arrayv/sorts/distribute/OptimizedGuessSort.java b/src/main/java/io/github/arrayv/sorts/impractical/OptimizedGuessSort.java similarity index 73% rename from src/main/java/io/github/arrayv/sorts/distribute/OptimizedGuessSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/OptimizedGuessSort.java index 18247d15..e1a96030 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/OptimizedGuessSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/OptimizedGuessSort.java @@ -1,24 +1,17 @@ -package io.github.arrayv.sorts.distribute; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; +@SortMeta(name = "Optimized Guess", slowSort = true, unreasonableLimit = 8) public final class OptimizedGuessSort extends BogoSorting { public OptimizedGuessSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Optimized Guess"); - this.setRunAllSortsName("Optimized Guess Sort"); - this.setRunSortName("Optimized Guess Sort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(8); - this.setBogoSort(false); } - // PROGRAMMER'S NOTE: This sort is intentionally bad, it is purposefully un-optimized. + // PROGRAMMER'S NOTE: This sort is intentionally bad, it is purposefully + // un-optimized. // OTHER PROGRAMMER'S NOTE: haha too bad not any more @Override public void runSort(int[] array, int length, int bucketCount) { @@ -28,12 +21,12 @@ public void runSort(int[] array, int length, int bucketCount) { while (true) { // check if the array is stably sorted (doubles as duplicate-detection) boolean sorted = true; - for (int i = 0; i < length-1; ++i) { + for (int i = 0; i < length - 1; ++i) { Highlights.markArray(1, i); - Highlights.markArray(2, i+1); + Highlights.markArray(2, i + 1); Delays.sleep(this.delay); - int comp = Reads.compareIndices(array, loops[i], loops[i+1], this.delay, true); - if (comp < 0 || comp == 0 && loops[i] < loops[i+1]) + int comp = Reads.compareIndices(array, loops[i], loops[i + 1], this.delay, true); + if (comp < 0 || comp == 0 && loops[i] < loops[i + 1]) continue; sorted = false; break; diff --git a/src/main/java/io/github/arrayv/sorts/exchange/QuadStoogeSort.java b/src/main/java/io/github/arrayv/sorts/impractical/QuadStoogeSort.java similarity index 77% rename from src/main/java/io/github/arrayv/sorts/exchange/QuadStoogeSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/QuadStoogeSort.java index 4895adb6..eb692bee 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/QuadStoogeSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/QuadStoogeSort.java @@ -1,9 +1,10 @@ /** * */ -package io.github.arrayv.sorts.exchange; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /** @@ -11,6 +12,7 @@ * @author EilrahcF * */ +@SortMeta(name = "Quad Stooge", slowSort = true, unreasonableLimit = 2048) public final class QuadStoogeSort extends Sort { /** @@ -18,15 +20,6 @@ public final class QuadStoogeSort extends Sort { */ public QuadStoogeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - setSortListName("Quad Stooge"); - setRunAllSortsName("Quad Stooge Sort"); - setRunSortName("Quad Stoogesort"); - setCategory("Impractical Sorts"); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(true); - setUnreasonableLimit(2048); - setBogoSort(false); } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/QuickBogoSort.java b/src/main/java/io/github/arrayv/sorts/impractical/QuickBogoSort.java similarity index 79% rename from src/main/java/io/github/arrayv/sorts/distribute/QuickBogoSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/QuickBogoSort.java index 2fc580c4..557b3dbe 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/QuickBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/QuickBogoSort.java @@ -1,6 +1,7 @@ -package io.github.arrayv.sorts.distribute; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; /* @@ -34,23 +35,14 @@ of this software and associated documentation files (the "Software"), to deal * it randomly shuffles the array until the pivot partitions the array. * The pivot is tracked as the array is shuffled. */ +@SortMeta(name = "Quick Bogo", slowSort = true, bogoSort = true, unreasonableLimit = 22) public final class QuickBogoSort extends BogoSorting { public QuickBogoSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Quick Bogo"); - this.setRunAllSortsName("Quick Bogo Sort"); - this.setRunSortName("Quick Bogosort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(22); - this.setBogoSort(true); } - private int quickBogoSwap(int[] array, int start, int pivot, int end){ - for(int i = start; i < end; i++) { + private int quickBogoSwap(int[] array, int start, int pivot, int end) { + for (int i = start; i < end; i++) { int j = BogoSorting.randInt(i, end); if (pivot == i) pivot = j; @@ -62,18 +54,18 @@ else if (pivot == j) } private void quickBogo(int[] array, int start, int end) { - if (start >= end-1) + if (start >= end - 1) return; int pivot = start; // worst-case pivot (linear distribution) // for (; pivot < end; ++pivot) - // if (array[pivot] == (start+end)/2) break; + // if (array[pivot] == (start+end)/2) break; while (!isRangePartitioned(array, start, pivot, end)) pivot = quickBogoSwap(array, start, pivot, end); quickBogo(array, start, pivot); - quickBogo(array, pivot+1, end); + quickBogo(array, pivot + 1, end); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/distribute/RandomGuessSort.java b/src/main/java/io/github/arrayv/sorts/impractical/RandomGuessSort.java similarity index 71% rename from src/main/java/io/github/arrayv/sorts/distribute/RandomGuessSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/RandomGuessSort.java index d23f8132..79aeadb9 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/RandomGuessSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/RandomGuessSort.java @@ -1,24 +1,17 @@ -package io.github.arrayv.sorts.distribute; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; +@SortMeta(name = "Random Guess", slowSort = true, bogoSort = true, unreasonableLimit = 8) public final class RandomGuessSort extends BogoSorting { public RandomGuessSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Random Guess"); - this.setRunAllSortsName("Random Guess Sort"); - this.setRunSortName("Random Guess Sort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(8); - this.setBogoSort(false); } - // PROGRAMMER'S NOTE: This sort is intentionally bad, it is purposefully un-optimized. + // PROGRAMMER'S NOTE: This sort is intentionally bad, it is purposefully + // un-optimized. // OTHER PROGRAMMER'S NOTE: haha too bad this isn't even the same sort anymore @Override public void runSort(int[] array, int length, int bucketCount) { @@ -28,12 +21,12 @@ public void runSort(int[] array, int length, int bucketCount) { while (true) { // check if the array is stably sorted (doubles as duplicate-detection) boolean sorted = true; - for (int i = 0; i < length-1; ++i) { + for (int i = 0; i < length - 1; ++i) { Highlights.markArray(1, i); - Highlights.markArray(2, i+1); + Highlights.markArray(2, i + 1); Delays.sleep(this.delay); - int comp = Reads.compareIndices(array, loops[i], loops[i+1], this.delay, true); - if (comp < 0 || comp == 0 && loops[i] < loops[i+1]) + int comp = Reads.compareIndices(array, loops[i], loops[i + 1], this.delay, true); + if (comp < 0 || comp == 0 && loops[i] < loops[i + 1]) continue; sorted = false; break; diff --git a/src/main/java/io/github/arrayv/sorts/distribute/SelectionBogoSort.java b/src/main/java/io/github/arrayv/sorts/impractical/SelectionBogoSort.java similarity index 82% rename from src/main/java/io/github/arrayv/sorts/distribute/SelectionBogoSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/SelectionBogoSort.java index 5d3f1d2a..23ac55db 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/SelectionBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/SelectionBogoSort.java @@ -1,6 +1,7 @@ -package io.github.arrayv.sorts.distribute; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; /* @@ -40,21 +41,13 @@ of this software and associated documentation files (the "Software"), to deal * but it randomly swaps an element out of the remaining unsorted elements * to the front of them until it is the smallest. *

- * Selection Bogosort can also be viewed as an optimized variation of Less Bogosort. + * Selection Bogosort can also be viewed as an optimized variation of Less + * Bogosort. */ +@SortMeta(name = "Selection Bogo", slowSort = true, bogoSort = true, unreasonableLimit = 4096) public final class SelectionBogoSort extends BogoSorting { public SelectionBogoSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Selection Bogo"); - this.setRunAllSortsName("Selection Bogo Sort"); - this.setRunSortName("Selection Bogosort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(4096); - this.setBogoSort(true); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/exchange/ShoveSort.java b/src/main/java/io/github/arrayv/sorts/impractical/ShoveSort.java similarity index 60% rename from src/main/java/io/github/arrayv/sorts/exchange/ShoveSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/ShoveSort.java index 1865d0b1..17d148ce 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/ShoveSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/ShoveSort.java @@ -1,6 +1,7 @@ -package io.github.arrayv.sorts.exchange; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /** @@ -8,29 +9,18 @@ * @author PiotrGrochowski * */ +@SortMeta(name = "Shove", slowSort = true, unreasonableLimit = 512) public final class ShoveSort extends Sort { public ShoveSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - setSortListName("Shove"); - setRunAllSortsName("Shove Sort"); - setRunSortName("Shove Sort"); - setCategory("Impractical Sorts"); - setBucketSort(false); - setRadixSort(false); - setUnreasonablySlow(true); - setUnreasonableLimit(512); - setBogoSort(false); } private void shovesort(int[] array, int start, int end, double sleep) { int i = start; while (i < end - 1) { - this.Highlights.markArray(1, i); - this.Highlights.markArray(2, i + 1); - this.Delays.sleep(sleep); - if (this.Reads.compareValues(array[i], array[i + 1]) == 1) { + if (Reads.compareIndices(array, i, i + 1, sleep, true) == 1) { for (int f = i; f < end - 1; f++) { this.Writes.swap(array, f, f + 1, sleep, true, false); } diff --git a/src/main/java/io/github/arrayv/sorts/impractical/SillySort.java b/src/main/java/io/github/arrayv/sorts/impractical/SillySort.java new file mode 100644 index 00000000..8463d269 --- /dev/null +++ b/src/main/java/io/github/arrayv/sorts/impractical/SillySort.java @@ -0,0 +1,45 @@ +package io.github.arrayv.sorts.impractical; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; + +// Written by Tom Duff, and found here: http://home.tiac.net/~cri_d/cri/2001/badsort.html +// from https://stackoverflow.com/questions/2609857/are-there-any-worse-sorting-algorithms-than-bogosort-a-k-a-monkey-sort/ +@SortMeta(name = "Silly", slowSort = true, unreasonableLimit = 150) +public final class SillySort extends Sort { + public SillySort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } + + private void sillySort(int[] array, int i, int j) { + int m; + + if (i < j) { + /* find the middle of the array */ + m = i + ((j - i) / 2); + + /* + * use this function (recursively) to find put the minimum elements of + * each half into the first elements of each half + */ + this.sillySort(array, i, m); + this.sillySort(array, m + 1, j); + + /* + * Choose the smallest element of the two halves, and put that element in + * the first position + */ + if (Reads.compareIndices(array, i, m + 1, 1, true) >= 0) { + Writes.swap(array, i, m + 1, 0, true, false); + } + + this.sillySort(array, i + 1, j); + } + } + + @Override + public void runSort(int[] array, int currentLength, int bucketCount) { + this.sillySort(array, 0, currentLength - 1); + } +} diff --git a/src/main/java/io/github/arrayv/sorts/impractical/SlowSort.java b/src/main/java/io/github/arrayv/sorts/impractical/SlowSort.java new file mode 100644 index 00000000..cc946d12 --- /dev/null +++ b/src/main/java/io/github/arrayv/sorts/impractical/SlowSort.java @@ -0,0 +1,34 @@ +package io.github.arrayv.sorts.impractical; + +import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; +import io.github.arrayv.sorts.templates.Sort; + +// Code refactored from Python: http://wiki.c2.com/?SlowSort +@SortMeta(name = "Slow", slowSort = true, unreasonableLimit = 150) +public final class SlowSort extends Sort { + public SlowSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } + + private void slowSort(int[] A, int i, int j) { + if (i >= j) { + return; + } + + int m = i + ((j - i) / 2); + + this.slowSort(A, i, m); + this.slowSort(A, m + 1, j); + + if (Reads.compareIndices(A, m, j, 1, true) == 1) { + Writes.swap(A, m, j, 0, true, false); + } + this.slowSort(A, i, j - 1); + } + + @Override + public void runSort(int[] array, int currentLength, int bucketCount) { + this.slowSort(array, 0, currentLength - 1); + } +} diff --git a/src/main/java/io/github/arrayv/sorts/distribute/SmartBogoBogoSort.java b/src/main/java/io/github/arrayv/sorts/impractical/SmartBogoBogoSort.java similarity index 75% rename from src/main/java/io/github/arrayv/sorts/distribute/SmartBogoBogoSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/SmartBogoBogoSort.java index 96c6e76b..c8a1bf27 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/SmartBogoBogoSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/SmartBogoBogoSort.java @@ -1,6 +1,7 @@ -package io.github.arrayv.sorts.distribute; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; /* @@ -35,33 +36,26 @@ of this software and associated documentation files (the "Software"), to deal * This is then simplified so that no copy of the array is needed. *

    *
  • All but the last element of the array are sorted using Bogobogosort. - *
  • If the last element of the sorted section is no greater than the last element of the array, - * then the copy is sorted. Otherwise, the array is shuffled and the process is repeated. + *
  • If the last element of the sorted section is no greater than the last + * element of the array, + * then the copy is sorted. Otherwise, the array is shuffled and the process is + * repeated. *
*/ +@SortMeta(name = "Smart BogoBogo", slowSort = true, bogoSort = true, unreasonableLimit = 11) public final class SmartBogoBogoSort extends BogoSorting { public SmartBogoBogoSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Smart Bogo Bogo"); - this.setRunAllSortsName("Smart Bogo Bogo Sort"); - this.setRunSortName("Smart Bogobogosort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(11); - this.setBogoSort(true); } private void smartBogoBogo(int[] array, int length) { if (length == 1) return; - smartBogoBogo(array, length-1); - while (Reads.compareIndices(array, length-2, length-1, this.delay, true) > 0) { + smartBogoBogo(array, length - 1); + while (Reads.compareIndices(array, length - 2, length - 1, this.delay, true) > 0) { this.bogoSwap(array, 0, length, false); - smartBogoBogo(array, length-1); + smartBogoBogo(array, length - 1); } } diff --git a/src/main/java/io/github/arrayv/sorts/distribute/SmartGuessSort.java b/src/main/java/io/github/arrayv/sorts/impractical/SmartGuessSort.java similarity index 74% rename from src/main/java/io/github/arrayv/sorts/distribute/SmartGuessSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/SmartGuessSort.java index e5a012bd..1c407096 100644 --- a/src/main/java/io/github/arrayv/sorts/distribute/SmartGuessSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/SmartGuessSort.java @@ -1,24 +1,17 @@ -package io.github.arrayv.sorts.distribute; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; +@SortMeta(name = "Smart Guess", slowSort = true, unreasonableLimit = 19) public final class SmartGuessSort extends BogoSorting { public SmartGuessSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Smart Guess"); - this.setRunAllSortsName("Smart Guess Sort"); - this.setRunSortName("Smart Guess Sort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(19); - this.setBogoSort(false); } - // PROGRAMMER'S NOTE: This sort is intentionally bad, it is purposefully un-optimized. + // PROGRAMMER'S NOTE: This sort is intentionally bad, it is purposefully + // un-optimized. // OTHER PROGRAMMER'S NOTE: haha too bad not any more at all @Override public void runSort(int[] array, int length, int bucketCount) { @@ -28,13 +21,13 @@ public void runSort(int[] array, int length, int bucketCount) { while (true) { // check if the array is stably sorted (doubles as duplicate-detection) boolean sorted = true; - int i = length-2; + int i = length - 2; for (; i >= 0; --i) { Highlights.markArray(1, i); - Highlights.markArray(2, i+1); + Highlights.markArray(2, i + 1); Delays.sleep(this.delay); - int comp = Reads.compareIndices(array, loops[i], loops[i+1], this.delay, true); - if (comp < 0 || comp == 0 && loops[i] < loops[i+1]) + int comp = Reads.compareIndices(array, loops[i], loops[i + 1], this.delay, true); + if (comp < 0 || comp == 0 && loops[i] < loops[i + 1]) continue; sorted = false; break; @@ -42,7 +35,8 @@ public void runSort(int[] array, int length, int bucketCount) { Highlights.clearAllMarks(); if (sorted) break; - // progress the loops (we skip ahead to progress the index where the out-of-order was detected) + // progress the loops (we skip ahead to progress the index where the + // out-of-order was detected) for (int pos = 0; pos < length; ++pos) if (pos >= i && loops[pos] < length - 1) { Writes.write(loops, pos, loops[pos] + 1, this.delay, true, true); diff --git a/src/main/java/io/github/arrayv/sorts/exchange/SnuffleSort.java b/src/main/java/io/github/arrayv/sorts/impractical/SnuffleSort.java similarity index 52% rename from src/main/java/io/github/arrayv/sorts/exchange/SnuffleSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/SnuffleSort.java index b09b26f5..7a2315dc 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/SnuffleSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/SnuffleSort.java @@ -1,32 +1,21 @@ -package io.github.arrayv.sorts.exchange; - -import java.lang.Math; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Snuffle", slowSort = true, unreasonableLimit = 100) public class SnuffleSort extends Sort { private static double DELAY = 1; + public SnuffleSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Snuffle"); - this.setRunAllSortsName("Snuffle Sort"); - this.setRunSortName("Snuffle Sort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(100); - this.setBogoSort(false); } - private void snuffleSort(int[] arr, int start, int stop) { + private void snuffleSort(int[] arr, int start, int stop) { if (stop - start + 1 >= 2) { - Highlights.markArray(0, start); - Highlights.markArray(1, stop); - if (Reads.compareValues(arr[start], arr[stop]) == 1) - Writes.swap(arr, start, stop, DELAY, false, false); + if (Reads.compareIndices(arr, start, stop, DELAY, true) == 1) + Writes.swap(arr, start, stop, 0, false, false); if (stop - start + 1 >= 3) { int mid = (stop - start) / 2 + start; for (int i = 0; i < (int) Math.ceil((stop - start + 1) / 2); i++) { @@ -35,7 +24,7 @@ private void snuffleSort(int[] arr, int start, int stop) { } } } - } + } @Override public void runSort(int[] array, int length, int buckets) { diff --git a/src/main/java/io/github/arrayv/sorts/exchange/StablePermutationSort.java b/src/main/java/io/github/arrayv/sorts/impractical/StablePermutationSort.java similarity index 56% rename from src/main/java/io/github/arrayv/sorts/exchange/StablePermutationSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/StablePermutationSort.java index d15d1733..e331cc8d 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/StablePermutationSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/StablePermutationSort.java @@ -1,6 +1,7 @@ -package io.github.arrayv.sorts.exchange; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BogoSorting; /* @@ -28,59 +29,52 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Stable Permutation", slowSort = true, unreasonableLimit = 11) public final class StablePermutationSort extends BogoSorting { - public StablePermutationSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Stable Permutation"); - this.setRunAllSortsName("Stable Permutation Sort"); - this.setRunSortName("Stable Permutation Sort"); - this.setCategory("Exchange Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(11); - this.setBogoSort(false); - } + public StablePermutationSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int length; private boolean permute(int[] array, int[] idx, int len) { - if(len < 2) return this.isArraySorted(array, this.length); + if (len < 2) + return this.isArraySorted(array, this.length); - for(int i = len-2; i >= 0; i--) { - if(this.permute(array, idx, len-1)) return true; + for (int i = len - 2; i >= 0; i--) { + if (this.permute(array, idx, len - 1)) + return true; - Writes.swap(array, idx[i], idx[len-1], 0, true, false); - Writes.swap(idx, i, len-1, this.delay, false, true); + Writes.swap(array, idx[i], idx[len - 1], 0, true, false); + Writes.swap(idx, i, len - 1, this.delay, false, true); } - if(this.permute(array, idx, len-1)) return true; + if (this.permute(array, idx, len - 1)) + return true; - int t = idx[len-1]; + int t = idx[len - 1]; - for(int i = len-1; i > 0; i--) - Writes.write(idx, i, idx[i-1], 0, false, true); + for (int i = len - 1; i > 0; i--) + Writes.write(idx, i, idx[i - 1], 0, false, true); Writes.write(idx, 0, t, 0, false, true); t = array[idx[0]]; - for(int i = 1; i < len; i++) - Writes.write(array, idx[i-1], array[idx[i]], this.delay, true, false); - Writes.write(array, idx[len-1], t, this.delay, true, false); + for (int i = 1; i < len; i++) + Writes.write(array, idx[i - 1], array[idx[i]], this.delay, true, false); + Writes.write(array, idx[len - 1], t, this.delay, true, false); return false; } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { this.length = length; int[] idx = Writes.createExternalArray(length); - for(int i = 0; i < length; i++) + for (int i = 0; i < length; i++) Writes.write(idx, i, i, this.delay, true, true); this.permute(array, idx, length); Writes.deleteExternalArray(idx); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/exchange/StoogeSort.java b/src/main/java/io/github/arrayv/sorts/impractical/StoogeSort.java similarity index 59% rename from src/main/java/io/github/arrayv/sorts/exchange/StoogeSort.java rename to src/main/java/io/github/arrayv/sorts/impractical/StoogeSort.java index 80b930da..a87f6099 100644 --- a/src/main/java/io/github/arrayv/sorts/exchange/StoogeSort.java +++ b/src/main/java/io/github/arrayv/sorts/impractical/StoogeSort.java @@ -1,6 +1,7 @@ -package io.github.arrayv.sorts.exchange; +package io.github.arrayv.sorts.impractical; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -14,34 +15,25 @@ */ // Code refactored from: https://en.wikipedia.org/wiki/Stooge_sort +@SortMeta(name = "Stooge", slowSort = true, unreasonableLimit = 1024) public final class StoogeSort extends Sort { public StoogeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Stooge"); - this.setRunAllSortsName("Stooge Sort"); - this.setRunSortName("Stoogesort"); - this.setCategory("Impractical Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(1024); - this.setBogoSort(false); } - private void stoogeSort(int[] A, int i, int j) { - if (Reads.compareIndices(A, i, j, 0.0025, true) == 1) { - Writes.swap(A, i, j, 0.005, true, false); - } + private void stoogeSort(int[] A, int i, int j) { + if (Reads.compareIndices(A, i, j, 0.0025, true) == 1) { + Writes.swap(A, i, j, 0.005, true, false); + } if (j - i + 1 >= 3) { - int t = (j - i + 1) / 3; + int t = (j - i + 1) / 3; - this.stoogeSort(A, i, j-t); - this.stoogeSort(A, i+t, j); - this.stoogeSort(A, i, j-t); - } - } + this.stoogeSort(A, i, j - t); + this.stoogeSort(A, i + t, j); + this.stoogeSort(A, i, j - t); + } + } @Override public void runSort(int[] array, int currentLength, int bucketCount) { diff --git a/src/main/java/io/github/arrayv/sorts/impractical/package-info.java b/src/main/java/io/github/arrayv/sorts/impractical/package-info.java new file mode 100644 index 00000000..1a9c5502 --- /dev/null +++ b/src/main/java/io/github/arrayv/sorts/impractical/package-info.java @@ -0,0 +1,2 @@ +@io.github.arrayv.sortdata.SortPackageMeta(category = "Impractical Sorts") +package io.github.arrayv.sorts.impractical; diff --git a/src/main/java/io/github/arrayv/sorts/insert/AATreeSort.java b/src/main/java/io/github/arrayv/sorts/insert/AATreeSort.java index 91aa6095..cd3ad5d7 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/AATreeSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/AATreeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.insert; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /** @@ -8,19 +9,10 @@ * * @author Sam Walko (Anonymous0726) */ +@SortMeta(listName = "Tree (AA)", runName = "AA-Balanced Tree Sort") public final class AATreeSort extends Sort { public AATreeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("AA Tree"); - this.setRunAllSortsName("Tree Sort (AA Balanced)"); - this.setRunSortName("Tree sort (AA Balanced)"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private Node NULL_NODE = new Node(); // (sub)tree of size 0 @@ -61,12 +53,13 @@ private Node(int[] array, int pointer) { /** * Recursively adds an element to the subtree whose root is this node * - * @param addPointer A pointer to the array telling what element is to be inserted + * @param addPointer A pointer to the array telling what element is to be + * inserted * @return the Node at to be located at this point */ private Node add(int addPointer) { // Case 1: If this is where to add the new element, create a node for it - if(this == NULL_NODE) { + if (this == NULL_NODE) { Highlights.clearMark(2); // No longer comparing to previous leaves return new Node(array, addPointer); // Create the node and return it } @@ -77,7 +70,7 @@ private Node add(int addPointer) { Highlights.markArray(2, pointer); // Case 2: The element is smaller and thus belongs in the left subtree - if(Reads.compareValues(array[addPointer], array[pointer]) == -1) { + if (Reads.compareValues(array[addPointer], array[pointer]) == -1) { Delays.sleep(0.25); // Recursively get the root of the new left subtree @@ -93,9 +86,9 @@ private Node add(int addPointer) { Delays.sleep(0.05); // This handles the case where left subtree increased in height - if(left.level == level) { - if(level != right.level) // Often, a skew is all that's needed to - return skew(); // keep AA tree properties + if (left.level == level) { + if (level != right.level) // Often, a skew is all that's needed to + return skew(); // keep AA tree properties // Other times, we can skip the case where a skew is immediately // followed by a split (i.e., a right rotation immediately @@ -127,7 +120,7 @@ private Node add(int addPointer) { // This handles the case where right subtree's right subtree increased // in height, requiring a split to keep AA tree properties - if(right.right.level == level) + if (right.right.level == level) return split(); // Else, just return this node @@ -193,13 +186,15 @@ private Node split() { * the values of the original array to a sorted temporary array * * @param tempArray the temporary array to write the contents of the subtree to - * @param location a pointer to the location in the temporary array to which the - * contents of the current subtree should be written to + * @param location a pointer to the location in the temporary array to which + * the + * contents of the current subtree should be written to * @return The size of subtree, used to determine where the next value should be - * written to. + * written to. */ private int writeToArray(int[] tempArray, int location) { - if(this == NULL_NODE) return 0; + if (this == NULL_NODE) + return 0; int leftTreeSize = left.writeToArray(tempArray, location); int newLocation = location + leftTreeSize; @@ -220,7 +215,7 @@ public void runSort(int[] array, int length, int bucketCount) { Node root = NULL_NODE; // This loop adds every element of the array to be sorted into the tree - for(int i = 0; i < length; i++) { + for (int i = 0; i < length; i++) { Highlights.markArray(1, i); // Highlights the element being added Node newRoot = root.add(i); @@ -241,7 +236,7 @@ public void runSort(int[] array, int length, int bucketCount) { Highlights.clearMark(1); // No more elements being transferred to temporary array // Write the contents of the temporary array back to the main array - for(int i = 0; i < length; i++) { + for (int i = 0; i < length; i++) { Writes.write(array, i, tempArray[i], 1, true, false); } } diff --git a/src/main/java/io/github/arrayv/sorts/insert/AVLTreeSort.java b/src/main/java/io/github/arrayv/sorts/insert/AVLTreeSort.java index c501fae9..d6f1370b 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/AVLTreeSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/AVLTreeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.insert; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /** @@ -9,19 +10,10 @@ * * @author Sam Walko (Anonymous0726) */ +@SortMeta(listName = "Tree (AVL)", runName = "AVL-Balanced Tree Sort") public final class AVLTreeSort extends Sort { public AVLTreeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("AVL Tree"); - this.setRunAllSortsName("Tree Sort (AVL Balanced)"); - this.setRunSortName("Tree sort (AVL Balanced)"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private Node NULL_NODE = new Node(); // (sub)tree of size 0 @@ -78,13 +70,15 @@ private AddContainer(Node node, boolean heightChange) { /** * Recursively adds an element to the subtree whose root is this node * - * @param addPointer A pointer to the array telling what element is to be inserted + * @param addPointer A pointer to the array telling what element is to be + * inserted * @return an AddContainer containing the node that is now the root of this - * subtree, and the boolean telling whether or not this subtree increased in height + * subtree, and the boolean telling whether or not this subtree + * increased in height */ private AddContainer add(int addPointer) { // Case 1: If this is where to add the new element, create a node for it - if(this == NULL_NODE) { + if (this == NULL_NODE) { Highlights.clearMark(2); // No longer comparing to previous leaves Node newNode = new Node(array, addPointer); // Create the node // Return the node, and the fact that the height obviously changed @@ -98,7 +92,7 @@ private AddContainer add(int addPointer) { Highlights.markArray(2, pointer); // Case 2: The element is smaller and thus belongs in the left subtree - if(Reads.compareValues(array[addPointer], array[pointer]) == -1) { + if (Reads.compareValues(array[addPointer], array[pointer]) == -1) { Delays.sleep(0.25); // Recursively get the root of the new left subtree @@ -115,7 +109,7 @@ private AddContainer add(int addPointer) { // This handles the case where left subtree increased in // height, possibly requiring rotations to keep balance - if(container.heightChange) + if (container.heightChange) return heightChangeLeft(); // In the case where left subtree did not increase in height, @@ -143,7 +137,7 @@ private AddContainer add(int addPointer) { // This handles the case where right subtree increased in // height, possibly requiring rotations to keep balance - if(container.heightChange) + if (container.heightChange) return heightChangeRight(); // In the case where right subtree did not increase in height, @@ -158,17 +152,17 @@ private AddContainer add(int addPointer) { * height has increased. Helper method for add. * * @return an AddContainer including the node to be placed at the position - * and whether or not the left subtree's height has been changed + * and whether or not the left subtree's height has been changed */ private AddContainer heightChangeLeft() { - if(balance != -1) { // No rotation necessary + if (balance != -1) { // No rotation necessary balance--; // Trust me, this boolean works return new AddContainer(this, balance == -1); } // Determine which type of rotation necessary. Note that after // a rotation, the subtree height must not have changed. - if(left.balance == -1) + if (left.balance == -1) // Left-most subtree must be too large, so fix with single rotation return new AddContainer(singleRotateRight(), false); // Middle-left subtree must be too large, so fix with double rotation @@ -180,17 +174,17 @@ private AddContainer heightChangeLeft() { * height has increased. Helper method for add. * * @return an AddContainer including the node to be placed at the position - * and whether or not the right subtree's height has been changed + * and whether or not the right subtree's height has been changed */ private AddContainer heightChangeRight() { - if(balance != 1) { // No rotation necessary + if (balance != 1) { // No rotation necessary balance++; // Trust me, this boolean works return new AddContainer(this, balance == 1); } // Determine which type of rotation necessary. Note that after // a rotation, the subtree height must not have changed. - if(right.balance == 1) + if (right.balance == 1) // Right-most subtree must be too large, so fix with single rotation return new AddContainer(singleRotateLeft(), false); // Middle-right subtree must be too large, so fix with double rotation @@ -278,9 +272,9 @@ private Node doubleRotateRight() { Node b = singleRotateRight(); - if(oldBBalance == -1) + if (oldBBalance == -1) b.right.balance = 1; - if(oldBBalance == 1) + if (oldBBalance == 1) b.left.balance = -1; return b; @@ -305,9 +299,9 @@ private Node doubleRotateLeft() { Node b = singleRotateLeft(); - if(oldBBalance == -1) + if (oldBBalance == -1) b.right.balance = 1; - if(oldBBalance == 1) + if (oldBBalance == 1) b.left.balance = -1; return b; @@ -318,13 +312,15 @@ private Node doubleRotateLeft() { * the values of the original array to a sorted temporary array * * @param tempArray the temporary array to write the contents of the subtree to - * @param location a pointer to the location in the temporary array to which the - * contents of the current subtree should be written to + * @param location a pointer to the location in the temporary array to which + * the + * contents of the current subtree should be written to * @return The size of subtree, used to determine where the next value should be - * written to. + * written to. */ private int writeToArray(int[] tempArray, int location) { - if(this == NULL_NODE) return 0; + if (this == NULL_NODE) + return 0; int leftTreeSize = left.writeToArray(tempArray, location); int newLocation = location + leftTreeSize; @@ -345,7 +341,7 @@ public void runSort(int[] array, int length, int bucketCount) { Node root = NULL_NODE; // This loop adds every element of the array to be sorted into the tree - for(int i = 0; i < length; i++) { + for (int i = 0; i < length; i++) { Highlights.markArray(1, i); // Highlights the element being added Node.AddContainer container = root.add(i); @@ -366,7 +362,7 @@ public void runSort(int[] array, int length, int bucketCount) { Highlights.clearMark(1); // No more elements being transferred to temporary array // Write the contents of the temporary array back to the main array - for(int i = 0; i < length; i++) { + for (int i = 0; i < length; i++) { Writes.write(array, i, tempArray[i], 1, true, false); } } diff --git a/src/main/java/io/github/arrayv/sorts/insert/BinaryDoubleInsertionSort.java b/src/main/java/io/github/arrayv/sorts/insert/BinaryDoubleInsertionSort.java index aaf295f1..09a704f8 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/BinaryDoubleInsertionSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/BinaryDoubleInsertionSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.insert; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,52 +29,43 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Binary Double Insertion") public final class BinaryDoubleInsertionSort extends Sort { public BinaryDoubleInsertionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Binary Double Insertion"); - this.setRunAllSortsName("Binary Double Insertion Sort"); - this.setRunSortName("Binary Double Insertsort"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private int leftBinarySearch(int[] array, int a, int b, int val, double sleep) { - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; Highlights.markArray(1, a); Highlights.markArray(2, m); Highlights.markArray(3, b); Delays.sleep(sleep); - if(Reads.compareValues(val, array[m]) <= 0) + if (Reads.compareValues(val, array[m]) <= 0) b = m; else - a = m+1; + a = m + 1; } return a; } + private int rightBinarySearch(int[] array, int a, int b, int val, double sleep) { - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; Highlights.markArray(1, a); Highlights.markArray(2, m); Highlights.markArray(3, b); Delays.sleep(sleep); - if(Reads.compareValues(val, array[m]) < 0) + if (Reads.compareValues(val, array[m]) < 0) b = m; else - a = m+1; + a = m + 1; } return a; @@ -82,42 +74,45 @@ private int rightBinarySearch(int[] array, int a, int b, int val, double sleep) private void insertToLeft(int[] array, int a, int b, int temp, double sleep) { Highlights.clearMark(2); - while(a > b) Writes.write(array, a, array[--a], sleep, true, false); + while (a > b) + Writes.write(array, a, array[--a], sleep, true, false); Writes.write(array, b, temp, sleep, true, false); } + private void insertToRight(int[] array, int a, int b, int temp, double sleep) { Highlights.clearMark(2); - while(a < b) Writes.write(array, a, array[++a], sleep, true, false); + while (a < b) + Writes.write(array, a, array[++a], sleep, true, false); Writes.write(array, a, temp, sleep, true, false); } public void doubleInsertion(int[] array, int a, int b, double compSleep, double sleep) { - if(b-a < 2) return; + if (b - a < 2) + return; - int j = a+(b-a-2)/2+1, i = a+(b-a-1)/2; + int j = a + (b - a - 2) / 2 + 1, i = a + (b - a - 1) / 2; - if(j > i && Reads.compareIndices(array, i, j, compSleep, true) == 1) + if (j > i && Reads.compareIndices(array, i, j, compSleep, true) == 1) Writes.swap(array, i, j, compSleep, true, false); i--; j++; - while(j < b) { - if(Reads.compareIndices(array, i, j, compSleep, true) == 1) { + while (j < b) { + if (Reads.compareIndices(array, i, j, compSleep, true) == 1) { int l = array[j]; int r = array[i]; - int m = this.rightBinarySearch(array, i+1, j, l, compSleep); - this.insertToRight(array, i, m-1, l, sleep); + int m = this.rightBinarySearch(array, i + 1, j, l, compSleep); + this.insertToRight(array, i, m - 1, l, sleep); this.insertToLeft(array, j, this.leftBinarySearch(array, m, j, r, compSleep), r, sleep); - } - else { + } else { int l = array[i]; int r = array[j]; - int m = this.leftBinarySearch(array, i+1, j, l, compSleep); - this.insertToRight(array, i, m-1, l, sleep); + int m = this.leftBinarySearch(array, i + 1, j, l, compSleep); + this.insertToRight(array, i, m - 1, l, sleep); this.insertToLeft(array, j, this.rightBinarySearch(array, m, j, r, compSleep), r, sleep); } i--; diff --git a/src/main/java/io/github/arrayv/sorts/insert/BinaryInsertionSort.java b/src/main/java/io/github/arrayv/sorts/insert/BinaryInsertionSort.java index 40ea0f08..ca75552e 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/BinaryInsertionSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/BinaryInsertionSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.insert; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.BinaryInsertionSorting; /* @@ -28,20 +29,10 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Binary Insertion") public final class BinaryInsertionSort extends BinaryInsertionSorting { public BinaryInsertionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Binary Insert"); - this.setRunAllSortsName("Binary Insertion Sort"); - this.setRunSortName("Binary Insertsort"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } public void customBinaryInsert(int[] array, int start, int end, double sleep) { diff --git a/src/main/java/io/github/arrayv/sorts/insert/BlockInsertionSort.java b/src/main/java/io/github/arrayv/sorts/insert/BlockInsertionSort.java index e12a6fa2..d2f1e5f5 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/BlockInsertionSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/BlockInsertionSort.java @@ -1,24 +1,17 @@ package io.github.arrayv.sorts.insert; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.GrailSorting; import io.github.arrayv.utils.Rotations; +@SortMeta(name = "Block Insertion") public final class BlockInsertionSort extends GrailSorting { public BlockInsertionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Block Insertion"); - this.setRunAllSortsName("Block Insertion Sort"); - this.setRunSortName("Block Insertsort"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } + @Override protected void grailRotate(int[] array, int pos, int lenA, int lenB) { Rotations.holyGriesMills(array, pos, lenA, lenB, 1, true, false); } @@ -51,11 +44,13 @@ private int findRun(int[] array, int a, int b) { int i = a + 1; if (i == b) return i; - if(Reads.compareIndices(array, i - 1, i++, 1, true) == 1) { - while(i < b && Reads.compareIndices(array, i - 1, i, 1, true) == 1) i++; + if (Reads.compareIndices(array, i - 1, i++, 1, true) == 1) { + while (i < b && Reads.compareIndices(array, i - 1, i, 1, true) == 1) + i++; Writes.reversal(array, a, i - 1, 1, true, false); - } - else while(i < b && Reads.compareIndices(array, i - 1, i, 1, true) <= 0) i++; + } else + while (i < b && Reads.compareIndices(array, i - 1, i, 1, true) <= 0) + i++; Highlights.clearMark(2); return i; } diff --git a/src/main/java/io/github/arrayv/sorts/insert/ClassicTreeSort.java b/src/main/java/io/github/arrayv/sorts/insert/ClassicTreeSort.java index 1b588636..3151acea 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/ClassicTreeSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/ClassicTreeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.insert; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,20 +29,10 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Classic Unbalanced Tree") public final class ClassicTreeSort extends Sort { public ClassicTreeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Classic Tree"); - this.setRunAllSortsName("Classic Unbalanced Tree Sort"); - this.setRunSortName("Classic Unbalanced Treesort"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private int idx; @@ -50,13 +41,15 @@ private void traverse(int[] array, int[] temp, int[] lower, int[] upper, int r) Highlights.markArray(1, r); Delays.sleep(1); - if(lower[r] != 0) this.traverse(array, temp, lower, upper, lower[r]); + if (lower[r] != 0) + this.traverse(array, temp, lower, upper, lower[r]); Writes.write(temp, this.idx++, array[r], 0, false, true); Highlights.markArray(1, r); Delays.sleep(1); - if(upper[r] != 0) this.traverse(array, temp, lower, upper, upper[r]); + if (upper[r] != 0) + this.traverse(array, temp, lower, upper, upper[r]); } @Override @@ -65,21 +58,18 @@ public void runSort(int[] array, int currentLength, int bucketCount) { int[] upper = Writes.createExternalArray(currentLength); int[] next; - for(int i = 1; i < currentLength; i++) { + for (int i = 1; i < currentLength; i++) { Highlights.markArray(2, i); int c = 0; - while(true) { - Highlights.markArray(1, c); - Delays.sleep(0.5); - - next = Reads.compareValues(array[i], array[c]) < 0 ? lower : upper; + while (true) { + next = Reads.compareIndices(array, i, c, 0.5, true) < 0 ? lower : upper; - if(next[c] == 0) { + if (next[c] == 0) { Writes.write(next, c, i, 0, false, true); break; - } - else c = next[c]; + } else + c = next[c]; } } Highlights.clearMark(2); diff --git a/src/main/java/io/github/arrayv/sorts/insert/DoubleInsertionSort.java b/src/main/java/io/github/arrayv/sorts/insert/DoubleInsertionSort.java index 74dfac4e..e9c2e860 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/DoubleInsertionSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/DoubleInsertionSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.insert; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,20 +29,10 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Double Insertion") public final class DoubleInsertionSort extends Sort { public DoubleInsertionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Double Insertion"); - this.setRunAllSortsName("Double Insertion Sort"); - this.setRunSortName("Double Insertsort"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } protected void insertionSort(int[] array, int start, int end, double sleep, boolean auxwrite) { @@ -71,8 +62,7 @@ protected void insertionSort(int[] array, int start, int end, double sleep, bool pos--; } Writes.write(array, pos + 1, rightItem, sleep, true, auxwrite); - } - else { + } else { leftItem = array[left]; rightItem = array[right]; diff --git a/src/main/java/io/github/arrayv/sorts/insert/InsertionSort.java b/src/main/java/io/github/arrayv/sorts/insert/InsertionSort.java index 5fd6cb9a..9abbf58a 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/InsertionSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/InsertionSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.insert; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.InsertionSorting; /* @@ -28,20 +29,10 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Insertion") public final class InsertionSort extends InsertionSorting { public InsertionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Insertion"); - this.setRunAllSortsName("Insertion Sort"); - this.setRunSortName("Insertsort"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } public void customInsertSort(int[] array, int start, int end, double sleep, boolean auxwrite) { diff --git a/src/main/java/io/github/arrayv/sorts/insert/LibrarySort.java b/src/main/java/io/github/arrayv/sorts/insert/LibrarySort.java index 8e6216ff..8d8db8cb 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/LibrarySort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/LibrarySort.java @@ -4,6 +4,7 @@ import java.util.Random; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -31,24 +32,16 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Library") public final class LibrarySort extends Sort { public LibrarySort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Library"); - this.setRunAllSortsName("Library Sort"); - this.setRunSortName("Library Sort"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - //possible implementation of the library sort here https://en.wikipedia.org/wiki/Library_sort - //makes O(1) insertions into gaps of constant size on random data using an extra (1+G)*n space + // possible implementation of the library sort here + // https://en.wikipedia.org/wiki/Library_sort + // makes O(1) insertions into gaps of constant size on random data using an + // extra (1+G)*n space private final int G = 15; private final int R = 4; @@ -56,40 +49,43 @@ public LibrarySort(ArrayVisualizer arrayVisualizer) { private int max; private void shiftExt(int[] array, int a, int m, int b) { - int m1 = a + Math.min(m-a, b-m); - while(m > a) Writes.write(array, --b, array[--m], 0.5, false, true); - while(a < m1) Writes.write(array, a++, this.max, 0.5, false, true); + int m1 = a + Math.min(m - a, b - m); + while (m > a) + Writes.write(array, --b, array[--m], 0.5, false, true); + while (a < m1) + Writes.write(array, a++, this.max, 0.5, false, true); } private int leftBlockSearch(int[] array, int a, int b, int val) { - int s = G+1; + int s = G + 1; - while(a < b) { - int m = a+(((b-a)/s)/2)*s; - Highlights.markArray(2, m/s); + while (a < b) { + int m = a + (((b - a) / s) / 2) * s; + Highlights.markArray(2, m / s); Delays.sleep(0.25); - if(Reads.compareValues(val, array[m]) <= 0) + if (Reads.compareValues(val, array[m]) <= 0) b = m; else - a = m+s; + a = m + s; } Highlights.clearMark(2); return a; } + private int rightBlockSearch(int[] array, int a, int b, int val) { - int s = G+1; + int s = G + 1; - while(a < b) { - int m = a+(((b-a)/s)/2)*s; - Highlights.markArray(2, m/s); + while (a < b) { + int m = a + (((b - a) / s) / 2) * s; + Highlights.markArray(2, m / s); Delays.sleep(0.25); - if(Reads.compareValues(val, array[m]) < 0) + if (Reads.compareValues(val, array[m]) < 0) b = m; else - a = m+s; + a = m + s; } Highlights.clearMark(2); @@ -97,25 +93,26 @@ private int rightBlockSearch(int[] array, int a, int b, int val) { } private int locSearch(int[] array, int a, int b) { - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; - if(Reads.compareOriginalValues(this.max, array[m]) <= 0) + if (Reads.compareOriginalValues(this.max, array[m]) <= 0) b = m; else - a = m+1; + a = m + 1; } return a; } + private int rightBinSearch(int[] array, int a, int b, int val) { - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; - if(Reads.compareValues(val, array[m]) < 0) + if (Reads.compareValues(val, array[m]) < 0) b = m; else - a = m+1; + a = m + 1; } return a; @@ -124,30 +121,31 @@ private int rightBinSearch(int[] array, int a, int b, int val) { private void insertTo(int[] array, int a, int b, boolean aux) { Highlights.clearMark(2); int temp = array[a]; - while(a > b) Writes.write(array, a, array[--a], 0.5, !aux, aux); + while (a > b) + Writes.write(array, a, array[--a], 0.5, !aux, aux); Writes.write(array, b, temp, 0.5, !aux, aux); } private void binaryInsertion(int[] array, int a, int b) { - for(int i = a+1; i < b; i++) + for (int i = a + 1; i < b; i++) this.insertTo(array, i, this.rightBinSearch(array, a, i, array[i]), false); } private void retrieve(int[] array, int[] tmp, int i, int pEnd) { - int loc = i-1; + int loc = i - 1; - for(int k = pEnd-(G+1); k > G;) { - int m = this.locSearch(tmp, k-G, k)-1; - k -= G+1; + for (int k = pEnd - (G + 1); k > G;) { + int m = this.locSearch(tmp, k - G, k) - 1; + k -= G + 1; - while(m >= k) { + while (m >= k) { Writes.write(array, loc--, tmp[m], 0, true, false); Writes.write(tmp, m--, max, 1, false, true); } } - int m = this.locSearch(tmp, 0, G)-1; - while(m >= 0) { + int m = this.locSearch(tmp, 0, G) - 1; + while (m >= 0) { Writes.write(array, loc--, tmp[m], 0, true, false); Writes.write(tmp, m--, max, 1, false, true); } @@ -157,74 +155,74 @@ private void retrieve(int[] array, int[] tmp, int i, int pEnd) { public void runSort(int[] array, int length, int bucketCount) { this.max = length; - //there is supposed to be a shuffle here between [0, length) - //but for the sake of demonstrating O(n^2) worst case it has been removed + // there is supposed to be a shuffle here between [0, length) + // but for the sake of demonstrating O(n^2) worst case it has been removed - int[] tmp = Writes.createExternalArray(length*(G+1)-1); - Arrays.fill(tmp, this.max); //(o_o;) + int[] tmp = Writes.createExternalArray(length * (G + 1) - 1); + Arrays.fill(tmp, this.max); // (o_o;) Random rng = new Random(); int s = length; - while(s >= 32) s = (s-1)/R + 1; + while (s >= 32) + s = (s - 1) / R + 1; - int i = s, j = R*i, pEnd = (s+1)*(G+1)+G; + int i = s, j = R * i, pEnd = (s + 1) * (G + 1) + G; this.binaryInsertion(array, 0, s); - for(int k = 0; k < s; k++) { + for (int k = 0; k < s; k++) { Highlights.markArray(1, k); - Writes.write(tmp, k*(G+1)+G, array[k], 1, false, true); + Writes.write(tmp, k * (G + 1) + G, array[k], 1, false, true); } - for(; i < length; i++) { - if(i == j) { + for (; i < length; i++) { + if (i == j) { this.retrieve(array, tmp, i, pEnd); s = i; - pEnd = (s+1)*(G+1)+G; + pEnd = (s + 1) * (G + 1) + G; j *= R; - for(int k = 0; k < s; k++) { + for (int k = 0; k < s; k++) { Highlights.markArray(1, k); - Writes.write(tmp, k*(G+1)+G, array[k], 1, false, true); + Writes.write(tmp, k * (G + 1) + G, array[k], 1, false, true); } } Highlights.markArray(1, i); - int bLoc = this.leftBlockSearch(tmp, G, pEnd-(G+1), array[i]); + int bLoc = this.leftBlockSearch(tmp, G, pEnd - (G + 1), array[i]); - if(Reads.compareValues(array[i], tmp[bLoc]) == 0) { - int eqEnd = this.rightBlockSearch(tmp, bLoc+(G+1), pEnd-(G+1), array[i]); - bLoc += rng.nextInt((eqEnd-bLoc)/(G+1))*(G+1); + if (Reads.compareValues(array[i], tmp[bLoc]) == 0) { + int eqEnd = this.rightBlockSearch(tmp, bLoc + (G + 1), pEnd - (G + 1), array[i]); + bLoc += rng.nextInt((eqEnd - bLoc) / (G + 1)) * (G + 1); } - int loc = this.locSearch(tmp, bLoc-G, bLoc); + int loc = this.locSearch(tmp, bLoc - G, bLoc); - if(loc == bLoc) { - do bLoc += G+1; - while(bLoc < pEnd && this.locSearch(tmp, bLoc-G, bLoc) == bLoc); + if (loc == bLoc) { + do + bLoc += G + 1; + while (bLoc < pEnd && this.locSearch(tmp, bLoc - G, bLoc) == bLoc); - if(bLoc == pEnd) { + if (bLoc == pEnd) { this.retrieve(array, tmp, i, pEnd); s = i; - pEnd = (s+1)*(G+1)+G; - j = R*i; + pEnd = (s + 1) * (G + 1) + G; + j = R * i; - for(int k = 0; k < s; k++) { + for (int k = 0; k < s; k++) { Highlights.markArray(1, k); - Writes.write(tmp, k*(G+1)+G, array[k], 1, false, true); + Writes.write(tmp, k * (G + 1) + G, array[k], 1, false, true); } - } - else { - int rotP = this.locSearch(tmp, bLoc-G, bLoc); - int rotS = bLoc - Math.max(rotP, bLoc - G/2); - this.shiftExt(tmp, loc-rotS, bLoc-rotS, bLoc); + } else { + int rotP = this.locSearch(tmp, bLoc - G, bLoc); + int rotS = bLoc - Math.max(rotP, bLoc - G / 2); + this.shiftExt(tmp, loc - rotS, bLoc - rotS, bLoc); } i--; - } - else { + } else { Writes.write(tmp, loc, array[i], 1, false, true); - this.insertTo(tmp, loc, this.rightBinSearch(tmp, bLoc-G, loc, tmp[loc]), true); + this.insertTo(tmp, loc, this.rightBinSearch(tmp, bLoc - G, loc, tmp[loc]), true); } } this.retrieve(array, tmp, length, pEnd); diff --git a/src/main/java/io/github/arrayv/sorts/insert/PatienceSort.java b/src/main/java/io/github/arrayv/sorts/insert/PatienceSort.java index e6f8211b..006c7995 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/PatienceSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/PatienceSort.java @@ -6,6 +6,7 @@ import java.util.Stack; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -19,20 +20,10 @@ Free Documentation License". * */ - +@SortMeta(name = "Patience") public final class PatienceSort extends Sort { public PatienceSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Patience"); - this.setRunAllSortsName("Patience Sort"); - this.setRunSortName("Patience Sort"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } final private class Pile extends Stack implements Comparable { @@ -53,12 +44,12 @@ private void binarySearch(ArrayList list, Pile find) { int change = list.size() / 4; long compsBefore = Reads.getComparisons(); - while(list.get(at).compare(find) != 0 && change > 0){ + while (list.get(at).compare(find) != 0 && change > 0) { Reads.setComparisons(compsBefore); Highlights.markArray(1, at); Delays.sleep(0.5); - if(list.get(at).compare(find) < 0) + if (list.get(at).compare(find) < 0) at += change; else at -= change; @@ -86,16 +77,16 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.changeAllocAmount(1); int i = Collections.binarySearch(piles, newPile); - if(!piles.isEmpty()) { + if (!piles.isEmpty()) { this.binarySearch(piles, newPile); } - if (i < 0) i = ~i; + if (i < 0) + i = ~i; if (i != piles.size()) { Writes.mockWrite(length, Math.min(piles.get(i).size(), length - 1), array[x], 0); piles.get(i).push(array[x]); Writes.changeAllocAmount(1); - } - else { + } else { Writes.mockWrite(length, Math.min(piles.size(), length - 1), newPile.get(0), 0); piles.add(newPile); Writes.changeAllocAmount(1); diff --git a/src/main/java/io/github/arrayv/sorts/insert/RecursiveShellSort.java b/src/main/java/io/github/arrayv/sorts/insert/RecursiveShellSort.java index f3f09f2a..e253dd1b 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/RecursiveShellSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/RecursiveShellSort.java @@ -1,42 +1,34 @@ package io.github.arrayv.sorts.insert; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Recursive Shell") public final class RecursiveShellSort extends Sort { public RecursiveShellSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Recursive Shell"); - this.setRunAllSortsName("yuji's Recursive Shell Sort"); - this.setRunSortName("yuji's Recursive Shell Sort"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } public void gappedInsertionSort(int[] arr, int a, int b, int gap) { - for (int i = a+gap; i < b; i+=gap) { + for (int i = a + gap; i < b; i += gap) { int key = arr[i]; - int j = i-gap; + int j = i - gap; while (j >= a && Reads.compareValues(key, arr[j]) < 0) { - Writes.write(arr, j+gap, arr[j], 0.5, true, false); - j-=gap; + Writes.write(arr, j + gap, arr[j], 0.5, true, false); + j -= gap; } - Writes.write(arr, j+gap, key, 0.5, true, false); + Writes.write(arr, j + gap, key, 0.5, true, false); } Highlights.clearAllMarks(); } public void recursiveShellSort(int[] array, int start, int end, int g) { - if (start+g <= end) { - this.recursiveShellSort(array, start, end, 3*g); - this.recursiveShellSort(array, start+g, end, 3*g); - this.recursiveShellSort(array, start+(2*g), end, 3*g); + if (start + g <= end) { + this.recursiveShellSort(array, start, end, 3 * g); + this.recursiveShellSort(array, start + g, end, 3 * g); + this.recursiveShellSort(array, start + (2 * g), end, 3 * g); this.gappedInsertionSort(array, start, end, g); } } diff --git a/src/main/java/io/github/arrayv/sorts/insert/RedBlackTreeSort.java b/src/main/java/io/github/arrayv/sorts/insert/RedBlackTreeSort.java index 848b635a..ab1451fa 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/RedBlackTreeSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/RedBlackTreeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.insert; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /** @@ -9,19 +10,10 @@ * * @author Sam Walko (Anonymous0726) */ +@SortMeta(listName = "Tree (Red-Black)", runName = "Red-Black-Balanced Tree Sort") public final class RedBlackTreeSort extends Sort { public RedBlackTreeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Red-Black Tree"); - this.setRunAllSortsName("Tree Sort (Red-Black Balanced)"); - this.setRunSortName("Tree sort (Red-Black Balanced)"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private Node NULL_NODE = new Node(); // (sub)tree of size 0 @@ -75,13 +67,15 @@ private AddContainer(Node node, boolean needsFix) { /** * Recursively adds an element to the subtree whose root is this node * - * @param addPointer A pointer to the array telling what element is to be inserted + * @param addPointer A pointer to the array telling what element is to be + * inserted * @return an AddContainer containing the node that is now the root of this - * subtree, and the boolean telling whether or not this subtree increased in height + * subtree, and the boolean telling whether or not this subtree + * increased in height */ private AddContainer add(int addPointer) { // Case 1: If this is where to add the new element, create a node for it - if(this == NULL_NODE) { + if (this == NULL_NODE) { Highlights.clearMark(1); // No longer comparing to previous leaves Node newNode = new Node(array, addPointer); // Create the node // Return the node, and the fact that a subtree of size 1 @@ -98,7 +92,7 @@ private AddContainer add(int addPointer) { // cascading rotations, without losing black balance. // (Note that this only occurs when there's actually a node here // already, hence this check is performed after the check for case 1.) - if(!isRed && left.isRed && right.isRed) { + if (!isRed && left.isRed && right.isRed) { Highlights.markArray(3, left.pointer); Highlights.markArray(4, right.pointer); @@ -112,7 +106,7 @@ private AddContainer add(int addPointer) { } // Case 2: The element is smaller and thus belongs in the left subtree - if(Reads.compareValues(array[addPointer], array[pointer]) == -1) { + if (Reads.compareValues(array[addPointer], array[pointer]) == -1) { Delays.sleep(0.25); // Recursively get the root of the new left subtree @@ -129,8 +123,8 @@ private AddContainer add(int addPointer) { // If the tree is determined to need rebalancing, then first // determine which type of rotation is necessary, then perform it. - if(container.needsFix) { - if(left.left.isRed) + if (container.needsFix) { + if (left.left.isRed) return new AddContainer(singleRotateRight(), false); return new AddContainer(doubleRotateRight(), false); } @@ -158,8 +152,8 @@ private AddContainer add(int addPointer) { // If the tree is determined to need rebalancing, then first // determine which type of rotation is necessary, then perform it. - if(container.needsFix) { - if(right.right.isRed) + if (container.needsFix) { + if (right.right.isRed) return new AddContainer(singleRotateLeft(), false); return new AddContainer(doubleRotateLeft(), false); } @@ -277,13 +271,15 @@ private Node doubleRotateLeft() { * the values of the original array to a sorted temporary array * * @param tempArray the temporary array to write the contents of the subtree to - * @param location a pointer to the location in the temporary array to which the - * contents of the current subtree should be written to + * @param location a pointer to the location in the temporary array to which + * the + * contents of the current subtree should be written to * @return The size of subtree, used to determine where the next value should be - * written to. + * written to. */ private int writeToArray(int[] tempArray, int location) { - if(this == NULL_NODE) return 0; + if (this == NULL_NODE) + return 0; int leftTreeSize = left.writeToArray(tempArray, location); int newLocation = location + leftTreeSize; @@ -304,7 +300,7 @@ public void runSort(int[] array, int length, int bucketCount) { Node root = NULL_NODE; // This loop adds every element of the array to be sorted into the tree - for(int i = 0; i < length; i++) { + for (int i = 0; i < length; i++) { Highlights.markArray(1, i); // Highlights the element being added Node.AddContainer container = root.add(i); @@ -329,7 +325,7 @@ public void runSort(int[] array, int length, int bucketCount) { Highlights.clearMark(1); // No more elements being transferred to temporary array // Write the contents of the temporary array back to the main array - for(int i = 0; i < length; i++) { + for (int i = 0; i < length; i++) { Writes.write(array, i, tempArray[i], 1, true, false); } } diff --git a/src/main/java/io/github/arrayv/sorts/insert/ShellSort.java b/src/main/java/io/github/arrayv/sorts/insert/ShellSort.java index 4f9a2042..8af5992e 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/ShellSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/ShellSort.java @@ -1,24 +1,15 @@ package io.github.arrayv.sorts.insert; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.ShellSorting; // Shell sort variant retrieved from: // https://www.cs.princeton.edu/~rs/talks/shellsort.ps - +@SortMeta(name = "Shell") public final class ShellSort extends ShellSorting { public ShellSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Shell"); - this.setRunAllSortsName("Shell Sort"); - this.setRunSortName("Shellsort"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } public void finishQuickShell(int[] array, int currentLen) { diff --git a/src/main/java/io/github/arrayv/sorts/insert/ShellSortParallel.java b/src/main/java/io/github/arrayv/sorts/insert/ShellSortParallel.java index 6d5b1044..ebc1350a 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/ShellSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/insert/ShellSortParallel.java @@ -1,21 +1,13 @@ package io.github.arrayv.sorts.insert; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.ShellSorting; +@SortMeta(name = "Parallel Shell", unreasonableLimit = 4096) public final class ShellSortParallel extends ShellSorting { public ShellSortParallel(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Shell (Parallel)"); - this.setRunAllSortsName("Parallel Shell Sort"); - this.setRunSortName("Parallel Shellsort"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private int[] array; @@ -23,27 +15,29 @@ public ShellSortParallel(ArrayVisualizer arrayVisualizer) { private class GappedInsertionSort extends Thread { private int a, b, g; + GappedInsertionSort(int a, int b, int g) { this.a = a; this.b = b; this.g = g; } + + @Override public void run() { ShellSortParallel.this.gappedInsertion(a, b, g); } } private void gappedInsertion(int a, int b, int g) { - for(int i = a+g; i < b; i+=g) { - if(Reads.compareIndices(this.array, i-g, i, 1, true) > 0) { + for (int i = a + g; i < b; i += g) { + if (Reads.compareIndices(this.array, i - g, i, 1, true) > 0) { int tmp = this.array[i], j = i; Highlights.clearMark(2); do { - Writes.write(this.array, j, this.array[j-g], 1, true, false); + Writes.write(this.array, j, this.array[j - g], 1, true, false); j -= g; - } - while(j-g >= a && Reads.compareValues(this.array[j-g], tmp) > 0); + } while (j - g >= a && Reads.compareValues(this.array[j - g], tmp) > 0); Writes.write(this.array, j, tmp, 1, true, false); } @@ -57,21 +51,22 @@ public void runSort(int[] array, int currentLength, int bucketCount) { int k = 0; - for(; this.gaps[k] >= currentLength; k++); - for(; k < this.gaps.length; k++) { + for (; this.gaps[k] >= currentLength; k++) + ; + for (; k < this.gaps.length; k++) { int g = this.gaps[k]; - int t = Math.min(g, currentLength-g); + int t = Math.min(g, currentLength - g); GappedInsertionSort[] ins = new GappedInsertionSort[t]; - for(int i = 0; i < t; i++) + for (int i = 0; i < t; i++) ins[i] = new GappedInsertionSort(i, currentLength, g); - for(GappedInsertionSort s : ins) s.start(); - for(GappedInsertionSort s : ins) { + for (GappedInsertionSort s : ins) + s.start(); + for (GappedInsertionSort s : ins) { try { s.join(); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } diff --git a/src/main/java/io/github/arrayv/sorts/insert/SimplifiedLibrarySort.java b/src/main/java/io/github/arrayv/sorts/insert/SimplifiedLibrarySort.java index 3c72216f..d1f6f75e 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/SimplifiedLibrarySort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/SimplifiedLibrarySort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.insert; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,43 +29,35 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Simplified Library") public final class SimplifiedLibrarySort extends Sort { public SimplifiedLibrarySort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Simplified Library"); - this.setRunAllSortsName("Simplified Library Sort"); - this.setRunSortName("Simplified Library Sort"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - //simple library sort with O(n) extra memory + counter & pointer array (n size combined) + // simple library sort with O(n) extra memory + counter & pointer array (n size + // combined) - private final int R = 4; //rebalancing factor (gaps have dynamic size) + private final int R = 4; // rebalancing factor (gaps have dynamic size) private BinaryInsertionSort binaryInsert; private int getMinLevel(int n) { - while(n >= 32) n = (n-1)/R+1; + while (n >= 32) + n = (n - 1) / R + 1; return n; } private int binarySearch(int[] array, int a, int b, int val, double sleep) { - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; Highlights.markArray(3, m); Delays.sleep(sleep); - if(Reads.compareValues(val, array[m]) < 0) + if (Reads.compareValues(val, array[m]) < 0) b = m; else - a = m+1; + a = m + 1; } Highlights.clearMark(3); @@ -72,33 +65,33 @@ private int binarySearch(int[] array, int a, int b, int val, double sleep) { } private void rebalance(int[] array, int[] temp, int[] cnts, int[] locs, int m, int b) { - //do a partial sum to find locations + // do a partial sum to find locations Highlights.clearMark(2); - for(int i = 0; i < m; i++) - Writes.write(cnts, i+1, cnts[i+1]+cnts[i]+1, 1, true, true); + for (int i = 0; i < m; i++) + Writes.write(cnts, i + 1, cnts[i + 1] + cnts[i] + 1, 1, true, true); - //place books in gaps into their correct locations - for(int i = m, j = 0; i < b; i++, j++) { + // place books in gaps into their correct locations + for (int i = m, j = 0; i < b; i++, j++) { Highlights.markArray(2, i); Writes.write(temp, cnts[locs[j]], array[i], 1, true, true); - Writes.write(cnts, locs[j], cnts[locs[j]]+1, 0, false, true); + Writes.write(cnts, locs[j], cnts[locs[j]] + 1, 0, false, true); } - for(int i = 0; i < m; i++) { + for (int i = 0; i < m; i++) { Highlights.markArray(2, i); Writes.write(temp, cnts[i], array[i], 1, true, true); - Writes.write(cnts, i, cnts[i]+1, 0, false, true); + Writes.write(cnts, i, cnts[i] + 1, 0, false, true); } Highlights.clearMark(2); - //copy back to array & sort the gaps + // copy back to array & sort the gaps Writes.arraycopy(temp, 0, array, 0, b, 1, true, false); - this.binaryInsert.customBinaryInsert(array, 0, cnts[0]-1, 0.5); - for(int i = 0; i < m-1; i++) - this.binaryInsert.customBinaryInsert(array, cnts[i], cnts[i+1]-1, 0.5); - this.binaryInsert.customBinaryInsert(array, cnts[m-1], cnts[m], 0.5); + this.binaryInsert.customBinaryInsert(array, 0, cnts[0] - 1, 0.5); + for (int i = 0; i < m - 1; i++) + this.binaryInsert.customBinaryInsert(array, cnts[i], cnts[i + 1] - 1, 0.5); + this.binaryInsert.customBinaryInsert(array, cnts[m - 1], cnts[m], 0.5); - //reset count array - for(int i = 0; i < m+2; i++) + // reset count array + for (int i = 0; i < m + 2; i++) Writes.write(cnts, i, 0, 0, false, true); } @@ -106,7 +99,7 @@ private void rebalance(int[] array, int[] temp, int[] cnts, int[] locs, int m, i public void runSort(int[] array, int length, int bucketCount) { this.binaryInsert = new BinaryInsertionSort(this.arrayVisualizer); - if(length < 32) { + if (length < 32) { this.binaryInsert.customBinaryInsert(array, 0, length, 1); return; } @@ -115,24 +108,25 @@ public void runSort(int[] array, int length, int bucketCount) { this.binaryInsert.customBinaryInsert(array, 0, j, 1); int maxLevel = j; - for(; maxLevel*R < length; maxLevel *= R); + for (; maxLevel * R < length; maxLevel *= R) + ; int[] temp = Writes.createExternalArray(length), - cnts = Writes.createExternalArray(maxLevel+2), - locs = Writes.createExternalArray(length-maxLevel); + cnts = Writes.createExternalArray(maxLevel + 2), + locs = Writes.createExternalArray(length - maxLevel); - for(int i = j, k = 0; i < length; i++) { - if(R*j == i) { + for (int i = j, k = 0; i < length; i++) { + if (R * j == i) { this.rebalance(array, temp, cnts, locs, j, i); j = i; k = 0; } - //search which gap a book goes and save the result + // search which gap a book goes and save the result Highlights.markArray(2, i); int loc = this.binarySearch(array, 0, j, array[i], 0.5); - Writes.write(cnts, loc+1, cnts[loc+1]+1, 0, false, true); + Writes.write(cnts, loc + 1, cnts[loc + 1] + 1, 0, false, true); Writes.write(locs, k++, loc, 0, false, true); } this.rebalance(array, temp, cnts, locs, j, length); diff --git a/src/main/java/io/github/arrayv/sorts/insert/SplaySort.java b/src/main/java/io/github/arrayv/sorts/insert/SplaySort.java index ee927a65..63f03d53 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/SplaySort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/SplaySort.java @@ -1,28 +1,22 @@ package io.github.arrayv.sorts.insert; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Splay") public final class SplaySort extends Sort { - //Splay sort is an adaptive algorithm based on splay tree data structure - //It is O(n log n) in the average/worst case, and O(n) in the best case when the data is mostly sorted + // Splay sort is an adaptive algorithm based on splay tree data structure + // It is O(n log n) in the average/worst case, and O(n) in the best case when + // the data is mostly sorted public SplaySort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Splay"); - this.setRunAllSortsName("Splay Sort"); - this.setRunSortName("Splaysort"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - // Splay tree code retrieved from https://www.geeksforgeeks.org/splay-tree-set-2-insert-delete/ + // Splay tree code retrieved from + // https://www.geeksforgeeks.org/splay-tree-set-2-insert-delete/ final private class Node { int key; @@ -41,7 +35,8 @@ public Node(int item) { private Node treeWrite(Node element, int at) { Node node = new Node(0); - if(at > 0 && at < this.length) Highlights.markArray(1, at - 1); + if (at > 0 && at < this.length) + Highlights.markArray(1, at - 1); Writes.changeAuxWrites(1); Writes.startLap(); node = element; @@ -78,7 +73,7 @@ private Node splay(Node root, int key, int depth) { if (Reads.compareValues(root.key, key) == 1) { if (root.left == null) { - return root; + return root; } if (Reads.compareValues(root.left.key, key) == 1) { @@ -93,7 +88,7 @@ private Node splay(Node root, int key, int depth) { return (root.left == null) ? root : rightRotate(root, depth); } else { if (root.right == null) { - return root; + return root; } if (Reads.compareValues(root.right.key, key) == 1) { @@ -139,7 +134,7 @@ private void traverseRec(Node root, int[] array) { } private void treeIns(int arr[]) { - for(int i = 0; i < this.length; i++) { + for (int i = 0; i < this.length; i++) { Highlights.markArray(2, i); this.insert(arr[i]); } diff --git a/src/main/java/io/github/arrayv/sorts/insert/TreeSort.java b/src/main/java/io/github/arrayv/sorts/insert/TreeSort.java index 57d0315c..c1004f0c 100644 --- a/src/main/java/io/github/arrayv/sorts/insert/TreeSort.java +++ b/src/main/java/io/github/arrayv/sorts/insert/TreeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.insert; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /** @@ -9,19 +10,10 @@ * * @author Sam Walko (Anonymous0726) */ +@SortMeta(listName = "Tree (Unbalanced)", runName = "Unbalanced Tree Sort") public final class TreeSort extends Sort { public TreeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Tree"); - this.setRunAllSortsName("Tree Sort (Unbalanced)"); - this.setRunSortName("Tree sort (Unbalanced)"); - this.setCategory("Insertion Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private Node NULL_NODE = new Node(); @@ -57,12 +49,13 @@ private Node(int[] array, int pointer) { /** * Recursively adds an element to the subtree whose root is this node * - * @param addPointer A pointer to the array telling what element is to be inserted + * @param addPointer A pointer to the array telling what element is to be + * inserted * @return the Node to be added at this point */ private Node add(int addPointer) { // Case 1: If this is where to add the new element, create a node for it - if(this == NULL_NODE) { + if (this == NULL_NODE) { Highlights.clearMark(1); // No longer comparing to previous leaves return new Node(array, addPointer); // Create the new node and return it } @@ -73,7 +66,7 @@ private Node add(int addPointer) { Highlights.markArray(2, pointer); // Case 2: The element is smaller and thus belongs in the left subtree - if(Reads.compareValues(array[addPointer], array[pointer]) == -1) { + if (Reads.compareValues(array[addPointer], array[pointer]) == -1) { Delays.sleep(0.25); // Recursively get the root of the new left subtree @@ -113,13 +106,15 @@ private Node add(int addPointer) { * the values of the original array to a sorted temporary array * * @param tempArray the temporary array to write the contents of the subtree to - * @param location a pointer to the location in the temporary array to which the - * contents of the current subtree should be written to + * @param location a pointer to the location in the temporary array to which + * the + * contents of the current subtree should be written to * @return The size of subtree, used to determine where the next value should be - * written to. + * written to. */ private int writeToArray(int[] tempArray, int location) { - if(this == NULL_NODE) return 0; + if (this == NULL_NODE) + return 0; int leftTreeSize = left.writeToArray(tempArray, location); int newLocation = location + leftTreeSize; @@ -139,8 +134,8 @@ public void runSort(int[] array, int length, int bucketCount) { // Creates a tree of size 0, to which all elements will be added Node root = NULL_NODE; - // This loop adds every element of the array to be sorted into the tree - for(int i = 0; i < length; i++) { + // This loop adds every element of the array to be sorted into the tree + for (int i = 0; i < length; i++) { Highlights.markArray(1, i); Node newRoot = root.add(i); @@ -161,7 +156,7 @@ public void runSort(int[] array, int length, int bucketCount) { Highlights.clearMark(1); // No more elements being transferred to temporary array // Write the contents of the temporary array back to the main array - for(int i = 0; i < length; i++) { + for (int i = 0; i < length; i++) { Writes.write(array, i, tempArray[i], 1, true, false); } } diff --git a/src/main/java/io/github/arrayv/sorts/insert/package-info.java b/src/main/java/io/github/arrayv/sorts/insert/package-info.java new file mode 100644 index 00000000..ee7f0365 --- /dev/null +++ b/src/main/java/io/github/arrayv/sorts/insert/package-info.java @@ -0,0 +1,2 @@ +@io.github.arrayv.sortdata.SortPackageMeta(category = "Insertion Sorts") +package io.github.arrayv.sorts.insert; diff --git a/src/main/java/io/github/arrayv/sorts/merge/AndreySort.java b/src/main/java/io/github/arrayv/sorts/merge/AndreySort.java index 7e0019b6..37739069 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/AndreySort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/AndreySort.java @@ -1,28 +1,20 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Andrey Astrelin's In-Place Merge") public class AndreySort extends Sort { public AndreySort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Andrey's Merge"); - this.setRunAllSortsName("Andrey Astrelin's In-Place Merge Sort"); - this.setRunSortName("Andreysort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void sort(int[] arr, int a, int b) { - while(b > 1) { + while (b > 1) { int k = 0; - for(int i = 1; i < b; i++) { - if(Reads.compareValues(arr[a + k], arr[a + i]) > 0) { + for (int i = 1; i < b; i++) { + if (Reads.compareValues(arr[a + k], arr[a + i]) > 0) { k = i; } } @@ -33,7 +25,7 @@ private void sort(int[] arr, int a, int b) { } private void aswap(int[] arr, int arr1, int arr2, int l) { - while(l-- > 0) { + while (l-- > 0) { Writes.swap(arr, arr1++, arr2++, 1, true, false); } } @@ -41,16 +33,15 @@ private void aswap(int[] arr, int arr1, int arr2, int l) { // arr1(-l1..0] :merge: arr2(-l2..0] -> arr2(-l2..l1] private int backmerge(int[] arr, int arr1, int l1, int arr2, int l2) { int arr0 = arr2 + l1; - for(;;) { - if(Reads.compareValues(arr[arr1], arr[arr2]) > 0) { + for (;;) { + if (Reads.compareValues(arr[arr1], arr[arr2]) > 0) { Writes.swap(arr, arr1--, arr0--, 1, true, false); - if(--l1 == 0) { + if (--l1 == 0) { return 0; } - } - else { + } else { Writes.swap(arr, arr2--, arr0--, 1, true, false); - if(--l2 == 0) { + if (--l2 == 0) { break; } } @@ -58,25 +49,25 @@ private int backmerge(int[] arr, int arr1, int l1, int arr2, int l2) { int res = l1; do { Writes.swap(arr, arr1--, arr0--, 1, true, false); - } while(--l1 != 0); + } while (--l1 != 0); return res; } // merge arr[p0..p1) by buffer arr[p1..p1+r) private void rmerge(int[] arr, int a, int l, int r) { - for(int i = 0; i < l; i += r) { + for (int i = 0; i < l; i += r) { // select smallest arr[p0+n*r] int q = i; - for(int j = i + r; j < l; j += r) { - if(Reads.compareValues(arr[a + q], arr[a + j]) > 0) { + for (int j = i + r; j < l; j += r) { + if (Reads.compareValues(arr[a + q], arr[a + j]) > 0) { q = j; } } - if(q != i) { + if (q != i) { aswap(arr, a + i, a + q, r); // swap it with current position } - if(i != 0) { - aswap(arr, a + l, a + i, r); // swap current position with buffer + if (i != 0) { + aswap(arr, a + l, a + i, r); // swap current position with buffer backmerge(arr, a + (l + r - 1), r, a + (i - 1), r); // buffer :merge: arr[i-r..i) -> arr[i-r..i+r) } } @@ -85,16 +76,17 @@ private void rmerge(int[] arr, int a, int l, int r) { private int rbnd(int len) { len = len / 2; int k = 0; - for(int i = 1; i < len; i *= 2) { + for (int i = 1; i < len; i *= 2) { k++; } len /= k; - for(k = 1; k <= len; k *= 2); + for (k = 1; k <= len; k *= 2) + ; return k; } private void msort(int[] arr, int a, int len) { - if(len < 12) { + if (len < 12) { sort(arr, a, len); return; } @@ -102,11 +94,11 @@ private void msort(int[] arr, int a, int len) { int r = rbnd(len); int lr = (len / r - 1) * r; - for(int p = 2; p <= lr; p += 2) { - if(Reads.compareValues(arr[a + (p - 2)], arr[a + (p - 1)]) > 0) { + for (int p = 2; p <= lr; p += 2) { + if (Reads.compareValues(arr[a + (p - 2)], arr[a + (p - 1)]) > 0) { Writes.swap(arr, a + (p - 2), a + (p - 1), 1, true, false); } - if((p & 2) != 0) { + if ((p & 2) != 0) { continue; } @@ -115,9 +107,9 @@ private void msort(int[] arr, int a, int len) { int m = len - p; int q = 2; - for(;;) { + for (;;) { int q0 = 2 * q; - if(q0 > m || (p & q0) != 0) { + if (q0 > m || (p & q0) != 0) { break; } backmerge(arr, a + (p - q - 1), q, a + (p + q - 1), q); @@ -128,17 +120,17 @@ private void msort(int[] arr, int a, int len) { int q1 = q; q *= 2; - while((q & p) == 0) { + while ((q & p) == 0) { q *= 2; rmerge(arr, a + (p - q), q, q1); } } int q1 = 0; - for(int q = r; q< lr; q *= 2) { - if((lr & q) != 0) { + for (int q = r; q < lr; q *= 2) { + if ((lr & q) != 0) { q1 += q; - if(q1 != q) { + if (q1 != q) { rmerge(arr, a + (lr - q1), q1, r); } } diff --git a/src/main/java/io/github/arrayv/sorts/merge/BlockSwapMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/BlockSwapMergeSort.java index dcba6a75..ca8948b2 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/BlockSwapMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/BlockSwapMergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -30,36 +31,27 @@ this software and associated documentation files (the "Software"), to deal in */ //refactored version of original implementation by @Piotr Grochowski (in place merge 2) +@SortMeta(name = "Block-Swap Merge") public final class BlockSwapMergeSort extends Sort { public BlockSwapMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Block-Swap Merge"); - this.setRunAllSortsName("Block-Swap Merge Sort"); - this.setRunSortName("Block-Swap Mergesort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void multiSwap(int[] array, int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(array, a+i, b+i, 1, true, false); + for (int i = 0; i < len; i++) + Writes.swap(array, a + i, b + i, 1, true, false); } private int binarySearchMid(int[] array, int start, int mid, int end) { - int a = 0, b = Math.min(mid-start, end-mid), m = a+(b-a)/2; + int a = 0, b = Math.min(mid - start, end - mid), m = a + (b - a) / 2; - while(b > a) { - if(Reads.compareValues(array[mid-m-1], array[mid+m]) == 1) - a = m+1; + while (b > a) { + if (Reads.compareValues(array[mid - m - 1], array[mid + m]) == 1) + a = m + 1; else b = m; - m = a+(b-a)/2; + m = a + (b - a) / 2; } return m; @@ -68,9 +60,9 @@ private int binarySearchMid(int[] array, int start, int mid, int end) { public void multiSwapMerge(int[] array, int start, int mid, int end) { int m = this.binarySearchMid(array, start, mid, end); - while(m > 0) { - this.multiSwap(array, mid-m, mid, m); - this.multiSwapMerge(array, mid, mid+m, end); + while (m > 0) { + this.multiSwap(array, mid - m, mid, m); + this.multiSwapMerge(array, mid, mid + m, end); end = mid; mid -= m; @@ -80,14 +72,14 @@ public void multiSwapMerge(int[] array, int start, int mid, int end) { } public void multiSwapMergeSort(int[] array, int a, int b) { - int len = b-a, i; + int len = b - a, i; - for(int j = 1; j < len; j *= 2) { - for(i = a; i + 2*j <= b; i += 2*j) - this.multiSwapMerge(array, i, i+j, i+2*j); + for (int j = 1; j < len; j *= 2) { + for (i = a; i + 2 * j <= b; i += 2 * j) + this.multiSwapMerge(array, i, i + j, i + 2 * j); - if(i + j < b) - this.multiSwapMerge(array, i, i+j, b); + if (i + j < b) + this.multiSwapMerge(array, i, i + j, b); } } diff --git a/src/main/java/io/github/arrayv/sorts/merge/BottomUpMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/BottomUpMergeSort.java index 71d67e7b..92ac0d6e 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/BottomUpMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/BottomUpMergeSort.java @@ -1,24 +1,16 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Bottom-Up Merge") public final class BottomUpMergeSort extends Sort { private int[] scratchArray; private int copyLength; public BottomUpMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Bottom-up Merge"); - this.setRunAllSortsName("Bottom-up Merge Sort"); - this.setRunSortName("Bottom-up Mergesort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void merge(int[] array, int currentLength, int index, int mergeSize) { @@ -29,37 +21,31 @@ private void merge(int[] array, int currentLength, int index, int mergeSize) { int scratchIndex = left; - if(right < end) { - while(left < mid && right < end) { - this.Highlights.markArray(1, left); - this.Highlights.markArray(2, right); - this.Delays.sleep(1); - - if(this.Reads.compareValues(array[left], array[right]) <= 0) { + if (right < end) { + while (left < mid && right < end) { + if (this.Reads.compareIndices(array, left, right, 1, true) <= 0) { this.Writes.write(this.scratchArray, scratchIndex++, array[left++], 0, false, true); - } - else { + } else { this.Writes.write(this.scratchArray, scratchIndex++, array[right++], 0, false, true); } } - if(left < mid) { - while(left < mid) { + if (left < mid) { + while (left < mid) { this.Highlights.markArray(1, left); this.Delays.sleep(1); this.Writes.write(this.scratchArray, scratchIndex++, array[left++], 0, false, true); } } - if(right < end) { - while(right < end) { + if (right < end) { + while (right < end) { this.Highlights.markArray(2, right); this.Delays.sleep(1); this.Writes.write(this.scratchArray, scratchIndex++, array[right++], 0, false, true); } } - } - else { + } else { this.copyLength = left; } } @@ -69,27 +55,27 @@ public void runSort(int[] array, int currentLength, int bucketCount) { this.scratchArray = Writes.createExternalArray(currentLength); int mergeSize = 2; - while(mergeSize <= currentLength) { + while (mergeSize <= currentLength) { this.copyLength = currentLength; - for(int i = 0; i < currentLength; i += mergeSize) { + for (int i = 0; i < currentLength; i += mergeSize) { this.merge(array, currentLength, i, mergeSize); } this.Highlights.clearMark(2); - for(int i = 0; i < this.copyLength; i++) { + for (int i = 0; i < this.copyLength; i++) { this.Writes.write(array, i, this.scratchArray[i], 1, true, false); } mergeSize *= 2; } - if((mergeSize / 2) != currentLength) { + if ((mergeSize / 2) != currentLength) { this.merge(array, currentLength, 0, mergeSize); this.Highlights.clearMark(2); - for(int i = 0; i < currentLength; i++) { + for (int i = 0; i < currentLength; i++) { this.Writes.write(array, i, this.scratchArray[i], 1, true, false); } } diff --git a/src/main/java/io/github/arrayv/sorts/merge/BufferedStoogeSort.java b/src/main/java/io/github/arrayv/sorts/merge/BufferedStoogeSort.java index d190e630..48906152 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/BufferedStoogeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/BufferedStoogeSort.java @@ -4,6 +4,7 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /** @@ -11,6 +12,7 @@ * @author thatsOven * */ +@SortMeta(name = "Buffered Stooge") public final class BufferedStoogeSort extends Sort { /** @@ -18,22 +20,10 @@ public final class BufferedStoogeSort extends Sort { */ public BufferedStoogeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - // TODO Auto-generated constructor stub - this.setSortListName("Buffered Stooge"); - this.setRunAllSortsName("Buffered Stooge Sort"); - this.setRunSortName("Buffered Stoogesort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private int compare(int[] arr, int x, int y) { - this.Highlights.markArray(0, x); - this.Highlights.markArray(1, y); - return this.Reads.compareValues(arr[x], arr[y]); + return this.Reads.compareIndices(arr, x, y, 0, true); } public void wrapper(int[] arr, int start, int stop) { @@ -88,9 +78,7 @@ public void wrapper(int[] arr, int start, int stop) { @Override public void runSort(int[] array, int sortLength, int bucketCount) throws Exception { - // TODO Auto-generated method stub wrapper(array, 0, sortLength); - } } diff --git a/src/main/java/io/github/arrayv/sorts/merge/ImprovedInPlaceMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/ImprovedInPlaceMergeSort.java index e8b75d87..4d9f015b 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/ImprovedInPlaceMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/ImprovedInPlaceMergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,58 +29,48 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Improved In-Place Merge") public final class ImprovedInPlaceMergeSort extends Sort { public ImprovedInPlaceMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Improved In-Place Merge"); - this.setRunAllSortsName("Improved In-Place Merge Sort"); - this.setRunSortName("Improved In-Place Mergesort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void push(int[] array, int p, int a, int b, double sleep) { - if(a == b) return; + if (a == b) + return; int temp = array[p]; Writes.write(array, p, array[a], sleep, true, false); - for(int i = a+1; i < b; i++) - Writes.write(array, i-1, array[i], sleep, true, false); + for (int i = a + 1; i < b; i++) + Writes.write(array, i - 1, array[i], sleep, true, false); - Writes.write(array, b-1, temp, sleep, true, false); + Writes.write(array, b - 1, temp, sleep, true, false); } private void merge(int[] array, int a, int m, int b, double sleep) { int i = a, j = m; Highlights.clearMark(1); - while(i < m && j < b) { - Highlights.markArray(2, i); - Highlights.markArray(3, j); - Delays.sleep(1); - - if(Reads.compareValues(array[i], array[j]) == 1) j++; - else this.push(array, i++, m, j, sleep); + while (i < m && j < b) { + if (Reads.compareIndices(array, i, j, 1, true) == 1) + j++; + else + this.push(array, i++, m, j, sleep); } Highlights.clearAllMarks(); - while(i < m) this.push(array, i++, m, b, sleep); + while (i < m) + this.push(array, i++, m, b, sleep); } private void mergeSort(int[] array, int a, int b, double sleep) { - int m = a+(b-a)/2; + int m = a + (b - a) / 2; - if(b-a > 2) { - if(b-a > 3) - this.mergeSort(array, a, m, 2*sleep); - this.mergeSort(array, m, b, 2*sleep); + if (b - a > 2) { + if (b - a > 3) + this.mergeSort(array, a, m, 2 * sleep); + this.mergeSort(array, m, b, 2 * sleep); } this.merge(array, a, m, b, sleep); diff --git a/src/main/java/io/github/arrayv/sorts/merge/InPlaceMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/InPlaceMergeSort.java index 6194c5f8..3cc39390 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/InPlaceMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/InPlaceMergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,25 +29,15 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "In-Place Merge") public final class InPlaceMergeSort extends Sort { public InPlaceMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("In-Place Merge"); - this.setRunAllSortsName("In-Place Merge Sort"); - this.setRunSortName("In-Place Mergesort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void push(int[] array, int low, int high) { - for(int i = low; i < high; i++) { - if(Reads.compareValues(array[i], array[i + 1]) == 1) { + for (int i = low; i < high; i++) { + if (Reads.compareValues(array[i], array[i + 1]) == 1) { Writes.swap(array, i, i + 1, 0.035, true, false); } } @@ -54,8 +45,8 @@ private void push(int[] array, int low, int high) { private void merge(int[] array, int min, int max, int mid) { int i = min; - while(i <= mid) { - if(Reads.compareValues(array[i], array[mid + 1]) == 1){ + while (i <= mid) { + if (Reads.compareValues(array[i], array[mid + 1]) == 1) { Writes.swap(array, i, mid + 1, 0.035, true, false); push(array, mid + 1, max); } @@ -64,21 +55,19 @@ private void merge(int[] array, int min, int max, int mid) { } } - private void mergeSort(int[] array, int min,int max) { - if(max - min == 0) { //only one element. - Delays.sleep(1); //no swap - } - else if(max - min == 1) { //only two elements and swaps them - if(Reads.compareValues(array[min], array[max]) == 1) { + private void mergeSort(int[] array, int min, int max) { + if (max - min == 0) { // only one element. + Delays.sleep(1); // no swap + } else if (max - min == 1) { // only two elements and swaps them + if (Reads.compareValues(array[min], array[max]) == 1) { Writes.swap(array, min, max, 0.035, true, false); } - } - else { - int mid = ((int) Math.floor((min + max) / 2)); //The midpoint + } else { + int mid = ((int) Math.floor((min + max) / 2)); // The midpoint - mergeSort(array, min, mid); //sort the left side - mergeSort(array, mid + 1, max); //sort the right side - merge(array, min, max, mid); //combines them + mergeSort(array, min, mid); // sort the left side + mergeSort(array, mid + 1, max); // sort the right side + merge(array, min, max, mid); // combines them } } diff --git a/src/main/java/io/github/arrayv/sorts/merge/IterativeTopDownMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/IterativeTopDownMergeSort.java index 16f68de6..dc5bc382 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/IterativeTopDownMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/IterativeTopDownMergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,26 +29,17 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Iterative Top-Down Merge") public class IterativeTopDownMergeSort extends Sort { public IterativeTopDownMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Iterative Top-down Merge"); - this.setRunAllSortsName("Iterative Top-down Merge Sort"); - this.setRunSortName("Iterative Top-down Mergesort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private static int ceilPowerOfTwo(int x) { --x; - for (int i=16; i>0; i>>=1) x |= x>>i; + for (int i = 16; i > 0; i >>= 1) + x |= x >> i; return ++x; } @@ -55,15 +47,13 @@ protected void merge(int[] array, int[] tmp, int start, int mid, int end) { int low = start; int high = mid; - Highlights.markArray(1, low); - Highlights.markArray(2, high); int nxt = start; for (; low < mid && high < end; ++nxt) { - if (Reads.compareValues(array[low], array[high]) == 1) { - Writes.write(tmp, nxt, array[high++], 1, false, true); + if (Reads.compareIndices(array, low, high, 1, true) == 1) { + Writes.write(tmp, nxt, array[high++], 0, false, true); Highlights.markArray(2, high); } else { - Writes.write(tmp, nxt, array[low++], 1, false, true); + Writes.write(tmp, nxt, array[low++], 0, false, true); Highlights.markArray(1, low); } } @@ -88,10 +78,11 @@ protected void merge(int[] array, int[] tmp, int start, int mid, int end) { } protected void mergeSort(int[] array, int[] tmp, int length) { - if (length<1<<15) - for (int subarrayCount=ceilPowerOfTwo(length); subarrayCount>1; subarrayCount>>=1) - for (int i=0; i 1; subarrayCount >>= 1) + for (int i = 0; i < subarrayCount; i += 2) + merge(array, tmp, length * i / subarrayCount, length * (i + 1) / subarrayCount, + length * (i + 2) / subarrayCount); else runSortLarge(array, tmp, length); } @@ -103,32 +94,31 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.deleteExternalArray(tmp); } - // implements "rational numbers" instead of multiplication/division but pretty hacky + // implements "rational numbers" instead of multiplication/division but pretty + // hacky private void runSortLarge(int[] array, int[] tmp, int length) { - for ( - int subarrayCount=ceilPowerOfTwo(length), wholeI=length/subarrayCount, fracI=length%subarrayCount; - subarrayCount>1; - ) { - for (int whole=0, frac=0; whole 1;) { + for (int whole = 0, frac = 0; whole < length;) { int start = whole; whole += wholeI; frac += fracI; - if (frac>=subarrayCount) { + if (frac >= subarrayCount) { ++whole; frac -= subarrayCount; } int mid = whole; whole += wholeI; frac += fracI; - if (frac>=subarrayCount) { + if (frac >= subarrayCount) { ++whole; frac -= subarrayCount; } merge(array, tmp, start, mid, whole); } - subarrayCount>>=1; - wholeI<<=1; - if (fracI>=subarrayCount) { + subarrayCount >>= 1; + wholeI <<= 1; + if (fracI >= subarrayCount) { ++wholeI; fracI -= subarrayCount; } diff --git a/src/main/java/io/github/arrayv/sorts/merge/LazyStableSort.java b/src/main/java/io/github/arrayv/sorts/merge/LazyStableSort.java index 3df7a1d3..9b5073fe 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/LazyStableSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/LazyStableSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.GrailSorting; /* @@ -37,20 +38,10 @@ this software and associated documentation files (the "Software"), to deal in /* methods copied from Grail Sort */ /* */ /*****************************************/ - +@SortMeta(name = "Lazy Stable") public final class LazyStableSort extends GrailSorting { public LazyStableSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Lazy Stable"); - this.setRunAllSortsName("Lazy Stable Sort"); - this.setRunSortName("Lazy Stable Sort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/merge/MergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/MergeSort.java index 67253beb..c3924612 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/MergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/MergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.MergeSorting; /* @@ -28,20 +29,10 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Merge") public final class MergeSort extends MergeSorting { public MergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Merge"); - this.setRunAllSortsName("Merge Sort"); - this.setRunSortName("Mergesort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/merge/MergeSortParallel.java b/src/main/java/io/github/arrayv/sorts/merge/MergeSortParallel.java index 03394464..a69e2ae7 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/MergeSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/merge/MergeSortParallel.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -27,20 +28,10 @@ this software and associated documentation files (the "Software"), to deal in CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ - +@SortMeta(name = "Parallel Merge", unreasonableLimit = 4096) public final class MergeSortParallel extends Sort { public MergeSortParallel(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Merge (Parallel)"); - this.setRunAllSortsName("Parallel Merge Sort"); - this.setRunSortName("Parallel Mergesort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private int[] array; @@ -48,10 +39,13 @@ public MergeSortParallel(ArrayVisualizer arrayVisualizer) { private class MergeSort extends Thread { private int a, b; + MergeSort(int a, int b) { this.a = a; this.b = b; } + + @Override public void run() { MergeSortParallel.this.mergeSort(a, b); } @@ -60,37 +54,38 @@ public void run() { private void merge(int a, int m, int b) { int i = a, j = m, k = a; - while(i < m && j < b) { - if(Reads.compareValues(array[i], array[j]) <= 0) { + while (i < m && j < b) { + if (Reads.compareValues(array[i], array[j]) <= 0) { Highlights.markArray(1, i); Writes.write(tmp, k++, array[i++], 1, false, true); - } - else { + } else { Highlights.markArray(2, j); Writes.write(tmp, k++, array[j++], 1, false, true); } } - while(i < m) { + while (i < m) { Highlights.markArray(1, i); Writes.write(tmp, k++, array[i++], 1, false, true); } - while(j < b) { + while (j < b) { Highlights.markArray(2, j); Writes.write(tmp, k++, array[j++], 1, false, true); } Highlights.clearMark(2); - while(a < b) Writes.write(array, a, tmp[a++], 1, true, false); + while (a < b) + Writes.write(array, a, tmp[a++], 1, true, false); } private void mergeSort(int a, int b) { - int len = b-a; + int len = b - a; - if(len < 2) return; + if (len < 2) + return; - int m = (a+b)/2; + int m = (a + b) / 2; - MergeSort left = new MergeSort(a, m); + MergeSort left = new MergeSort(a, m); MergeSort right = new MergeSort(m, b); left.start(); right.start(); diff --git a/src/main/java/io/github/arrayv/sorts/merge/NewShuffleMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/NewShuffleMergeSort.java index 56df72b4..9a51d961 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/NewShuffleMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/NewShuffleMergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; /* * @@ -38,36 +39,26 @@ of this software and associated documentation files (the "Software"), to deal * See also a proof of the time complexity at https://arxiv.org/abs/1508.00292. * The implementation is based on the pseudocode found in this. */ - +@SortMeta(name = "New Shuffle Merge") public class NewShuffleMergeSort extends IterativeTopDownMergeSort { public NewShuffleMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("New Shuffle Merge"); - this.setRunAllSortsName("New Shuffle Merge Sort"); - this.setRunSortName("New Shuffle Mergesort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void rotateEqual(int[] array, int a, int b, int size, double sleep) { - for (int i=0; i0 && b>0) { + while (a > 0 && b > 0) { if (a > b) { - rotateEqual(array, mid-b, mid, b, sleep); + rotateEqual(array, mid - b, mid, b, sleep); mid -= b; a -= b; } else { - rotateEqual(array, mid-a, mid, a, sleep); + rotateEqual(array, mid - a, mid, a, sleep); mid += a; b -= a; } @@ -76,43 +67,44 @@ private void rotate(int[] array, int mid, int a, int b, double sleep) { private void shuffleEasy(int[] array, int start, int size) { Highlights.clearMark(2); - for (int i=1; i 1) { - int n = (end-start)/2; + while (end - start > 1) { + int n = (end - start) / 2; int l = 1; - while (l*3-1<=2*n) l *= 3; - int m = (l-1)/2; + while (l * 3 - 1 <= 2 * n) + l *= 3; + int m = (l - 1) / 2; - rotate(array, start+n, n-m, m, 1); + rotate(array, start + n, n - m, m, 1); shuffleEasy(array, start, l); - start += l-1; + start += l - 1; } } private void rotateShuffledEqual(int[] array, int a, int b, int size) { - for (int i=0; i0 && b>0) { + while (a > 0 && b > 0) { if (a > b) { - rotateShuffledEqual(array, mid-b, mid, b); + rotateShuffledEqual(array, mid - b, mid, b); mid -= b; a -= b; } else { - rotateShuffledEqual(array, mid-a, mid, a); + rotateShuffledEqual(array, mid - a, mid, a); mid += a; b -= a; } @@ -121,77 +113,82 @@ private void rotateShuffled(int[] array, int mid, int a, int b) { private void rotateShuffledOuter(int[] array, int mid, int a, int b) { if (a > b) { - rotateShuffledEqual(array, mid-b, mid+1, b); + rotateShuffledEqual(array, mid - b, mid + 1, b); mid -= b; a -= b; rotateShuffled(array, mid, a, b); } else { - rotateShuffledEqual(array, mid-a, mid+1, a); - mid += a+1; + rotateShuffledEqual(array, mid - a, mid + 1, a); + mid += a + 1; b -= a; rotateShuffled(array, mid, a, b); } } private void unshuffleEasy(int[] array, int start, int size) { - for (int i=1; i 1) { - int n = (end-start)/2; + while (end - start > 1) { + int n = (end - start) / 2; int l = 1; - while (l*3-1<=2*n) l *= 3; - int m = (l-1)/2; + while (l * 3 - 1 <= 2 * n) + l *= 3; + int m = (l - 1) / 2; - rotateShuffledOuter(array, start+2*m, 2*m, 2*n-2*m); + rotateShuffledOuter(array, start + 2 * m, 2 * m, 2 * n - 2 * m); unshuffleEasy(array, start, l); - start += l-1; + start += l - 1; } } private void mergeUp(int[] array, int start, int end, boolean type) { int i = start; - int j = i+1; + int j = i + 1; while (j < end) { int cmp = Reads.compareIndices(array, i, j, 0, true); - if (cmp==-1 || !type && cmp==0) { + if (cmp == -1 || !type && cmp == 0) { ++i; if (i == j) { ++j; type = !type; } - } else if (end-j == 1) { - rotate(array, j, j-i, 1, 0.25); + } else if (end - j == 1) { + rotate(array, j, j - i, 1, 0.25); break; } else { int r = 0; - if (type) while (j+2*r= runCount ? length : (runs[i + 2]); merge(array, runs[i], runs[i + 1], end); } - for (int i = 1, j = 2; i < runCount; i++, j+=2, runCount--) { + for (int i = 1, j = 2; i < runCount; i++, j += 2, runCount--) { Writes.write(runs, i, runs[j], 0.5, true, true); } } diff --git a/src/main/java/io/github/arrayv/sorts/merge/QuadSort.java b/src/main/java/io/github/arrayv/sorts/merge/QuadSort.java index 7f02e769..421ba2a9 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/QuadSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/QuadSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.QuadSorting; /* @@ -28,20 +29,10 @@ a copy of this software and associated documentation files (the // re-implemented to Java, ArrayV by mg-2018, 2021 // 210704 ~ 210816 - +@SortMeta(name = "Quad") public final class QuadSort extends QuadSorting { public QuadSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Quad"); - this.setRunAllSortsName("Quad Sort"); - this.setRunSortName("Quadsort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/merge/RotateMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/RotateMergeSort.java index 5cf587c5..0f9bc868 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/RotateMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/RotateMergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -27,94 +28,85 @@ this software and associated documentation files (the "Software"), to deal in CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ - +@SortMeta(name = "Rotate Merge") public final class RotateMergeSort extends Sort { - public RotateMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Rotate Merge"); - this.setRunAllSortsName("Rotate Merge Sort"); - //this.setRunAllID("In-Place Merge Sort with Rotations"); - this.setRunSortName(/*"In-Place */"Rotate Mergesort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void multiSwap(int[] array, int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(array, a+i, b+i, 1, true, false); + public RotateMergeSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } + + private void multiSwap(int[] array, int a, int b, int len) { + for (int i = 0; i < len; i++) + Writes.swap(array, a + i, b + i, 1, true, false); } - private void rotate(int[] array, int a, int m, int b) { - int l = m-a, r = b-m; + private void rotate(int[] array, int a, int m, int b) { + int l = m - a, r = b - m; - while(l > 0 && r > 0) { - if(r < l) { - this.multiSwap(array, m-r, m, r); + while (l > 0 && r > 0) { + if (r < l) { + this.multiSwap(array, m - r, m, r); b -= r; m -= r; l -= r; - } - else { + } else { this.multiSwap(array, a, m, l); a += l; m += l; r -= l; - } - } - } + } + } + } private int binarySearch(int[] array, int a, int b, int value, boolean left) { - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; boolean comp = left ? Reads.compareValues(value, array[m]) <= 0 - : Reads.compareValues(value, array[m]) < 0; + : Reads.compareValues(value, array[m]) < 0; - if(comp) b = m; - else a = m+1; + if (comp) + b = m; + else + a = m + 1; } return a; } - private void rotateMerge(int[] array, int a, int m, int b) { + private void rotateMerge(int[] array, int a, int m, int b) { int m1, m2, m3; - if(m-a >= b-m) { - m1 = a+(m-a)/2; + if (m - a >= b - m) { + m1 = a + (m - a) / 2; m2 = this.binarySearch(array, m, b, array[m1], true); - m3 = m1+(m2-m); - } - else { - m2 = m+(b-m)/2; + m3 = m1 + (m2 - m); + } else { + m2 = m + (b - m) / 2; m1 = this.binarySearch(array, a, m, array[m2], false); - m3 = (m2++)-(m-m1); + m3 = (m2++) - (m - m1); } this.rotate(array, m1, m, m2); - if(m2-(m3+1) > 0 && b-m2 > 0) this.rotateMerge(array, m3+1, m2, b); - if(m1-a > 0 && m3-m1 > 0) this.rotateMerge(array, a, m1, m3); + if (m2 - (m3 + 1) > 0 && b - m2 > 0) + this.rotateMerge(array, m3 + 1, m2, b); + if (m1 - a > 0 && m3 - m1 > 0) + this.rotateMerge(array, a, m1, m3); } protected void rotateMergeSort(int[] array, int a, int b) { - int len = b-a, i; + int len = b - a, i; - for(int j = 1; j < len; j *= 2) { - for(i = a; i + 2*j <= b; i += 2*j) - this.rotateMerge(array, i, i+j, i+2*j); + for (int j = 1; j < len; j *= 2) { + for (i = a; i + 2 * j <= b; i += 2 * j) + this.rotateMerge(array, i, i + j, i + 2 * j); - if(i + j < b) - this.rotateMerge(array, i, i+j, b); - } - } + if (i + j < b) + this.rotateMerge(array, i, i + j, b); + } + } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { this.rotateMergeSort(array, 0, length); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/merge/RotateMergeSortParallel.java b/src/main/java/io/github/arrayv/sorts/merge/RotateMergeSortParallel.java index c5a8435e..2ddf820b 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/RotateMergeSortParallel.java +++ b/src/main/java/io/github/arrayv/sorts/merge/RotateMergeSortParallel.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -27,105 +28,101 @@ this software and associated documentation files (the "Software"), to deal in CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ - +@SortMeta(name = "Parallel Rotate Merge", unreasonableLimit = 4096) public final class RotateMergeSortParallel extends Sort { - public RotateMergeSortParallel(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Rotate Merge (Parallel)"); - this.setRunAllSortsName("Parallel Rotate Merge Sort"); - //this.setRunAllID("In-Place Merge Sort with Rotations"); - this.setRunSortName(/*"In-Place */"Parallel Rotate Mergesort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(true); - this.setUnreasonableLimit(4096); - this.setBogoSort(false); - } + public RotateMergeSortParallel(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int[] array; private class RotateMergeSort extends Thread { - private int a, b; - RotateMergeSort(int a, int b) { - this.a = a; + private int a, b; + + RotateMergeSort(int a, int b) { + this.a = a; this.b = b; - } - public void run() { - RotateMergeSortParallel.this.rotateMergeSort(this.a, this.b); - } - } - - private class RotateMerge extends Thread { - private int a, m, b; - RotateMerge(int a, int m, int b) { - this.a = a; - this.m = m; - this.b = b; - } - public void run() { - RotateMergeSortParallel.this.rotateMerge(a, m, b); - } - } - - private void multiSwap(int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(this.array, a+i, b+i, 1, true, false); + } + + @Override + public void run() { + RotateMergeSortParallel.this.rotateMergeSort(this.a, this.b); + } + } + + private class RotateMerge extends Thread { + private int a, m, b; + + RotateMerge(int a, int m, int b) { + this.a = a; + this.m = m; + this.b = b; + } + + @Override + public void run() { + RotateMergeSortParallel.this.rotateMerge(a, m, b); + } + } + + private void multiSwap(int a, int b, int len) { + for (int i = 0; i < len; i++) + Writes.swap(this.array, a + i, b + i, 1, true, false); } - private void rotate(int a, int m, int b) { - int l = m-a, r = b-m; + private void rotate(int a, int m, int b) { + int l = m - a, r = b - m; - while(l > 0 && r > 0) { - if(r < l) { - this.multiSwap(m-r, m, r); + while (l > 0 && r > 0) { + if (r < l) { + this.multiSwap(m - r, m, r); b -= r; m -= r; l -= r; - } - else { + } else { this.multiSwap(a, m, l); a += l; m += l; r -= l; - } - } - } + } + } + } private int binarySearch(int a, int b, int value, boolean left) { - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; boolean comp = left ? Reads.compareValues(value, this.array[m]) <= 0 - : Reads.compareValues(value, this.array[m]) < 0; + : Reads.compareValues(value, this.array[m]) < 0; - if(comp) b = m; - else a = m+1; + if (comp) + b = m; + else + a = m + 1; } return a; } - private void rotateMerge(int a, int m, int b) { - if(m-a < 1 || b-m < 1) return; + private void rotateMerge(int a, int m, int b) { + if (m - a < 1 || b - m < 1) + return; int m1, m2, m3; - if(m-a >= b-m) { - m1 = a+(m-a)/2; + if (m - a >= b - m) { + m1 = a + (m - a) / 2; m2 = this.binarySearch(m, b, this.array[m1], true); - m3 = m1+(m2-m); - } - else { - m2 = m+(b-m)/2; + m3 = m1 + (m2 - m); + } else { + m2 = m + (b - m) / 2; m1 = this.binarySearch(a, m, this.array[m2], false); - m3 = (m2++)-(m-m1); + m3 = (m2++) - (m - m1); } this.rotate(m1, m, m2); RotateMerge l = new RotateMerge(a, m1, m3); - RotateMerge r = new RotateMerge(m3+1, m2, b); + RotateMerge r = new RotateMerge(m3 + 1, m2, b); l.start(); r.start(); try { @@ -137,9 +134,10 @@ private void rotateMerge(int a, int m, int b) { } protected void rotateMergeSort(int a, int b) { - if(b-a < 2) return; + if (b - a < 2) + return; - int m = (a+b)/2; + int m = (a + b) / 2; RotateMergeSort l = new RotateMergeSort(a, m); RotateMergeSort r = new RotateMergeSort(m, b); l.start(); @@ -147,16 +145,15 @@ protected void rotateMergeSort(int a, int b) { try { l.join(); r.join(); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); } this.rotateMerge(a, m, b); - } + } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { this.array = array; this.rotateMergeSort(0, length); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/merge/StacklessRotateMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/StacklessRotateMergeSort.java index d17aac87..dd0c2948 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/StacklessRotateMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/StacklessRotateMergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; import io.github.arrayv.utils.IndexedRotations; @@ -28,98 +29,90 @@ this software and associated documentation files (the "Software"), to deal in CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ - +@SortMeta(name = "Stackless Rotate Merge") public final class StacklessRotateMergeSort extends Sort { - public StacklessRotateMergeSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Stackless Rotate Merge"); - this.setRunAllSortsName("Stackless Rotate Merge Sort"); - this.setRunSortName("Stackless Rotate Mergesort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } - - private void rotate(int[] array, int a, int m, int b) { + public StacklessRotateMergeSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } + + private void rotate(int[] array, int a, int m, int b) { IndexedRotations.griesMills(array, a, m, b, 0.5, true, false); - } + } - //@param c - select c smallest elements + // @param c - select c smallest elements private void partitionMerge(int[] array, int a, int m, int b, int c) { - int lenA = m-a, lenB = b-m; + int lenA = m - a, lenB = b - m; - if(lenA < 1 || lenB < 1) return; + if (lenA < 1 || lenB < 1) + return; - if(lenB < lenA) { - c = (lenA+lenB)-c; + if (lenB < lenA) { + c = (lenA + lenB) - c; int r1 = 0, r2 = Math.min(c, lenB); - while(r1 < r2) { - int ml = (r1+r2)/2; + while (r1 < r2) { + int ml = (r1 + r2) / 2; - if(Reads.compareValues(array[m-(c-ml)], array[b-ml-1]) > 0) + if (Reads.compareValues(array[m - (c - ml)], array[b - ml - 1]) > 0) r2 = ml; else - r1 = ml+1; + r1 = ml + 1; } - //[lenA-(c-r1)][c-r1][lenB-r1][r1] - //[lenA-(c-r1)][lenB-r1][c-r1][r1] - this.rotate(array, m-(c-r1), m, b-r1); - } - else { + // [lenA-(c-r1)][c-r1][lenB-r1][r1] + // [lenA-(c-r1)][lenB-r1][c-r1][r1] + this.rotate(array, m - (c - r1), m, b - r1); + } else { int r1 = 0, r2 = Math.min(c, lenA); - while(r1 < r2) { - int ml = (r1+r2)/2; + while (r1 < r2) { + int ml = (r1 + r2) / 2; - if(Reads.compareValues(array[a+ml], array[m+(c-ml)-1]) > 0) + if (Reads.compareValues(array[a + ml], array[m + (c - ml) - 1]) > 0) r2 = ml; else - r1 = ml+1; + r1 = ml + 1; } - //[r1][lenA-r1][c-r1][lenB-(c-r1)] - //[r1][c-r1][lenA-r1][lenB-(c-r1)] - this.rotate(array, a+r1, m, m+(c-r1)); + // [r1][lenA-r1][c-r1][lenB-(c-r1)] + // [r1][c-r1][lenA-r1][lenB-(c-r1)] + this.rotate(array, a + r1, m, m + (c - r1)); } } private void rotateMerge(int[] array, int a, int b, int c) { int i; - for(i = a+1; i < b && Reads.compareIndices(array, i-1, i, 0.25, true) <= 0; i++); - if(i < b) this.partitionMerge(array, a, i, b, c); + for (i = a + 1; i < b && Reads.compareIndices(array, i - 1, i, 0.25, true) <= 0; i++) + ; + if (i < b) + this.partitionMerge(array, a, i, b, c); } public void rotatePartitionMergeSort(int[] array, int a, int b) { - int len = b-a; + int len = b - a; - for(int i = a+1; i < b; i += 2) - if(Reads.compareIndices(array, i-1, i, 0.5, true) > 0) - Writes.swap(array, i-1, i, 0.5, true, false); + for (int i = a + 1; i < b; i += 2) + if (Reads.compareIndices(array, i - 1, i, 0.5, true) > 0) + Writes.swap(array, i - 1, i, 0.5, true, false); - for(int j = 2; j < len; j *= 2) { + for (int j = 2; j < len; j *= 2) { int b1 = 0; - for(int i = a; i+j < b; i += 2*j) { - b1 = Math.min(i+2*j, b); - this.partitionMerge(array, i, i+j, b1, j); + for (int i = a; i + j < b; i += 2 * j) { + b1 = Math.min(i + 2 * j, b); + this.partitionMerge(array, i, i + j, b1, j); } - for(int k = j/2; k > 1; k /= 2) - for(int i = a; i+k < b1; i += 2*k) - this.rotateMerge(array, i, Math.min(i+2*k, b), k); + for (int k = j / 2; k > 1; k /= 2) + for (int i = a; i + k < b1; i += 2 * k) + this.rotateMerge(array, i, Math.min(i + 2 * k, b), k); - for(int i = a+1; i < b1; i += 2) - if(Reads.compareIndices(array, i-1, i, 0.5, true) > 0) - Writes.swap(array, i-1, i, 0.5, true, false); - } - } + for (int i = a + 1; i < b1; i += 2) + if (Reads.compareIndices(array, i - 1, i, 0.5, true) > 0) + Writes.swap(array, i - 1, i, 0.5, true, false); + } + } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { this.rotatePartitionMergeSort(array, 0, length); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/merge/StrandSort.java b/src/main/java/io/github/arrayv/sorts/merge/StrandSort.java index e6772c51..a2244901 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/StrandSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/StrandSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,34 +29,25 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Strand") public final class StrandSort extends Sort { public StrandSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Strand"); - this.setRunAllSortsName("Strand Sort"); - this.setRunSortName("Strandsort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - //reverses equal items order + // reverses equal items order private void mergeTo(int[] array, int[] subList, int a, int m, int b) { - int i = 0, s = m-a; + int i = 0, s = m - a; - while(i < s && m < b) { - if(Reads.compareValues(subList[i], array[m]) < 0) + while (i < s && m < b) { + if (Reads.compareValues(subList[i], array[m]) < 0) Writes.write(array, a++, subList[i++], 0.5, true, false); - else Writes.write(array, a++, array[m++], 0.5, true, false); + else + Writes.write(array, a++, array[m++], 0.5, true, false); } - while(i < s) + while (i < s) Writes.write(array, a++, subList[i++], 0.5, true, false); } @@ -65,16 +57,15 @@ public void runSort(int[] array, int length, int bucketCount) { int j = length, k = j; - while(j > 0) { + while (j > 0) { Writes.write(subList, 0, array[0], 1, true, true); k--; - for(int i = 0, p = 0, m = 1; m < j; m++) { - if(Reads.compareValues(array[m], subList[i]) >= 0) { + for (int i = 0, p = 0, m = 1; m < j; m++) { + if (Reads.compareValues(array[m], subList[i]) >= 0) { Writes.write(subList, ++i, array[m], 1, true, true); k--; - } - else { + } else { Highlights.markArray(2, p); Writes.write(array, p++, array[m], 0.1, false, false); } diff --git a/src/main/java/io/github/arrayv/sorts/merge/TwinSort.java b/src/main/java/io/github/arrayv/sorts/merge/TwinSort.java index 37614fac..68a1647b 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/TwinSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/TwinSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.TwinSorting; /* @@ -34,20 +35,10 @@ a copy of this software and associated documentation files (the /* twinsort 1.1.3.3 */ - +@SortMeta(name = "Twin") public final class TwinSort extends TwinSorting { public TwinSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Twin"); - this.setRunAllSortsName("Twin Sort"); - this.setRunSortName("Twin Sort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/merge/WeavedMergeSort.java b/src/main/java/io/github/arrayv/sorts/merge/WeavedMergeSort.java index edbe96e1..0be0bcf8 100644 --- a/src/main/java/io/github/arrayv/sorts/merge/WeavedMergeSort.java +++ b/src/main/java/io/github/arrayv/sorts/merge/WeavedMergeSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.merge; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,45 +29,33 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Weaved Merge") public class WeavedMergeSort extends Sort { public WeavedMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Weaved Merge"); - this.setRunAllSortsName("Weaved Merge Sort"); - this.setRunSortName("Weaved Mergesort"); - this.setCategory("Merge Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void merge(int[] array, int[] tmp, int length, int residue, int modulus) { - if (residue+modulus >= length) + if (residue + modulus >= length) return; int low = residue; - int high = residue+modulus; - int dmodulus = modulus<<1; + int high = residue + modulus; + int dmodulus = modulus << 1; merge(array, tmp, length, low, dmodulus); merge(array, tmp, length, high, dmodulus); - Highlights.markArray(1, low); - Highlights.markArray(2, high); int nxt = residue; - for (; low < length && high < length; nxt+=modulus) { - int cmp = Reads.compareValues(array[low], array[high]); + for (; low < length && high < length; nxt += modulus) { + int cmp = Reads.compareIndices(array, low, high, 1, true); if (cmp == 1 || cmp == 0 && low > high) { - Writes.write(tmp, nxt, array[high], 1, false, true); + Writes.write(tmp, nxt, array[high], 0, false, true); high += dmodulus; Highlights.markArray(2, high); } else { - Writes.write(tmp, nxt, array[low], 1, false, true); + Writes.write(tmp, nxt, array[low], 0, false, true); low += dmodulus; Highlights.markArray(1, low); } @@ -90,7 +79,7 @@ private void merge(int[] array, int[] tmp, int length, int residue, int modulus) Highlights.clearMark(1); Highlights.clearMark(2); - for (int i = residue; i < length; i+=modulus) { + for (int i = residue; i < length; i += modulus) { Writes.write(array, i, tmp[i], 1, true, false); } } @@ -99,7 +88,7 @@ private void merge(int[] array, int[] tmp, int length, int residue, int modulus) public void runSort(int[] array, int length, int bucketCount) { int[] tmp = Writes.createExternalArray(length); - merge(array, tmp, length, 0 , 1); + merge(array, tmp, length, 0, 1); Writes.deleteExternalArray(tmp); } diff --git a/src/main/java/io/github/arrayv/sorts/merge/package-info.java b/src/main/java/io/github/arrayv/sorts/merge/package-info.java new file mode 100644 index 00000000..cbdea118 --- /dev/null +++ b/src/main/java/io/github/arrayv/sorts/merge/package-info.java @@ -0,0 +1,2 @@ +@io.github.arrayv.sortdata.SortPackageMeta(category = "Merge Sorts") +package io.github.arrayv.sorts.merge; diff --git a/src/main/java/io/github/arrayv/sorts/misc/BurntPancakeSort.java b/src/main/java/io/github/arrayv/sorts/misc/BurntPancakeSort.java index d6ebf120..c760692a 100644 --- a/src/main/java/io/github/arrayv/sorts/misc/BurntPancakeSort.java +++ b/src/main/java/io/github/arrayv/sorts/misc/BurntPancakeSort.java @@ -4,10 +4,7 @@ import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; -@SortMeta( - name = "Burnt Pancake", - runName = "Burnt Pancake Sort" -) +@SortMeta(name = "Burnt Pancake") public final class BurntPancakeSort extends Sort { public BurntPancakeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); diff --git a/src/main/java/io/github/arrayv/sorts/misc/PancakeInsertionSort.java b/src/main/java/io/github/arrayv/sorts/misc/PancakeInsertionSort.java index b3848f06..70db1b87 100644 --- a/src/main/java/io/github/arrayv/sorts/misc/PancakeInsertionSort.java +++ b/src/main/java/io/github/arrayv/sorts/misc/PancakeInsertionSort.java @@ -4,9 +4,7 @@ import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; -@SortMeta( - name = "Pancake Insertion" -) +@SortMeta(name = "Pancake Insertion") public final class PancakeInsertionSort extends Sort { public PancakeInsertionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); diff --git a/src/main/java/io/github/arrayv/sorts/misc/PancakeSort.java b/src/main/java/io/github/arrayv/sorts/misc/PancakeSort.java index 70363910..fb2d4580 100644 --- a/src/main/java/io/github/arrayv/sorts/misc/PancakeSort.java +++ b/src/main/java/io/github/arrayv/sorts/misc/PancakeSort.java @@ -13,22 +13,17 @@ * https://www.ideserve.co.in/learn/pancake-sorting */ -@SortMeta( - name = "Pancake", - runName = "Pancake Sort" -) +@SortMeta(name = "Pancake") public final class PancakeSort extends Sort { public PancakeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } private boolean sorted(int[] array, int length) { - for(int i = 0; i < length; i++) { - Highlights.markArray(1, i); - Delays.sleep(0.025); + for (int i = 0; i < length; i++) + if (Reads.compareIndices(array, i, i + 1, 0.025, true) > 0) + return false; - if(Reads.compareValues(array[i], array[i + 1]) > 0) return false; - } return true; } @@ -52,18 +47,17 @@ private int findMax(int[] arr, int end) { @Override public void runSort(int[] array, int length, int bucketCount) { for (int i = length - 1; i >= 0; i--) { - if(!this.sorted(array, i)) { + if (!this.sorted(array, i)) { int index = this.findMax(array, i); - if(index == 0) { + if (index == 0) { Writes.reversal(array, 0, i, 0.05, true, false); - } - else if(index != i) { + } else if (index != i) { Writes.reversal(array, 0, index, 0.05, true, false); Writes.reversal(array, 0, i, 0.05, true, false); } - } - else break; + } else + break; } } } diff --git a/src/main/java/io/github/arrayv/sorts/misc/StalinSort.java b/src/main/java/io/github/arrayv/sorts/misc/StalinSort.java index 35b32b0b..9c0c676d 100644 --- a/src/main/java/io/github/arrayv/sorts/misc/StalinSort.java +++ b/src/main/java/io/github/arrayv/sorts/misc/StalinSort.java @@ -4,9 +4,7 @@ import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; -@SortMeta( - name = "Stalin" -) +@SortMeta(name = "Stalin") public final class StalinSort extends Sort { public StalinSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); diff --git a/src/main/java/io/github/arrayv/sorts/misc/package-info.java b/src/main/java/io/github/arrayv/sorts/misc/package-info.java index b0ffd475..7bd16444 100644 --- a/src/main/java/io/github/arrayv/sorts/misc/package-info.java +++ b/src/main/java/io/github/arrayv/sorts/misc/package-info.java @@ -1,4 +1,2 @@ -@io.github.arrayv.sortdata.SortPackageMeta( - category = "Miscellaneous Sorts" -) +@io.github.arrayv.sortdata.SortPackageMeta(category = "Miscellaneous Sorts") package io.github.arrayv.sorts.misc; diff --git a/src/main/java/io/github/arrayv/sorts/quick/TernaryLLQuickSort.java b/src/main/java/io/github/arrayv/sorts/quick/TernaryLLQuickSort.java index 791736bb..24a150f0 100644 --- a/src/main/java/io/github/arrayv/sorts/quick/TernaryLLQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/quick/TernaryLLQuickSort.java @@ -6,14 +6,10 @@ /** * @author Timo Bingmann - * Implemented in ArrayV by Gaming32 - * https://github.com/bingmann/sound-of-sorting/blob/master/src/SortAlgo.cpp#L536-L595 + * Implemented in ArrayV by Gaming32 + * https://github.com/bingmann/sound-of-sorting/blob/master/src/SortAlgo.cpp#L536-L595 */ -@SortMeta( - listName = "Ternary LL Quick", - showcaseName = "Quick Sort (ternary, LL ptrs)", - runName = "Quicksort (ternary, LL ptrs)" -) +@SortMeta(listName = "Ternary LL Quick", runName = "Quicksort (ternary, LL ptrs)") public final class TernaryLLQuickSort extends Sort { class PivotPair { int first, second; @@ -42,8 +38,8 @@ private int selectPivot(int[] A, int lo, int hi) { return hi - 1; return compare(A, lo, mid) < 0 - ? (compare(A, mid, hi - 1) < 0 ? mid : (compare(A, lo, hi - 1) < 0 ? hi - 1 : lo)) - : (compare(A, mid, hi - 1) > 0 ? mid : (compare(A, lo, hi - 1) < 0 ? lo : hi - 1)); + ? (compare(A, mid, hi - 1) < 0 ? mid : (compare(A, lo, hi - 1) < 0 ? hi - 1 : lo)) + : (compare(A, mid, hi - 1) > 0 ? mid : (compare(A, lo, hi - 1) < 0 ? lo : hi - 1)); } private PivotPair partitionTernaryLL(int[] A, int lo, int hi) { @@ -61,8 +57,7 @@ private PivotPair partitionTernaryLL(int[] A, int lo, int hi) { Writes.swap(A, --k, j, 1, true, false); --j; Highlights.markArray(4, k); - } - else if (cmp < 0) { + } else if (cmp < 0) { Writes.swap(A, i++, j, 1, true, false); Highlights.markArray(3, i); } diff --git a/src/main/java/io/github/arrayv/sorts/quick/TernaryLRQuickSort.java b/src/main/java/io/github/arrayv/sorts/quick/TernaryLRQuickSort.java index 13a0b1d6..910242ac 100644 --- a/src/main/java/io/github/arrayv/sorts/quick/TernaryLRQuickSort.java +++ b/src/main/java/io/github/arrayv/sorts/quick/TernaryLRQuickSort.java @@ -6,14 +6,10 @@ /** * @author Timo Bingmann - * Implemented in ArrayV by Gaming32 - * https://github.com/bingmann/sound-of-sorting/blob/master/src/SortAlgo.cpp#L449-L534 + * Implemented in ArrayV by Gaming32 + * https://github.com/bingmann/sound-of-sorting/blob/master/src/SortAlgo.cpp#L449-L534 */ -@SortMeta( - listName = "Ternary LR Quick", - showcaseName = "Quick Sort (ternary, LR ptrs)", - runName = "Quicksort (ternary, LR ptrs)" -) +@SortMeta(listName = "Ternary LR Quick", runName = "Quicksort (ternary, LR ptrs)") public final class TernaryLRQuickSort extends Sort { public TernaryLRQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -33,12 +29,13 @@ private int selectPivot(int[] A, int lo, int hi) { return hi - 1; return compare(A, lo, mid) < 0 - ? (compare(A, mid, hi - 1) < 0 ? mid : (compare(A, lo, hi - 1) < 0 ? hi - 1 : lo)) - : (compare(A, mid, hi - 1) > 0 ? mid : (compare(A, lo, hi - 1) < 0 ? lo : hi - 1)); + ? (compare(A, mid, hi - 1) < 0 ? mid : (compare(A, lo, hi - 1) < 0 ? hi - 1 : lo)) + : (compare(A, mid, hi - 1) > 0 ? mid : (compare(A, lo, hi - 1) < 0 ? lo : hi - 1)); } private void quickSortTernaryLR(int[] A, int lo, int hi) { - if (hi <= lo) return; + if (hi <= lo) + return; int cmp; @@ -71,7 +68,8 @@ private void quickSortTernaryLR(int[] A, int lo, int hi) { Highlights.markArray(3, j); } - if (i > j) break; + if (i > j) + break; Writes.swap(A, i++, j--, 1, true, false); Highlights.markArray(3, j); @@ -82,7 +80,8 @@ private void quickSortTernaryLR(int[] A, int lo, int hi) { int num_less = i - p; int num_greater = q - j; - j = i - 1; i = i + 1; + j = i - 1; + i = i + 1; Highlights.markArray(3, i); int pe = lo + Math.min(p - lo, num_less); diff --git a/src/main/java/io/github/arrayv/sorts/quick/package-info.java b/src/main/java/io/github/arrayv/sorts/quick/package-info.java index e53fe3de..e65a7f8a 100644 --- a/src/main/java/io/github/arrayv/sorts/quick/package-info.java +++ b/src/main/java/io/github/arrayv/sorts/quick/package-info.java @@ -1,4 +1,2 @@ -@io.github.arrayv.sortdata.SortPackageMeta( - category = "Quick Sorts" -) +@io.github.arrayv.sortdata.SortPackageMeta(category = "Quick Sorts") package io.github.arrayv.sorts.quick; diff --git a/src/main/java/io/github/arrayv/sorts/select/AsynchronousSort.java b/src/main/java/io/github/arrayv/sorts/select/AsynchronousSort.java index 93e27996..932db051 100644 --- a/src/main/java/io/github/arrayv/sorts/select/AsynchronousSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/AsynchronousSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.insert.InsertionSort; import io.github.arrayv.sorts.templates.Sort; @@ -29,20 +30,10 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Asynchronous") public final class AsynchronousSort extends Sort { public AsynchronousSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Asynchronous"); - this.setRunAllSortsName("Asynchronous Sort"); - this.setRunSortName("Asynchronous Sort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/select/BaseNMaxHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/BaseNMaxHeapSort.java index 6de75c99..e6824f0a 100644 --- a/src/main/java/io/github/arrayv/sorts/select/BaseNMaxHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/BaseNMaxHeapSort.java @@ -4,13 +4,7 @@ import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; -@SortMeta( - name = "Base-N Max Heap", - category = "Selection Sorts", - showcaseName = "Base-N Max Heap Sort, Base 4", - question = "Enter the base for this sort:", - defaultAnswer = 4 -) +@SortMeta(name = "Base-N Max Heap", question = "Enter the base for this sort:", defaultAnswer = 4) public final class BaseNMaxHeapSort extends Sort { public BaseNMaxHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); diff --git a/src/main/java/io/github/arrayv/sorts/select/BingoSort.java b/src/main/java/io/github/arrayv/sorts/select/BingoSort.java index 2b8d045d..c4677736 100644 --- a/src/main/java/io/github/arrayv/sorts/select/BingoSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/BingoSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -18,59 +19,48 @@ * * >> Imported and Translated (from Pascal) by Joel "McDude73" Zaleschuk */ - +@SortMeta(name = "Bingo") public final class BingoSort extends Sort { public BingoSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Bingo"); - this.setRunAllSortsName("Bingo Sort"); - this.setRunSortName("Bingosort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override public void runSort(int[] array, int length, int bucketCount) { - double sleep = Math.min(Math.max(10d/this.arrayVisualizer.getUniqueItems(), 0.001), 1); + double sleep = Math.min(Math.max(10d / this.arrayVisualizer.getUniqueItems(), 0.001), 1); int maximum = length - 1; int next = array[maximum]; - for(int i=maximum-1;i>=0;i--) { - if(array[i] > next) { + for (int i = maximum - 1; i >= 0; i--) { + if (array[i] > next) { next = array[i]; } } - while(maximum > 0 && array[maximum] == next) { + while (maximum > 0 && array[maximum] == next) { maximum--; } - while(maximum > 0) { + while (maximum > 0) { int val = next; next = array[maximum]; - for(int j=maximum-1;j>=0;j--) { + for (int j = maximum - 1; j >= 0; j--) { Highlights.markArray(1, array[j]); Highlights.markArray(2, val); - if(Reads.compareValues(array[j], val) == 0) { - Writes.swap(array, j, maximum, 2*sleep, true, false); + if (Reads.compareValues(array[j], val) == 0) { + Writes.swap(array, j, maximum, 2 * sleep, true, false); maximum--; - } - else { - if(array[j] > next) { + } else { + if (array[j] > next) { next = array[j]; } } Delays.sleep(sleep); } - while(maximum > 0 && array[maximum] == next) { + while (maximum > 0 && array[maximum] == next) { maximum--; } } diff --git a/src/main/java/io/github/arrayv/sorts/select/BinomialHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/BinomialHeapSort.java index b88412ff..4146c102 100644 --- a/src/main/java/io/github/arrayv/sorts/select/BinomialHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/BinomialHeapSort.java @@ -1,21 +1,13 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Binomial Heap") public final class BinomialHeapSort extends Sort { public BinomialHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Binomial Heap"); - this.setRunAllSortsName("Binomial Heap Sort"); - this.setRunSortName("Binomial Heapsort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/select/BinomialSmoothSort.java b/src/main/java/io/github/arrayv/sorts/select/BinomialSmoothSort.java index e25a5c15..d55611ff 100644 --- a/src/main/java/io/github/arrayv/sorts/select/BinomialSmoothSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/BinomialSmoothSort.java @@ -1,35 +1,27 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Binomial Smooth") public final class BinomialSmoothSort extends Sort { public BinomialSmoothSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Binomial Smooth"); - this.setRunAllSortsName("Binomial Smooth Sort"); - this.setRunSortName("Binomial Smoothsort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - private int height(int node){ + private int height(int node) { int count = 0; while ((node >> count) % 2 == 1) count++; return count; } - private void thrift(int[] array, int node, boolean parent, boolean root){ + private void thrift(int[] array, int node, boolean parent, boolean root) { root = root && (node >= (1 << height(node))); if (!root && !parent) return; - int choice = height(node) - (root?0:1); + int choice = height(node) - (root ? 0 : 1); if (parent) for (int child = choice - 1; child >= 0; child--) if (Reads.compareValues(array[node - (1 << choice)], array[node - (1 << child)]) != 1) @@ -37,18 +29,19 @@ private void thrift(int[] array, int node, boolean parent, boolean root){ if (Reads.compareValues(array[node - (1 << choice)], array[node]) != 1) return; Writes.swap(array, node, node - (1 << choice), .65, true, false); - thrift(array, node - (1 << choice), (node - (1 << choice)) % 2 ==1, choice == height(node)); + thrift(array, node - (1 << choice), (node - (1 << choice)) % 2 == 1, choice == height(node)); } @Override - public void runSort(int[] array, int length, int bucketCount){ - //heapify from 0 to length - 1 + public void runSort(int[] array, int length, int bucketCount) { + // heapify from 0 to length - 1 int Node; for (Node = 1; Node < length; Node++) thrift(array, Node, Node % 2 == 1, (Node + (1 << height(Node)) >= length)); for (Node -= (Node - 1) % 2; Node > 2; Node -= 2) - //extract largest and second largest(already at end), then heapify from 0 to Node - 1 - for (int Child = height(Node) - 1; Child >= 0; Child --) + // extract largest and second largest(already at end), then heapify from 0 to + // Node - 1 + for (int Child = height(Node) - 1; Child >= 0; Child--) thrift(array, Node - (1 << Child), false, true); } } diff --git a/src/main/java/io/github/arrayv/sorts/select/BottomUpHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/BottomUpHeapSort.java index e23c2a34..e9cd600e 100644 --- a/src/main/java/io/github/arrayv/sorts/select/BottomUpHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/BottomUpHeapSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,37 +29,32 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Bottom-Up Heap") public final class BottomUpHeapSort extends Sort { public BottomUpHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Bottom-up Heap"); - this.setRunAllSortsName("Bottom-up Heap Sort"); - this.setRunSortName("Bottom-up Heapsort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - //source: https://en.wikipedia.org/wiki/Heapsort#Bottom-up_heapsort + // source: https://en.wikipedia.org/wiki/Heapsort#Bottom-up_heapsort private void siftDown(int[] array, int i, int b) { int j = i; - for(; 2*j + 1 < b; j = 2*j + 2 < b ? (Reads.compareValues(array[2*j + 2], array[2*j + 1]) > 0 ? 2*j + 2 : 2*j + 1) : 2*j + 1); - for(; Reads.compareValues(array[i], array[j]) > 0; j = (j-1)/2); - for(; j > i; j = (j-1)/2) Writes.swap(array, i, j, 1, true, false); + for (; 2 * j + 1 < b; j = 2 * j + 2 < b + ? (Reads.compareValues(array[2 * j + 2], array[2 * j + 1]) > 0 ? 2 * j + 2 : 2 * j + 1) + : 2 * j + 1) + ; + for (; Reads.compareValues(array[i], array[j]) > 0; j = (j - 1) / 2) + ; + for (; j > i; j = (j - 1) / 2) + Writes.swap(array, i, j, 1, true, false); } @Override public void runSort(int[] array, int length, int bucketCount) { - for(int i = (length-1)/2; i >= 0; i--) + for (int i = (length - 1) / 2; i >= 0; i--) this.siftDown(array, i, length); - for(int i = length-1; i > 0; i--) { + for (int i = length - 1; i > 0; i--) { Writes.swap(array, 0, i, 1, true, false); this.siftDown(array, 0, i); } diff --git a/src/main/java/io/github/arrayv/sorts/select/ClassicTournamentSort.java b/src/main/java/io/github/arrayv/sorts/select/ClassicTournamentSort.java index 3c589b2e..a1fa0272 100644 --- a/src/main/java/io/github/arrayv/sorts/select/ClassicTournamentSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/ClassicTournamentSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,21 +29,11 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Classic Tournament") public final class ClassicTournamentSort extends Sort { - public ClassicTournamentSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Classic Tournament"); - this.setRunAllSortsName("Classic Tournament Sort"); - this.setRunSortName("Classic Tournament Sort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public ClassicTournamentSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int[] array; private int[] tmp; @@ -52,7 +43,8 @@ public ClassicTournamentSort(ArrayVisualizer arrayVisualizer) { private int ceilPow2(int n) { int r = 1; - while(r < n) r *= 2; + while (r < n) + r *= 2; return r; } @@ -61,27 +53,28 @@ private boolean treeCompare(int a, int b) { } private void buildTree(int n) { - this.size = this.ceilPow2(n)-1; - int mod = n&1; - int treeSize = n+this.size+mod; + this.size = this.ceilPow2(n) - 1; + int mod = n & 1; + int treeSize = n + this.size + mod; this.tree = Writes.createExternalArray(treeSize); - for(int i = 0; i < treeSize; i++) + for (int i = 0; i < treeSize; i++) Writes.write(this.tree, i, -1, 0, false, true); - for(int i = this.size; i < treeSize-mod; i++) { - Highlights.markArray(1, i-this.size); - Writes.write(this.tree, i, i-this.size, 0.5, false, true); + for (int i = this.size; i < treeSize - mod; i++) { + Highlights.markArray(1, i - this.size); + Writes.write(this.tree, i, i - this.size, 0.5, false, true); } - for(int i, j = this.size, k = treeSize-mod; j > 0; j /= 2, k /= 2) { - for(i = j; i+1 < k; i += 2) { - int val = this.treeCompare(i, i+1) ? this.tree[i] : this.tree[i+1]; + for (int i, j = this.size, k = treeSize - mod; j > 0; j /= 2, k /= 2) { + for (i = j; i + 1 < k; i += 2) { + int val = this.treeCompare(i, i + 1) ? this.tree[i] : this.tree[i + 1]; - Writes.write(this.tree, i/2, val, 0, false, true); + Writes.write(this.tree, i / 2, val, 0, false, true); } - if(i < k) Writes.write(this.tree, i/2, this.tree[i], 0, false, true); + if (i < k) + Writes.write(this.tree, i / 2, this.tree[i], 0, false, true); } } @@ -90,33 +83,36 @@ private int peek() { } private int findNext() { - int root = this.tree[0]+this.size; + int root = this.tree[0] + this.size; - for(int i = root; i > 0; i = (i-1)/2) + for (int i = root; i > 0; i = (i - 1) / 2) Writes.write(this.tree, i, -1, 0, false, true); - for(int i = root; i > 0; ) { - int j = i + ((i&1)<<1)-1; + for (int i = root; i > 0;) { + int j = i + ((i & 1) << 1) - 1; int c1 = this.tree[i] >> 31; int c2 = this.tree[j] >> 31; int nVal = (c1 & ((c2 & -1) + (~c2 & this.tree[j]))) + (~c1 & ((c2 & this.tree[i]) + (~c2 & -2))); - if(nVal == -2) { - if(i < j) nVal = this.treeCompare(i, j) ? this.tree[i] : this.tree[j]; - else nVal = this.treeCompare(j, i) ? this.tree[j] : this.tree[i]; + if (nVal == -2) { + if (i < j) + nVal = this.treeCompare(i, j) ? this.tree[i] : this.tree[j]; + else + nVal = this.treeCompare(j, i) ? this.tree[j] : this.tree[i]; } - i = (i-1)/2; - if(nVal != -1) Writes.write(this.tree, i, nVal, 0, false, true); + i = (i - 1) / 2; + if (nVal != -1) + Writes.write(this.tree, i, nVal, 0, false, true); } return this.peek(); } - @Override - public void runSort(int[] array, int length, int bucketCount) { + @Override + public void runSort(int[] array, int length, int bucketCount) { this.array = array; this.buildTree(length); @@ -125,7 +121,7 @@ public void runSort(int[] array, int length, int bucketCount) { Highlights.markArray(3, 0); Writes.write(this.tmp, 0, this.peek(), 1, false, true); - for(int i = 1; i < length; i++) { + for (int i = 1; i < length; i++) { int val = this.findNext(); Highlights.markArray(3, i); @@ -136,5 +132,5 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.deleteExternalArray(this.tree); Writes.deleteExternalArray(this.tmp); - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/select/CycleSort.java b/src/main/java/io/github/arrayv/sorts/select/CycleSort.java index 930b93c3..9c9477e3 100644 --- a/src/main/java/io/github/arrayv/sorts/select/CycleSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/CycleSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,26 +29,16 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Cycle") public final class CycleSort extends Sort { - public CycleSort(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - - this.setSortListName("Cycle"); - this.setRunAllSortsName("Cycle Sort"); - this.setRunSortName("Cyclesort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); - } + public CycleSort(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } private int countLesser(int[] array, int a, int b, int t) { int r = a; - for(int i = a+1; i < b; i++) { + for (int i = a + 1; i < b; i++) { Highlights.markArray(1, r); Highlights.markArray(2, i); Delays.sleep(0.01); @@ -58,28 +49,28 @@ private int countLesser(int[] array, int a, int b, int t) { return r; } - @Override - public void runSort(int[] array, int length, int bucketCount) { - for(int i = 0; i < length-1; i++) { + @Override + public void runSort(int[] array, int length, int bucketCount) { + for (int i = 0; i < length - 1; i++) { Highlights.markArray(3, i); int t = array[i]; int r = this.countLesser(array, i, length, t); - if(r != i) { + if (r != i) { do { - while(Reads.compareIndexValue(array, r, t, 0.01, true) == 0) r++; + while (Reads.compareIndexValue(array, r, t, 0.01, true) == 0) + r++; int t1 = array[r]; Writes.write(array, r, t, 0.02, false, false); t = t1; r = this.countLesser(array, i, length, t); - } - while(r != i); + } while (r != i); Writes.write(array, i, t, 0.02, false, false); } } - } + } } diff --git a/src/main/java/io/github/arrayv/sorts/select/DoubleSelectionSort.java b/src/main/java/io/github/arrayv/sorts/select/DoubleSelectionSort.java index ce6ea565..df3e4336 100644 --- a/src/main/java/io/github/arrayv/sorts/select/DoubleSelectionSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/DoubleSelectionSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,20 +29,10 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Double Selection") public final class DoubleSelectionSort extends Sort { public DoubleSelectionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Double Selection"); - this.setRunAllSortsName("Double Selection Sort"); - this.setRunSortName("Double Selection Sort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override @@ -51,24 +42,21 @@ public void runSort(int[] array, int length, int bucketCount) { int smallest = 0; int biggest = 0; - while(left <= right) { - for(int i = left; i <= right; i++) { + while (left <= right) { + for (int i = left; i <= right; i++) { Highlights.markArray(3, i); - if(Reads.compareValues(array[i], array[biggest]) == 1) { + if (Reads.compareIndices(array, i, biggest, 0.01, true) == 1) biggest = i; - Highlights.markArray(1, biggest); - Delays.sleep(0.01); - } - if(Reads.compareValues(array[i], array[smallest]) == -1) { + + if (Reads.compareIndices(array, i, smallest, 0.01, true) == -1) { smallest = i; Highlights.markArray(2, smallest); - Delays.sleep(0.01); } Delays.sleep(0.01); } - if(biggest == left) + if (biggest == left) biggest = smallest; Writes.swap(array, left, smallest, 0.02, true, false); diff --git a/src/main/java/io/github/arrayv/sorts/select/FlippedMinHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/FlippedMinHeapSort.java index af93b96f..acb3b3dc 100644 --- a/src/main/java/io/github/arrayv/sorts/select/FlippedMinHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/FlippedMinHeapSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -21,36 +22,26 @@ the only real changes are subtracting every array access from (length - 1) and removing the Writes.reverse() at the end the rest is just compacting the code a bit */ - +@SortMeta(name = "Flipped Min Heap") public final class FlippedMinHeapSort extends Sort { public FlippedMinHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Flipped Min Heap"); - this.setRunAllSortsName("Flipped Min Heap Sort"); - this.setRunSortName("Flipped Reverse Heapsort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } + private void siftDown(int[] array, int length, int root, int dist) { while (root <= dist / 2) { int leaf = 2 * root; - if (leaf < dist && Reads.compareValues(array[length - leaf], array[length - leaf - 1]) == 1) { + if (leaf < dist && Reads.compareIndices(array, length - leaf, length - leaf - 1, 0, true) == 1) { leaf++; } - Highlights.markArray(1, length - root); - Highlights.markArray(2, length - leaf); - Delays.sleep(1); - if (Reads.compareValues(array[length - root], array[length - leaf]) == 1) { + if (Reads.compareIndices(array, length - root, length - leaf, 1, true) == 1) { Writes.swap(array, length - root, length - leaf, 0, true, false); root = leaf; - } else break; + } else + break; } } + @Override public void runSort(int[] array, int length, int bucketCount) { for (int i = length / 2; i >= 1; i--) { diff --git a/src/main/java/io/github/arrayv/sorts/select/LazyHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/LazyHeapSort.java index 080276fc..b64ec47a 100644 --- a/src/main/java/io/github/arrayv/sorts/select/LazyHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/LazyHeapSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,27 +29,17 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Lazy Heap") public final class LazyHeapSort extends Sort { public LazyHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Lazy Heap"); - this.setRunAllSortsName("Lazy Heap Sort"); - this.setRunSortName("Lazy Heapsort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private void maxToFront(int[] array, int a, int b) { int max = a; - for(int i = a+1; i < b; i++) - if(Reads.compareIndices(array, i, max, 0.1, true) > 0) + for (int i = a + 1; i < b; i++) + if (Reads.compareIndices(array, i, max, 0.1, true) > 0) max = i; Writes.swap(array, max, a, 1, true, false); @@ -56,20 +47,20 @@ private void maxToFront(int[] array, int a, int b) { @Override public void runSort(int[] array, int length, int bucketCount) { - int s = (int)Math.sqrt(length-1)+1; + int s = (int) Math.sqrt(length - 1) + 1; - for(int i = 0; i < length; i += s) - this.maxToFront(array, i, Math.min(i+s, length)); + for (int i = 0; i < length; i += s) + this.maxToFront(array, i, Math.min(i + s, length)); - for(int j = length; j > 0;) { + for (int j = length; j > 0;) { int max = 0; - for(int i = max+s; i < j; i += s) - if(Reads.compareIndices(array, i, max, 0.1, true) >= 0) + for (int i = max + s; i < j; i += s) + if (Reads.compareIndices(array, i, max, 0.1, true) >= 0) max = i; Writes.swap(array, max, --j, 1, true, false); - this.maxToFront(array, max, Math.min(max+s, j)); + this.maxToFront(array, max, Math.min(max + s, j)); } } } diff --git a/src/main/java/io/github/arrayv/sorts/select/MaxHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/MaxHeapSort.java index 42975e2d..f855f858 100644 --- a/src/main/java/io/github/arrayv/sorts/select/MaxHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/MaxHeapSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.HeapSorting; /* @@ -14,20 +15,10 @@ Free Documentation License". * */ - +@SortMeta(name = "Max Heap") public final class MaxHeapSort extends HeapSorting { public MaxHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Max Heap"); - this.setRunAllSortsName("Max Heap Sort"); - this.setRunSortName("Heapsort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } public void makeHeap(int[] array, int start, int length, double sleep) { diff --git a/src/main/java/io/github/arrayv/sorts/select/MinHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/MinHeapSort.java index 0aff34a6..b4b4c171 100644 --- a/src/main/java/io/github/arrayv/sorts/select/MinHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/MinHeapSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.HeapSorting; /* @@ -14,20 +15,10 @@ Free Documentation License". * */ - +@SortMeta(name = "Min Heap") public final class MinHeapSort extends HeapSorting { public MinHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Min Heap"); - this.setRunAllSortsName("Min Heap Sort"); - this.setRunSortName("Reverse Heapsort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override diff --git a/src/main/java/io/github/arrayv/sorts/select/MinMaxHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/MinMaxHeapSort.java index 2deae8eb..1949d958 100644 --- a/src/main/java/io/github/arrayv/sorts/select/MinMaxHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/MinMaxHeapSort.java @@ -1,25 +1,17 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; // Min-Max Heaps translated from https://github.com/BartMassey/minmaxheap +@SortMeta(name = "Min-Max Heap") public final class MinMaxHeapSort extends Sort { int[] a; int start, end; public MinMaxHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Min-Max Heap"); - this.setRunAllSortsName("Min-Max Heap Sort"); - this.setRunSortName("Min-max Heapsort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } protected boolean compare(int x, int y, boolean isGt) { @@ -51,7 +43,7 @@ public void downheap(int i) { while (left < this.end) { int right = left + 1; int nexti = left; - for (int c : new int[] {right, 2 * left + 1, 2 * left + 2, 2 * right + 1, 2 * right + 2}) { + for (int c : new int[] { right, 2 * left + 1, 2 * left + 2, 2 * right + 1, 2 * right + 2 }) { if (c >= this.end) { break; } @@ -87,12 +79,12 @@ public void heapify() { } // public void store_min() { - // this.end--; - // if (this.end <= this.start) { - // return; - // } - // this.swap(this.start, this.end); - // this.downheap(this.start); + // this.end--; + // if (this.end <= this.start) { + // return; + // } + // this.swap(this.start, this.end); + // this.downheap(this.start); // } public void store_max() { diff --git a/src/main/java/io/github/arrayv/sorts/select/OutOfPlaceHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/OutOfPlaceHeapSort.java index 3b41f724..cb9e303d 100644 --- a/src/main/java/io/github/arrayv/sorts/select/OutOfPlaceHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/OutOfPlaceHeapSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,29 +29,24 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Out-of-Place Heap") public final class OutOfPlaceHeapSort extends Sort { public OutOfPlaceHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Out-of-Place Heap"); - this.setRunAllSortsName("Out-of-Place Heap Sort"); - this.setRunSortName("Out-of-Place Heapsort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } - //source: https://en.wikipedia.org/wiki/Heapsort#Bottom-up_heapsort + // source: https://en.wikipedia.org/wiki/Heapsort#Bottom-up_heapsort private void siftDown(int[] array, int i, int b) { int j = i; - for(; 2*j + 1 < b; j = 2*j + 2 < b ? (Reads.compareValues(array[2*j + 2], array[2*j + 1]) > 0 ? 2*j + 2 : 2*j + 1) : 2*j + 1); - for(; Reads.compareValues(array[i], array[j]) > 0; j = (j-1)/2); - for(; j > i; j = (j-1)/2) Writes.swap(array, i, j, 1, true, false); + for (; 2 * j + 1 < b; j = 2 * j + 2 < b + ? (Reads.compareValues(array[2 * j + 2], array[2 * j + 1]) > 0 ? 2 * j + 2 : 2 * j + 1) + : 2 * j + 1) + ; + for (; Reads.compareValues(array[i], array[j]) > 0; j = (j - 1) / 2) + ; + for (; j > i; j = (j - 1) / 2) + Writes.swap(array, i, j, 1, true, false); } private void findNext(int[] array, int b) { @@ -58,38 +54,35 @@ private void findNext(int[] array, int b) { int l = 1; int r = 2; - while(r < b && !(array[l] == -1 && array[r] == -1)) { - if(array[l] == -1) { + while (r < b && !(array[l] == -1 && array[r] == -1)) { + if (array[l] == -1) { Writes.swap(array, i, r, 1, true, false); i = r; - } - else if(array[r] == -1) { + } else if (array[r] == -1) { Writes.swap(array, i, l, 1, true, false); i = l; - } - else if(Reads.compareValues(array[r], array[l]) > 0) { + } else if (Reads.compareValues(array[r], array[l]) > 0) { Writes.swap(array, i, r, 1, true, false); i = r; - } - else { + } else { Writes.swap(array, i, l, 1, true, false); i = l; } - l = 2*i + 1; - r = l+1; + l = 2 * i + 1; + r = l + 1; } - if(l < b && array[l] != -1) + if (l < b && array[l] != -1) Writes.swap(array, i, l, 1, true, false); } @Override public void runSort(int[] array, int length, int bucketCount) { - for(int i = (length-1)/2; i >= 0; i--) + for (int i = (length - 1) / 2; i >= 0; i--) this.siftDown(array, i, length); int[] tmp = Writes.createExternalArray(length); - for(int i = length-1; i >= 0; i--) { + for (int i = length - 1; i >= 0; i--) { Writes.write(tmp, i, array[0], 0, true, true); Writes.write(array, 0, -1, 1, false, false); diff --git a/src/main/java/io/github/arrayv/sorts/select/PoplarHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/PoplarHeapSort.java index 72b6255c..2cb0943e 100644 --- a/src/main/java/io/github/arrayv/sorts/select/PoplarHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/PoplarHeapSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -26,20 +27,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ - +@SortMeta(name = "Poplar Heap") public class PoplarHeapSort extends Sort { public PoplarHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Poplar Heap"); - this.setRunAllSortsName("Poplar Heap Sort"); - this.setRunSortName("Poplar Heapsort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } //////////////////////////////////////////////////////////// @@ -70,7 +61,8 @@ private void unchecked_insertion_sort(int[] array, int first, int last) { } private void insertion_sort(int[] array, int first, int last) { - if (first == last) return; + if (first == last) + return; unchecked_insertion_sort(array, first, last); } @@ -79,7 +71,8 @@ private void insertion_sort(int[] array, int first, int last) { //////////////////////////////////////////////////////////// private void sift(int[] array, int first, int size) { - if (size < 2) return; + if (size < 2) + return; int root = first + (size - 1); int child_root1 = root - 1; @@ -93,13 +86,15 @@ private void sift(int[] array, int first, int size) { if (Reads.compareValues(array[max_root], array[child_root2]) == -1) { max_root = child_root2; } - if (max_root == root) return; + if (max_root == root) + return; Writes.swap(array, root, max_root, 0.75, true, false); Highlights.clearMark(2); size /= 2; - if (size < 2) return; + if (size < 2) + return; root = max_root; child_root1 = root - 1; @@ -117,7 +112,8 @@ private void pop_heap_with_size(int[] array, int first, int last, int size) { int it = first; while (true) { int root = it + poplar_size - 1; - if (root == last_root) break; + if (root == last_root) + break; if (Reads.compareValues(array[bigger], array[root]) == -1) { bigger = root; bigger_size = poplar_size; @@ -139,7 +135,8 @@ private void pop_heap_with_size(int[] array, int first, int last, int size) { private void make_heap(int[] array, int first, int last) { int size = last - first; - if (size < 2) return; + if (size < 2) + return; // A sorted collection is a valid poplar heap; whenever the heap // is small, using insertion sort should be faster, which is why @@ -184,7 +181,8 @@ private void make_heap(int[] array, int first, int last) { private void sort_heap(int[] array, int first, int last) { int size = last - first; - if (size < 2) return; + if (size < 2) + return; do { this.pop_heap_with_size(array, first, last, size); diff --git a/src/main/java/io/github/arrayv/sorts/select/SelectionSort.java b/src/main/java/io/github/arrayv/sorts/select/SelectionSort.java index 9a872cc8..c31bffe0 100644 --- a/src/main/java/io/github/arrayv/sorts/select/SelectionSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/SelectionSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,20 +29,10 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Selection") public final class SelectionSort extends Sort { public SelectionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Selection"); - this.setRunAllSortsName("Selection Sort"); - this.setRunSortName("Selection Sort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override @@ -49,16 +40,10 @@ public void runSort(int[] array, int length, int bucketCount) { for (int i = 0; i < length - 1; i++) { int lowestindex = i; - for (int j = i + 1; j < length; j++) { - Highlights.markArray(2, j); - Delays.sleep(0.01); - - if (Reads.compareValues(array[j], array[lowestindex]) == -1){ + for (int j = i + 1; j < length; j++) + if (Reads.compareIndices(array, j, lowestindex, 0.01, true) == -1) lowestindex = j; - Highlights.markArray(1, lowestindex); - Delays.sleep(0.01); - } - } + Writes.swap(array, i, lowestindex, 0.02, true, false); } } diff --git a/src/main/java/io/github/arrayv/sorts/select/SmoothSort.java b/src/main/java/io/github/arrayv/sorts/select/SmoothSort.java index 298f7b73..b8bdb0fb 100644 --- a/src/main/java/io/github/arrayv/sorts/select/SmoothSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/SmoothSort.java @@ -1,45 +1,35 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Smooth") public final class SmoothSort extends Sort { public SmoothSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Smooth"); - this.setRunAllSortsName("Smooth Sort"); - this.setRunSortName("Smoothsort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } // SMOOTH SORT - Provided here: // https://stackoverflow.com/questions/1390832/how-to-sort-nearly-sorted-array-in-the-fastest-time-possible-java/28352545#28352545 - static final int LP[] = {1, 1, 3, 5, 9, 15, 25, 41, 67, 109, - 177, 287, 465, 753, 1219, 1973, 3193, 5167, 8361, 13529, 21891}; - /* - 35421, 57313, 92735, 150049, 242785, 392835, 635621, 1028457, - 1664079, 2692537, 4356617, 7049155, 11405773, 18454929, 29860703, - 48315633, 78176337, 126491971, 204668309, 331160281, 535828591, - 866988873 // the next number is > 31 bits. - */ - - private void sift(int[] A, int pshift, int head) - { + static final int LP[] = { 1, 1, 3, 5, 9, 15, 25, 41, 67, 109, + 177, 287, 465, 753, 1219, 1973, 3193, 5167, 8361, 13529, 21891 }; + /* + * 35421, 57313, 92735, 150049, 242785, 392835, 635621, 1028457, + * 1664079, 2692537, 4356617, 7049155, 11405773, 18454929, 29860703, + * 48315633, 78176337, 126491971, 204668309, 331160281, 535828591, + * 866988873 // the next number is > 31 bits. + */ + + private void sift(int[] A, int pshift, int head) { // we do not use Floyd's improvements to the heapsort sift, because we // are not doing what heapsort does - always moving nodes from near // the bottom of the tree to the root. int val = A[head]; - while (pshift > 1) - { + while (pshift > 1) { int rt = head - 1; int lf = head - 1 - LP[pshift - 2]; @@ -55,8 +45,7 @@ private void sift(int[] A, int pshift, int head) Writes.write(A, head, A[lf], 0.65, true, false); head = lf; pshift -= 1; - } - else { + } else { Writes.write(A, head, A[rt], 0.65, true, false); head = rt; pshift -= 2; @@ -68,12 +57,10 @@ private void sift(int[] A, int pshift, int head) Highlights.clearMark(3); } - private void trinkle(int[] A, int p, int pshift, int head, boolean isTrusty) - { + private void trinkle(int[] A, int p, int pshift, int head, boolean isTrusty) { int val = A[head]; - while (p != 1) - { + while (p != 1) { int stepson = head - LP[pshift]; if (Reads.compareValues(A[stepson], val) <= 0) @@ -91,7 +78,7 @@ private void trinkle(int[] A, int p, int pshift, int head, boolean isTrusty) Delays.sleep(0.325); if (Reads.compareValues(A[rt], A[stepson]) >= 0 || - Reads.compareValues(A[lf], A[stepson]) >= 0) + Reads.compareValues(A[lf], A[stepson]) >= 0) break; } Writes.write(A, head, A[stepson], 0.65, true, false); @@ -100,7 +87,7 @@ private void trinkle(int[] A, int p, int pshift, int head, boolean isTrusty) Highlights.clearMark(3); head = stepson; - //int trail = Integer.numberOfTrailingZeros(p & ~1); + // int trail = Integer.numberOfTrailingZeros(p & ~1); int trail = Integer.numberOfTrailingZeros(p & ~1); p >>= trail; pshift += trail; @@ -113,8 +100,7 @@ private void trinkle(int[] A, int p, int pshift, int head, boolean isTrusty) } } - private void smoothSort(int[] A, int lo, int hi, boolean fullSort) - { + private void smoothSort(int[] A, int lo, int hi, boolean fullSort) { int head = lo; // the offset of the first element of the prefix into m // These variables need a little explaining. If our string of heaps @@ -131,16 +117,14 @@ private void smoothSort(int[] A, int lo, int hi, boolean fullSort) int p = 1; // the bitmap of the current standard concatenation >> pshift int pshift = 1; - while (head < hi) - { + while (head < hi) { if ((p & 3) == 3) { // Add 1 by merging the first two blocks into a larger one. // The next Leonardo number is one bigger. this.sift(A, pshift, head); p >>= 2; pshift += 2; - } - else { + } else { // adding a new block of length 1 if (LP[pshift - 1] >= hi - head) { // this block is its final size. @@ -164,25 +148,23 @@ private void smoothSort(int[] A, int lo, int hi, boolean fullSort) head++; } - if(fullSort) { + if (fullSort) { this.trinkle(A, p, pshift, head, false); - while (pshift != 1 || p != 1) - { + while (pshift != 1 || p != 1) { if (pshift <= 1) { // block of length 1. No fiddling needed int trail = Integer.numberOfTrailingZeros(p & ~1); p >>= trail; - pshift += trail; - } - else { + pshift += trail; + } else { p <<= 2; p ^= 7; pshift -= 2; // This block gets broken into three bits. The rightmost bit is a // block of length 1. The left hand part is split into two, a block - // of length LP[pshift+1] and one of LP[pshift]. Both these two + // of length LP[pshift+1] and one of LP[pshift]. Both these two // are appropriately heapified, but the root nodes are not // necessarily in order. We therefore semitrinkle both of them diff --git a/src/main/java/io/github/arrayv/sorts/select/StableCycleSort.java b/src/main/java/io/github/arrayv/sorts/select/StableCycleSort.java index 03caa543..f0855508 100644 --- a/src/main/java/io/github/arrayv/sorts/select/StableCycleSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/StableCycleSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -28,20 +29,10 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Stable Cycle") public final class StableCycleSort extends Sort { public StableCycleSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Stable Cycle"); - this.setRunAllSortsName("Stable Cycle Sort"); - this.setRunSortName("Stable Cyclesort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private final int WLEN = 3; @@ -59,17 +50,19 @@ private void flag(int[] bits, int idx) { private int destination1(int[] array, int[] bits, int a, int b1, int b) { int d = a, e = 0; - for(int i = a+1; i < b; i++) { + for (int i = a + 1; i < b; i++) { Highlights.markArray(2, i); int cmp = Reads.compareValues(array[i], array[a]); - if(cmp < 0) d++; - else if(i < b1 && !this.getBit(bits, i) && cmp == 0) e++; + if (cmp < 0) + d++; + else if (i < b1 && !this.getBit(bits, i) && cmp == 0) + e++; Highlights.markArray(3, d); Delays.sleep(0.01); } - while(this.getBit(bits, d) || e-- > 0) { + while (this.getBit(bits, d) || e-- > 0) { d++; Highlights.markArray(3, d); @@ -81,10 +74,10 @@ private int destination1(int[] array, int[] bits, int a, int b1, int b) { @Override public void runSort(int[] array, int length, int bucketCount) { - int[] bits = Writes.createExternalArray(((length-1) >> WLEN) + 1); + int[] bits = Writes.createExternalArray(((length - 1) >> WLEN) + 1); - for(int i = 0; i < length-1; i++) { - if(!this.getBit(bits, i)) { + for (int i = 0; i < length - 1; i++) { + if (!this.getBit(bits, i)) { Highlights.markArray(1, i); int j = i; @@ -93,8 +86,7 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.swap(array, i, k, 0.02, true, false); this.flag(bits, k); j = k; - } - while(j != i); + } while (j != i); } } Writes.deleteExternalArray(bits); diff --git a/src/main/java/io/github/arrayv/sorts/select/StableSelectionSort.java b/src/main/java/io/github/arrayv/sorts/select/StableSelectionSort.java index c086959d..dbf8b10e 100644 --- a/src/main/java/io/github/arrayv/sorts/select/StableSelectionSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/StableSelectionSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -24,35 +25,21 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. * */ - +@SortMeta(name = "Stable Selection") public final class StableSelectionSort extends Sort { - public StableSelectionSort(ArrayVisualizer arrayVisualizer) { + public StableSelectionSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Stable Selection"); - this.setRunAllSortsName("Stable Selection Sort"); - this.setRunSortName("Stable Selection Sort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } @Override public void runSort(int[] array, int length, int bucketCount) { for (int i = 0; i < length - 1; i++) { int min = i; - for (int j = i + 1; j < length; j++) { - Highlights.markArray(1, j); - if (Reads.compareValues(array[j], array[min]) == -1) { + for (int j = i + 1; j < length; j++) + if (Reads.compareIndices(array, j, min, 1, true) == -1) min = j; - Highlights.markArray(2, j); - } - Delays.sleep(1); - } + Highlights.clearMark(2); int tmp = array[min]; int pos = min; diff --git a/src/main/java/io/github/arrayv/sorts/select/TernaryHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/TernaryHeapSort.java index a95ffe18..7dd53ad6 100644 --- a/src/main/java/io/github/arrayv/sorts/select/TernaryHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/TernaryHeapSort.java @@ -1,21 +1,13 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; +@SortMeta(name = "Ternary Heap") public final class TernaryHeapSort extends Sort { public TernaryHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Ternary Heap"); - this.setRunAllSortsName("Ternary Heap Sort"); - this.setRunSortName("Ternary Heapsort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } // TERNARY HEAP SORT - written by qbit @@ -44,16 +36,15 @@ private void maxHeapify(int[] array, int i) { largest = leftChild <= heapSize && Reads.compareValues(array[leftChild], array[i]) > 0 ? leftChild : i; - if(rightChild <= heapSize && Reads.compareValues(array[rightChild], array[largest]) > 0) { + if (rightChild <= heapSize && Reads.compareValues(array[rightChild], array[largest]) > 0) { largest = rightChild; } - if(middleChild <= heapSize && Reads.compareValues(array[middleChild], array[largest]) > 0) { + if (middleChild <= heapSize && Reads.compareValues(array[middleChild], array[largest]) > 0) { largest = middleChild; } - - if(largest != i) { + if (largest != i) { Writes.swap(array, i, largest, 1, true, false); this.maxHeapify(array, largest); } @@ -61,7 +52,7 @@ private void maxHeapify(int[] array, int i) { private void buildMaxTernaryHeap(int[] array, int length) { heapSize = length - 1; - for(int i = length - 1 / 3; i >= 0; i--) + for (int i = length - 1 / 3; i >= 0; i--) this.maxHeapify(array, i); } @@ -69,10 +60,10 @@ private void buildMaxTernaryHeap(int[] array, int length) { public void runSort(int[] array, int length, int bucketCount) { this.buildMaxTernaryHeap(array, length); - for(int i = length - 1; i >= 0; i--){ - Writes.swap(array, 0, i, 1, true, false); //add last element on array, i.e heap root + for (int i = length - 1; i >= 0; i--) { + Writes.swap(array, 0, i, 1, true, false); // add last element on array, i.e heap root - heapSize = heapSize - 1; //shrink heap by 1 + heapSize = heapSize - 1; // shrink heap by 1 this.maxHeapify(array, 0); } } diff --git a/src/main/java/io/github/arrayv/sorts/select/TournamentSort.java b/src/main/java/io/github/arrayv/sorts/select/TournamentSort.java index cc5bed10..81f05f18 100644 --- a/src/main/java/io/github/arrayv/sorts/select/TournamentSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/TournamentSort.java @@ -1,6 +1,7 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /* @@ -20,23 +21,13 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ - +@SortMeta(name = "Tournament") public final class TournamentSort extends Sort { private int[] matches; private int tourney; public TournamentSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Tournament"); - this.setRunAllSortsName("Tournament Sort"); - this.setRunSortName("Tournament Sort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private int tourneyCompare(int a, int b) { @@ -55,21 +46,27 @@ private static boolean isPlayer(int i) { private void setWinner(int root, int winner) { Writes.write(matches, root, winner, 0, false, true); } + private void setWinners(int root, int winners) { Writes.write(matches, root + 1, winners, 0, false, true); } + private void setLosers(int root, int losers) { Writes.write(matches, root + 2, losers, 0, false, true); } + private int getWinner(int root) { return matches[root]; } + private int getWinners(int root) { return matches[root + 1]; } + private int getLosers(int root) { return matches[root + 2]; } + private void setMatch(int root, int winner, int winners, int losers) { this.setWinner(root, winner); this.setWinners(root, winners); @@ -103,10 +100,12 @@ private int makeMatch(int[] arr, int top, int bot, int root) { } private int knockout(int[] arr, int i, int k, int root) { - if (i == k) return TournamentSort.makePlayer(i); + if (i == k) + return TournamentSort.makePlayer(i); int j = (i + k) / 2; - return this.makeMatch(arr, this.knockout(arr, i, j, 2 * root), this.knockout(arr,j + 1, k, (2 * root) + 3), root); + return this.makeMatch(arr, this.knockout(arr, i, j, 2 * root), this.knockout(arr, j + 1, k, (2 * root) + 3), + root); } private int rebuild(int[] arr, int root) { @@ -122,8 +121,7 @@ private int rebuild(int[] arr, int root) { this.setLosers(root, this.getWinners(root)); this.setWinners(root, temp); - } - else { + } else { this.setWinner(root, this.getPlayer(this.getWinners(root))); } diff --git a/src/main/java/io/github/arrayv/sorts/select/TriangularHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/TriangularHeapSort.java index a02b7179..dc98b92d 100644 --- a/src/main/java/io/github/arrayv/sorts/select/TriangularHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/TriangularHeapSort.java @@ -1,25 +1,17 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; /** * @author aphitorite */ +@SortMeta(name = "Triangular Heap") public final class TriangularHeapSort extends Sort { public TriangularHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - // TODO Auto-generated constructor stub - this.setSortListName("Triangular Heap"); - this.setRunAllSortsName("Triangular Heap Sort"); - this.setRunSortName("Triangular Heapsort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } public static int triangularRoot(int val) { @@ -66,7 +58,6 @@ public void triangularHeapify(int[] array, int length) { @Override public void runSort(int[] array, int length, int bucketCount) { - // TODO Auto-generated method stub triangularHeapify(array, length); for (int i = 1; i < length - 1; i++) { this.Writes.swap(array, 0, length - i, 0.5D, true, false); diff --git a/src/main/java/io/github/arrayv/sorts/select/WeakHeapSort.java b/src/main/java/io/github/arrayv/sorts/select/WeakHeapSort.java index 4b43d00f..dbb0dcd4 100644 --- a/src/main/java/io/github/arrayv/sorts/select/WeakHeapSort.java +++ b/src/main/java/io/github/arrayv/sorts/select/WeakHeapSort.java @@ -1,23 +1,15 @@ package io.github.arrayv.sorts.select; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.sorts.templates.Sort; // Refactored from C++ code written by Manish Bhojasia, found here: // https://www.sanfoundry.com/cpp-program-implement-weak-heap/ +@SortMeta(name = "Weak Heap") public final class WeakHeapSort extends Sort { public WeakHeapSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - - this.setSortListName("Weak Heap"); - this.setRunAllSortsName("Weak Heap Sort"); - this.setRunSortName("Weak Heapsort"); - this.setCategory("Selection Sorts"); - this.setBucketSort(false); - this.setRadixSort(false); - this.setUnreasonablySlow(false); - this.setUnreasonableLimit(0); - this.setBogoSort(false); } private static int getBitwiseFlag(int[] bits, int x) { @@ -35,8 +27,7 @@ private void toggleBitwiseFlag(int[] bits, int x) { * Merge Weak Heap */ private void weakHeapMerge(int[] array, int[] bits, int i, int j) { - if (Reads.compareValues(array[i], array[j]) == -1) - { + if (Reads.compareValues(array[i], array[j]) == -1) { this.toggleBitwiseFlag(bits, j); Writes.swap(array, i, j, 1, true, false); } diff --git a/src/main/java/io/github/arrayv/sorts/select/package-info.java b/src/main/java/io/github/arrayv/sorts/select/package-info.java new file mode 100644 index 00000000..1df2c27c --- /dev/null +++ b/src/main/java/io/github/arrayv/sorts/select/package-info.java @@ -0,0 +1,2 @@ +@io.github.arrayv.sortdata.SortPackageMeta(category = "Selection Sorts") +package io.github.arrayv.sorts.select; diff --git a/src/main/java/io/github/arrayv/sorts/templates/BinaryInsertionSorting.java b/src/main/java/io/github/arrayv/sorts/templates/BinaryInsertionSorting.java index f4f8ba46..ea4a537a 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/BinaryInsertionSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/BinaryInsertionSorting.java @@ -46,10 +46,10 @@ protected void binaryInsertSort(int[] array, int start, int end, double compSlee Delays.sleep(compSleep); - if (Reads.compareValues(num, array[mid]) < 0) { // do NOT move equal elements to right of inserted element; this maintains stability! + if (Reads.compareValues(num, array[mid]) < 0) { // do NOT move equal elements to right of inserted + // element; this maintains stability! hi = mid; - } - else { + } else { lo = mid + 1; } } @@ -60,8 +60,7 @@ protected void binaryInsertSort(int[] array, int start, int end, double compSlee int j = i - 1; - while (j >= lo) - { + while (j >= lo) { Writes.write(array, j + 1, array[j], writeSleep, true, false); j--; } diff --git a/src/main/java/io/github/arrayv/sorts/templates/BinaryQuickSorting.java b/src/main/java/io/github/arrayv/sorts/templates/BinaryQuickSorting.java index 5104cdec..7bc45ac0 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/BinaryQuickSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/BinaryQuickSorting.java @@ -32,45 +32,38 @@ public static class Task { public int r; public int bit; - public Task(int p, int r, int bit) - { + public Task(int p, int r, int bit) { this.p = p; this.r = r; this.bit = bit; } } - public void binaryQuickSortRecursive(int[] array, int p, int r, int bit) - { - if (p < r && bit >= 0) - { + public void binaryQuickSortRecursive(int[] array, int p, int r, int bit) { + if (p < r && bit >= 0) { int q = partition(array, p, r, bit); Delays.sleep(1); - binaryQuickSortRecursive(array, p, q, bit-1); - binaryQuickSortRecursive(array, q+1, r, bit-1); + binaryQuickSortRecursive(array, p, q, bit - 1); + binaryQuickSortRecursive(array, q + 1, r, bit - 1); } } - public void binaryQuickSort(int[] array, int p, int r, int bit) - { + public void binaryQuickSort(int[] array, int p, int r, int bit) { Queue tasks = new LinkedList<>(); tasks.add(new Task(p, r, bit)); - while (tasks.isEmpty() == false) - { + while (tasks.isEmpty() == false) { Task task = tasks.remove(); - if (task.p < task.r && task.bit >= 0) - { + if (task.p < task.r && task.bit >= 0) { int q = partition(array, task.p, task.r, task.bit); Delays.sleep(1); - tasks.add(new Task(task.p, q, task.bit-1)); - tasks.add(new Task(q+1, task.r, task.bit-1)); + tasks.add(new Task(task.p, q, task.bit - 1)); + tasks.add(new Task(q + 1, task.r, task.bit - 1)); } } } - public int partition(int[] array, int p, int r, int bit) - { + public int partition(int[] array, int p, int r, int bit) { int i = p - 1; int j = r + 1; @@ -79,14 +72,14 @@ public int partition(int[] array, int p, int r, int bit) while (true) { // Left is not set i++; - while(i <= r && !Reads.getBit(array[i], bit)) { + while (i <= r && !Reads.getBit(array[i], bit)) { i++; Highlights.markArray(1, i); Delays.sleep(0.45); } // Right is set j--; - while(j >= p && Reads.getBit(array[j], bit)) { + while (j >= p && Reads.getBit(array[j], bit)) { j--; Highlights.markArray(2, j); Delays.sleep(0.45); diff --git a/src/main/java/io/github/arrayv/sorts/templates/BlockMergeSorting.java b/src/main/java/io/github/arrayv/sorts/templates/BlockMergeSorting.java index 68a2efd2..f0ba867f 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/BlockMergeSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/BlockMergeSorting.java @@ -30,45 +30,54 @@ of this software and associated documentation files (the "Software"), to deal */ public abstract class BlockMergeSorting extends Sort { - protected BlockMergeSorting(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - } + protected BlockMergeSorting(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } protected final int MRUN = 16; protected void shiftFW(int[] array, int a, int m, int b) { - while(m < b) Writes.swap(array, a++, m++, 1, true, false); + while (m < b) + Writes.swap(array, a++, m++, 1, true, false); } + protected void shiftBW(int[] array, int a, int m, int b) { - while(m > a) Writes.swap(array, --b, --m, 1, true, false); + while (m > a) + Writes.swap(array, --b, --m, 1, true, false); } protected void shiftFWExt(int[] array, int a, int m, int b) { Highlights.clearMark(2); - while(m < b) Writes.write(array, a++, array[m++], 1, true, false); + while (m < b) + Writes.write(array, a++, array[m++], 1, true, false); } + protected void shiftBWExt(int[] array, int a, int m, int b) { Highlights.clearMark(2); - while(m > a) Writes.write(array, --b, array[--m], 1, true, false); + while (m > a) + Writes.write(array, --b, array[--m], 1, true, false); } protected void insertTo(int[] array, int a, int b) { - Highlights.clearMark(2); - int temp = array[a]; - while(a > b) Writes.write(array, a, array[--a], 0.5, true, false); - Writes.write(array, b, temp, 0.5, true, false); - } - protected void insertToBW(int[] array, int a, int b) { - Highlights.clearMark(2); - int temp = array[a]; - while(a < b) Writes.write(array, a, array[++a], 0.5, true, false); - Writes.write(array, a, temp, 0.5, true, false); - } + Highlights.clearMark(2); + int temp = array[a]; + while (a > b) + Writes.write(array, a, array[--a], 0.5, true, false); + Writes.write(array, b, temp, 0.5, true, false); + } + + protected void insertToBW(int[] array, int a, int b) { + Highlights.clearMark(2); + int temp = array[a]; + while (a < b) + Writes.write(array, a, array[++a], 0.5, true, false); + Writes.write(array, a, temp, 0.5, true, false); + } protected void multiSwap(int[] array, int a, int b, int len) { - for(int i = 0; i < len; i++) - Writes.swap(array, a+i, b+i, 1, true, false); - } + for (int i = 0; i < len; i++) + Writes.swap(array, a + i, b + i, 1, true, false); + } protected void rotate(int[] array, int a, int m, int b) { Highlights.clearMark(2); @@ -76,277 +85,302 @@ protected void rotate(int[] array, int a, int m, int b) { } protected int leftBinSearch(int[] array, int a, int b, int val) { - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; Highlights.markArray(2, m); Delays.sleep(0.25); - if(Reads.compareValues(val, array[m]) <= 0) + if (Reads.compareValues(val, array[m]) <= 0) b = m; else - a = m+1; + a = m + 1; } return a; } + protected int rightBinSearch(int[] array, int a, int b, int val) { - while(a < b) { - int m = a+(b-a)/2; + while (a < b) { + int m = a + (b - a) / 2; Highlights.markArray(2, m); Delays.sleep(0.25); - if(Reads.compareValues(val, array[m]) < 0) + if (Reads.compareValues(val, array[m]) < 0) b = m; else - a = m+1; + a = m + 1; } return a; } protected boolean buildRuns(int[] array, int a, int b) { boolean noSort = true; - int i = a+1, j = a; - - while(i < b) { - if(Reads.compareIndices(array, i-1, i++, 1, true) == 1) { - while(i < b && Reads.compareIndices(array, i-1, i, 1, true) == 1) i++; - Writes.reversal(array, j, i-1, 1, true, false); - } - else while(i < b && Reads.compareIndices(array, i-1, i, 1, true) <= 0) i++; - - if(i < b) { + int i = a + 1, j = a; + + while (i < b) { + if (Reads.compareIndices(array, i - 1, i++, 1, true) == 1) { + while (i < b && Reads.compareIndices(array, i - 1, i, 1, true) == 1) + i++; + Writes.reversal(array, j, i - 1, 1, true, false); + } else + while (i < b && Reads.compareIndices(array, i - 1, i, 1, true) <= 0) + i++; + + if (i < b) { noSort = false; - j = i - (i-j-1)%this.MRUN - 1; //a%b, if(a%b == 0) -> a = b + j = i - (i - j - 1) % this.MRUN - 1; // a%b, if(a%b == 0) -> a = b + } + while (i - j < this.MRUN && i < b) { + this.insertTo(array, i, this.rightBinSearch(array, j, i, array[i])); + i++; } - while(i-j < this.MRUN && i < b) { - this.insertTo(array, i, this.rightBinSearch(array, j, i, array[i])); - i++; - } - j = i++; - } + j = i++; + } return noSort; - } + } protected int findKeys(int[] array, int a, int b, int nKeys, int n) { - int p = a, pEnd = a+nKeys; - - Highlights.clearMark(2); - for(int i = pEnd; i < b && nKeys < n; i++) { - Highlights.markArray(1, i); - Delays.sleep(1); - int loc = this.leftBinSearch(array, p, pEnd, array[i]); - - if(pEnd == loc || Reads.compareValues(array[i], array[loc]) != 0) { - this.rotate(array, p, pEnd, i); - int inc = i-pEnd; - loc += inc; - p += inc; - pEnd += inc; - - this.insertTo(array, pEnd, loc); - nKeys++; - pEnd++; - } - } - this.rotate(array, a, p, pEnd); - return nKeys; - } + int p = a, pEnd = a + nKeys; + + Highlights.clearMark(2); + for (int i = pEnd; i < b && nKeys < n; i++) { + Highlights.markArray(1, i); + Delays.sleep(1); + int loc = this.leftBinSearch(array, p, pEnd, array[i]); + + if (pEnd == loc || Reads.compareValues(array[i], array[loc]) != 0) { + this.rotate(array, p, pEnd, i); + int inc = i - pEnd; + loc += inc; + p += inc; + pEnd += inc; + + this.insertTo(array, pEnd, loc); + nKeys++; + pEnd++; + } + } + this.rotate(array, a, p, pEnd); + return nKeys; + } + protected int findKeysBW(int[] array, int a, int b, int nKeys, int n) { - int p = b-nKeys, pEnd = b; - - Highlights.clearMark(2); - for(int i = p-1; i >= a && nKeys < n; i--) { - Highlights.markArray(1, i); - Delays.sleep(1); - int loc = this.leftBinSearch(array, p, pEnd, array[i]); - - if(pEnd == loc || Reads.compareValues(array[i], array[loc]) != 0) { - this.rotate(array, i+1, p, pEnd); - int inc = p-(i+1); - loc -= inc; - pEnd -= inc; - p -= inc+1; - nKeys++; - - this.insertToBW(array, i, loc-1); - } - } - this.rotate(array, p, pEnd, b); - return nKeys; - } + int p = b - nKeys, pEnd = b; + + Highlights.clearMark(2); + for (int i = p - 1; i >= a && nKeys < n; i--) { + Highlights.markArray(1, i); + Delays.sleep(1); + int loc = this.leftBinSearch(array, p, pEnd, array[i]); + + if (pEnd == loc || Reads.compareValues(array[i], array[loc]) != 0) { + this.rotate(array, i + 1, p, pEnd); + int inc = p - (i + 1); + loc -= inc; + pEnd -= inc; + p -= inc + 1; + nKeys++; + + this.insertToBW(array, i, loc - 1); + } + } + this.rotate(array, p, pEnd, b); + return nKeys; + } protected void binaryInsertion(int[] array, int a, int b) { - for(int i = a+1; i < b; i++) - this.insertTo(array, i, this.rightBinSearch(array, a, i, array[i])); - } + for (int i = a + 1; i < b; i++) + this.insertTo(array, i, this.rightBinSearch(array, a, i, array[i])); + } protected boolean boundCheck(int[] array, int a, int m, int b) { - return m >= b || Reads.compareValues(array[m-1], array[m]) <= 0; + return m >= b || Reads.compareValues(array[m - 1], array[m]) <= 0; } protected void mergeBW(int[] array, int a, int m, int b, int p) { - if(this.boundCheck(array, a, m, b)) return; + if (this.boundCheck(array, a, m, b)) + return; - int pLen = b-m; - this.multiSwap(array, m, p, pLen); + int pLen = b - m; + this.multiSwap(array, m, p, pLen); - int i = pLen-1, j = m-1, k = b-1; + int i = pLen - 1, j = m - 1, k = b - 1; + + while (i >= 0 && j >= a) { + if (Reads.compareValues(array[p + i], array[j]) >= 0) + Writes.swap(array, k--, p + (i--), 1, true, false); + else + Writes.swap(array, k--, j--, 1, true, false); + } + while (i >= 0) + Writes.swap(array, k--, p + (i--), 1, true, false); + } - while(i >= 0 && j >= a) { - if(Reads.compareValues(array[p+i], array[j]) >= 0) - Writes.swap(array, k--, p+(i--), 1, true, false); - else - Writes.swap(array, k--, j--, 1, true, false); - } - while(i >= 0) Writes.swap(array, k--, p+(i--), 1, true, false); - } protected void mergeTo(int[] array, int a, int m, int b, int p) { int i = a, j = m; - while(i < m && j < b) { - if(Reads.compareValues(array[i], array[j]) <= 0) + while (i < m && j < b) { + if (Reads.compareValues(array[i], array[j]) <= 0) Writes.swap(array, p++, i++, 1, true, false); else Writes.swap(array, p++, j++, 1, true, false); } - while(i < m) Writes.swap(array, p++, i++, 1, true, false); - while(j < b) Writes.swap(array, p++, j++, 1, true, false); + while (i < m) + Writes.swap(array, p++, i++, 1, true, false); + while (j < b) + Writes.swap(array, p++, j++, 1, true, false); } + protected void pingPongMerge(int[] array, int a, int m1, int m2, int m3, int b, int p) { - if(Reads.compareValues(array[m1-1], array[m1]) > 0 - || (m3 < b && Reads.compareValues(array[m3-1], array[m3]) > 0)) { - int p1 = p + m2-a, pEnd = p + b-a; + if (Reads.compareValues(array[m1 - 1], array[m1]) > 0 + || (m3 < b && Reads.compareValues(array[m3 - 1], array[m3]) > 0)) { + int p1 = p + m2 - a, pEnd = p + b - a; this.mergeTo(array, a, m1, m2, p); this.mergeTo(array, m2, m3, b, p1); this.mergeTo(array, p, p1, pEnd, a); - } - else this.mergeBW(array, a, m2, b, p); + } else + this.mergeBW(array, a, m2, b, p); } protected void mergeFWExt(int[] array, int[] tmp, int a, int m, int b) { - int s = m-a; + int s = m - a; Writes.arraycopy(array, a, tmp, 0, s, 1, true, true); int i = 0, j = m; - while(i < s && j < b) { - if(Reads.compareValues(tmp[i], array[j]) <= 0) + while (i < s && j < b) { + if (Reads.compareValues(tmp[i], array[j]) <= 0) Writes.write(array, a++, tmp[i++], 1, true, false); else Writes.write(array, a++, array[j++], 1, true, false); } - while(i < s) Writes.write(array, a++, tmp[i++], 1, true, false); + while (i < s) + Writes.write(array, a++, tmp[i++], 1, true, false); } + protected void mergeBWExt(int[] array, int[] tmp, int a, int m, int b) { - int s = b-m; + int s = b - m; Writes.arraycopy(array, m, tmp, 0, s, 1, true, true); - int i = s-1, j = m-1; + int i = s - 1, j = m - 1; - while(i >= 0 && j >= a) { - if(Reads.compareValues(tmp[i], array[j]) >= 0) + while (i >= 0 && j >= a) { + if (Reads.compareValues(tmp[i], array[j]) >= 0) Writes.write(array, --b, tmp[i--], 1, true, false); else Writes.write(array, --b, array[j--], 1, true, false); } - while(i >= 0) Writes.write(array, --b, tmp[i--], 1, true, false); + while (i >= 0) + Writes.write(array, --b, tmp[i--], 1, true, false); } protected void mergeWithBufFW(int[] array, int a, int m, int b, int p) { int i = m; - while(a < m && i < b) { + while (a < m && i < b) { Highlights.markArray(2, i); - if(Reads.compareValues(array[a], array[i]) <= 0) + if (Reads.compareValues(array[a], array[i]) <= 0) Writes.swap(array, p++, a++, 1, true, false); else Writes.swap(array, p++, i++, 1, true, false); } - if(a > p) this.shiftFW(array, p, a, m); + if (a > p) + this.shiftFW(array, p, a, m); this.shiftFW(array, p, i, b); } + protected void mergeWithBufBW(int[] array, int a, int m, int b, int p) { - int i = m-1; b--; + int i = m - 1; + b--; - while(b >= m && i >= a) { + while (b >= m && i >= a) { Highlights.markArray(2, i); - if(Reads.compareValues(array[b], array[i]) >= 0) + if (Reads.compareValues(array[b], array[i]) >= 0) Writes.swap(array, --p, b--, 1, true, false); else Writes.swap(array, --p, i--, 1, true, false); } - if(p > b) this.shiftBW(array, m, b+1, p); + if (p > b) + this.shiftBW(array, m, b + 1, p); - this.shiftBW(array, a, i+1, p); + this.shiftBW(array, a, i + 1, p); } + protected void mergeWithBufFWExt(int[] array, int a, int m, int b, int p) { int i = m; - while(a < m && i < b) { + while (a < m && i < b) { Highlights.markArray(2, i); - if(Reads.compareValues(array[a], array[i]) <= 0) + if (Reads.compareValues(array[a], array[i]) <= 0) Writes.write(array, p++, array[a++], 1, true, false); else Writes.write(array, p++, array[i++], 1, true, false); } - if(a > p) this.shiftFWExt(array, p, a, m); + if (a > p) + this.shiftFWExt(array, p, a, m); this.shiftFWExt(array, p, i, b); } + protected void mergeWithBufBWExt(int[] array, int a, int m, int b, int p) { - int i = m-1; b--; + int i = m - 1; + b--; - while(b >= m && i >= a) { + while (b >= m && i >= a) { Highlights.markArray(2, i); - if(Reads.compareValues(array[b], array[i]) >= 0) + if (Reads.compareValues(array[b], array[i]) >= 0) Writes.write(array, --p, array[b--], 1, true, false); else Writes.write(array, --p, array[i--], 1, true, false); } - if(p > b) this.shiftBWExt(array, m, b+1, p); + if (p > b) + this.shiftBWExt(array, m, b + 1, p); - this.shiftBWExt(array, a, i+1, p); + this.shiftBWExt(array, a, i + 1, p); } protected void inPlaceMerge(int[] array, int a, int m, int b) { - while(a < m && m < b) { + while (a < m && m < b) { a = this.rightBinSearch(array, a, m, array[m]); - if(a == m) return; + if (a == m) + return; int i = this.leftBinSearch(array, m, b, array[a]); this.rotate(array, a, m, i); - int t = i-m; + int t = i - m; m = i; - a += t+1; + a += t + 1; } } + protected void inPlaceMergeBW(int[] array, int a, int m, int b) { - while(b > m && m > a) { - int i = this.rightBinSearch(array, a, m, array[b-1]); + while (b > m && m > a) { + int i = this.rightBinSearch(array, a, m, array[b - 1]); this.rotate(array, i, m, b); - int t = m-i; + int t = m - i; m = i; - b -= t+1; + b -= t + 1; - if(m == a) break; + if (m == a) + break; - b = this.leftBinSearch(array, m, b, array[m-1]); + b = this.leftBinSearch(array, m, b, array[m - 1]); } } } diff --git a/src/main/java/io/github/arrayv/sorts/templates/BogoSorting.java b/src/main/java/io/github/arrayv/sorts/templates/BogoSorting.java index 12b53a74..682d33f9 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/BogoSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/BogoSorting.java @@ -50,6 +50,7 @@ public abstract class BogoSorting extends Sort { /** * Constructs a new instance of this sort. + * * @param arrayVisualizer the Array Visualizer instance */ protected BogoSorting(ArrayVisualizer arrayVisualizer) { @@ -58,6 +59,7 @@ protected BogoSorting(ArrayVisualizer arrayVisualizer) { /** * Gets the length of each delay, in milliseconds. + * * @return the length of delay */ public double getDelay() { @@ -66,6 +68,7 @@ public double getDelay() { /** * Sets the length of each delay, in milliseconds. + * * @param delay the length of delay */ public void setDelay(double delay) { @@ -76,7 +79,7 @@ public void setDelay(double delay) { * Returns a random {@code int} value in the range {@code [start, end)}. * * @param start the start of the range, inclusive - * @param end the end of the range, exclusive + * @param end the end of the range, exclusive * @return a random {@code int} value within the range */ protected static int randInt(int start, int end) { @@ -99,30 +102,31 @@ protected static boolean randBoolean() { * * @param array the array * @param start the start of the range, inclusive - * @param end the end of the range, exclusive - * @param aux whether the array is auxililary + * @param end the end of the range, exclusive + * @param aux whether the array is auxililary */ - protected void bogoSwap(int[] array, int start, int end, boolean aux){ + protected void bogoSwap(int[] array, int start, int end, boolean aux) { for (int i = start; i < end; ++i) Writes.swap(array, i, BogoSorting.randInt(i, end), this.delay, true, aux); } /** * Sets a random combination of {@code size} elements - * in the range {@code [start, end)} of {@code array} to {@code 1}, and the rest to {@code 0}. + * in the range {@code [start, end)} of {@code array} to {@code 1}, and the rest + * to {@code 0}. * * @param array the array * @param start the start of the range, inclusive - * @param end the end of the range, exclusive - * @param size the number of elements to set to 1 - * @param aux whether the array is auxililary + * @param end the end of the range, exclusive + * @param size the number of elements to set to 1 + * @param aux whether the array is auxililary */ protected void bogoCombo(int[] array, int start, int end, int size, boolean aux) { for (int i = start; i < end; ++i) Writes.write(array, i, 0, this.delay, true, aux); - for (int i = end-size; i < end; ++i) { - int j = BogoSorting.randInt(start, i+1); + for (int i = end - size; i < end; ++i) { + int j = BogoSorting.randInt(start, i + 1); Highlights.markArray(1, j); Delays.sleep(this.delay); Writes.write(array, Reads.compareValues(array[j], 0) == 0 ? j : i, 1, this.delay, true, aux); @@ -132,17 +136,18 @@ protected void bogoCombo(int[] array, int start, int end, int size, boolean aux) /** * Checks if the range {@code [start, end)} of {@code array} is sorted. * - * @param array the array - * @param start the start of the range, inclusive - * @param end the end of the range, exclusive - * @param mark whether to mark each comparison + * @param array the array + * @param start the start of the range, inclusive + * @param end the end of the range, exclusive + * @param mark whether to mark each comparison * @param markLast whether to mark the element that is not sorted * @return whether the range is sorted */ protected boolean isRangeSorted(int[] array, int start, int end, boolean mark, boolean markLast) { for (int i = start; i < end - 1; ++i) { if (Reads.compareIndices(array, i, i + 1, this.delay, mark) > 0) { - if (markLast) Highlights.markArray(3, i + 1); + if (markLast) + Highlights.markArray(3, i + 1); return false; } } @@ -152,14 +157,14 @@ protected boolean isRangeSorted(int[] array, int start, int end, boolean mark, b /** * Checks if the range {@code [start, end)} of {@code array} is sorted. *
    - *
  • {@code mark} defaults to {@code true}. - *
  • {@code markLast} defaults to {@code false}. + *
  • {@code mark} defaults to {@code true}. + *
  • {@code markLast} defaults to {@code false}. *
*
* * @param array the array * @param start the start of the range, inclusive - * @param end the end of the range, exclusive + * @param end the end of the range, exclusive * @return whether the range is sorted * * @see #isRangeSorted(int[], int, int, boolean, boolean) @@ -170,9 +175,10 @@ protected boolean isRangeSorted(int[] array, int start, int end) { /** * Checks if {@code array} is sorted. - * This can also be used to check if a prefix of length {@code length} of {@code array} is sorted. + * This can also be used to check if a prefix of length {@code length} of + * {@code array} is sorted. * - * @param array the array + * @param array the array * @param length the length of the array or prefix * @return whether the array or prefix is sorted */ @@ -181,15 +187,17 @@ protected boolean isArraySorted(int[] array, int length) { } /** - * Checks if the range {@code [start, end)} of {@code array} is partitioned around index {@code pivot}. + * Checks if the range {@code [start, end)} of {@code array} is partitioned + * around index {@code pivot}. *

- * Partitioned means that every element before {@code pivot} is no greater than the value of {@code pivot}, + * Partitioned means that every element before {@code pivot} is no + * greater than the value of {@code pivot}, * and every element after is no less. * * @param array the array * @param start the start of the range, inclusive * @param pivot the index of the pivot - * @param end the end of the range, exclusive + * @param end the end of the range, exclusive * @return whether the range is partitioned */ protected boolean isRangePartitioned(int[] array, int start, int pivot, int end) { @@ -205,11 +213,12 @@ protected boolean isRangePartitioned(int[] array, int start, int pivot, int end) } /** - * Checks if the first element in the range {@code [start, end)} of {@code array} is a minimum. + * Checks if the first element in the range {@code [start, end)} of + * {@code array} is a minimum. * * @param array the array * @param start the start of the range, inclusive - * @param end the end of the range, exclusive + * @param end the end of the range, exclusive * @return whether the first element is a minimum */ protected boolean isMinSorted(int[] array, int start, int end) { @@ -217,33 +226,36 @@ protected boolean isMinSorted(int[] array, int start, int end) { } /** - * Checks if the last element in the range {@code [start, end)} of {@code array} is a maximum. + * Checks if the last element in the range {@code [start, end)} of {@code array} + * is a maximum. * * @param array the array * @param start the start of the range, inclusive - * @param end the end of the range, exclusive + * @param end the end of the range, exclusive * @return whether the last element is a maximum */ protected boolean isMaxSorted(int[] array, int start, int end) { - return isRangePartitioned(array, start, end-1, end); + return isRangePartitioned(array, start, end - 1, end); } /** - * Checks if the elements in the range {@code [start, end)} of {@code array} are split by {@code mid}, + * Checks if the elements in the range {@code [start, end)} of {@code array} are + * split by {@code mid}, * where the {@code mid} itself belongs to the ending side of the array. *

- * Split means that all elements in range {@code [start, mid)} are no greater than those in range {@code [mid, end)}. + * Split means that all elements in range {@code [start, mid)} are no + * greater than those in range {@code [mid, end)}. * * @param array the array * @param start the start of the range, inclusive - * @param mid the index where range is split - * @param end the end of the range, exclusive + * @param mid the index where range is split + * @param end the end of the range, exclusive * @return whether the range is split */ protected boolean isRangeSplit(int[] array, int start, int mid, int end) { Highlights.markArray(1, start); int lowMax = array[start]; - for (int i = start+1; i < mid; ++i) { + for (int i = start + 1; i < mid; ++i) { Highlights.markArray(1, i); Delays.sleep(this.delay); if (Reads.compareValues(lowMax, array[i]) < 0) diff --git a/src/main/java/io/github/arrayv/sorts/templates/CircleSorting.java b/src/main/java/io/github/arrayv/sorts/templates/CircleSorting.java index 61d73383..1be547b1 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/CircleSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/CircleSorting.java @@ -40,7 +40,7 @@ protected int circleSortRoutine(int[] array, int lo, int hi, int swapCount, doub } swapCount = this.circleSortRoutine(array, low, low + mid, swapCount, sleep); - if(low + mid + 1 < this.end) + if (low + mid + 1 < this.end) swapCount = this.circleSortRoutine(array, low + mid + 1, high, swapCount, sleep); return swapCount; diff --git a/src/main/java/io/github/arrayv/sorts/templates/CombSorting.java b/src/main/java/io/github/arrayv/sorts/templates/CombSorting.java index 3debbaaf..05a5ee09 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/CombSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/CombSorting.java @@ -41,34 +41,27 @@ protected void combSort(int[] array, int length, double shrink, boolean hybrid) boolean swapped = false; int gap = length; - while ((gap > 1) || swapped) - { + while ((gap > 1) || swapped) { Highlights.clearMark(2); if (gap > 1) { gap = (int) (gap / shrink); - //ArrayVisualizer.setCurrentGap(gap); + // ArrayVisualizer.setCurrentGap(gap); } swapped = false; - for (int i = 0; (gap + i) < length; ++i) - { - if(hybrid && (gap <= Math.min(8, length * 0.03125))) { + for (int i = 0; (gap + i) < length; ++i) { + if (hybrid && (gap <= Math.min(8, length * 0.03125))) { gap = 0; insertSorter.customInsertSort(array, 0, length, 0.5, false); break; } - if (Reads.compareValues(array[i], array[i + gap]) == 1) - { - Writes.swap(array, i, i+gap, 0.75, true, false); + if (Reads.compareIndices(array, i, i + gap, 0.25, true) == 1) { + Writes.swap(array, i, i + gap, 0.75, true, false); swapped = true; } - Highlights.markArray(1, i); - Highlights.markArray(2, i + gap); - - Delays.sleep(0.25); Highlights.clearMark(1); } } diff --git a/src/main/java/io/github/arrayv/sorts/templates/GrailSorting.java b/src/main/java/io/github/arrayv/sorts/templates/GrailSorting.java index b0e1e805..84ea31c7 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/GrailSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/GrailSorting.java @@ -68,7 +68,8 @@ protected int getLeftOverFrag() { public abstract class GrailSorting extends Sort { private OptimizedGnomeSort grailInsertSorter; - final private int grailStaticBufferLen = 32; //Buffer length changed due to less numbers in this program being sorted than what Mr. Astrelin used for testing. + final private int grailStaticBufferLen = 32; // Buffer length changed due to less numbers in this program being + // sorted than what Mr. Astrelin used for testing. protected GrailSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -83,20 +84,19 @@ private void grailSwap(int[] arr, int a, int b) { } private void grailMultiSwap(int[] arr, int a, int b, int swapsLeft) { - while(swapsLeft != 0) { + while (swapsLeft != 0) { this.grailSwap(arr, a++, b++); swapsLeft--; } } protected void grailRotate(int[] array, int pos, int lenA, int lenB) { - while(lenA != 0 && lenB != 0) { - if(lenA <= lenB) { + while (lenA != 0 && lenB != 0) { + if (lenA <= lenB) { this.grailMultiSwap(array, pos, pos + lenA, lenA); pos += lenA; lenB -= lenA; - } - else { + } else { this.grailMultiSwap(array, pos + (lenA - lenB), pos + lenA, lenB); lenA -= lenB; } @@ -107,21 +107,22 @@ private void grailInsertSort(int[] arr, int pos, int len) { grailInsertSorter.customSort(arr, pos, pos + len, 0.75); } - //boolean argument determines direction + // boolean argument determines direction private int grailBinSearch(int[] arr, int pos, int len, int keyPos, boolean isLeft) { int left = -1, right = len; - while(left < right - 1) { + while (left < right - 1) { int mid = left + ((right - left) >> 1); - if(isLeft) { - if(Reads.compareValues(arr[pos + mid], arr[keyPos]) >= 0) { + if (isLeft) { + if (Reads.compareValues(arr[pos + mid], arr[keyPos]) >= 0) { right = mid; } else { left = mid; } } else { - if(Reads.compareValues(arr[pos + mid], arr[keyPos]) > 0) { + if (Reads.compareValues(arr[pos + mid], arr[keyPos]) > 0) { right = mid; - } else left = mid; + } else + left = mid; } Highlights.markArray(1, pos + mid); } @@ -130,21 +131,21 @@ private int grailBinSearch(int[] arr, int pos, int len, int keyPos, boolean isLe // cost: 2 * len + numKeys^2 / 2 private int grailFindKeys(int[] arr, int pos, int len, int numKeys) { - int dist = 1, foundKeys = 1, firstKey = 0; // first key is always here + int dist = 1, foundKeys = 1, firstKey = 0; // first key is always here - while(dist < len && foundKeys < numKeys) { - if(dist < (len - 1)) Highlights.markArray(3, dist + 1); + while (dist < len && foundKeys < numKeys) { + if (dist < (len - 1)) + Highlights.markArray(3, dist + 1); Delays.sleep(1); - //Binary Search left + // Binary Search left int loc = this.grailBinSearch(arr, pos + firstKey, foundKeys, pos + dist, true); - if(loc == foundKeys || Reads.compareValues(arr[pos + dist], arr[pos + (firstKey + loc)]) != 0) { + if (loc == foundKeys || Reads.compareValues(arr[pos + dist], arr[pos + (firstKey + loc)]) != 0) { this.grailRotate(arr, pos + firstKey, foundKeys, dist - (firstKey + foundKeys)); firstKey = dist - foundKeys; this.grailRotate(arr, pos + (firstKey + loc), foundKeys - loc, 1); foundKeys++; - } - else { + } else { Highlights.clearMark(2); } @@ -160,51 +161,59 @@ private int grailFindKeys(int[] arr, int pos, int len, int numKeys) { // cost: min(len1, len2)^2 + max(len1, len2) protected void grailMergeWithoutBuffer(int[] arr, int pos, int len1, int len2) { - if(len1 < len2) { - while(len1 != 0) { - //Binary Search left + if (len1 < len2) { + while (len1 != 0) { + // Binary Search left int loc = this.grailBinSearch(arr, pos + len1, len2, pos, true); - if(loc != 0) { + if (loc != 0) { this.grailRotate(arr, pos, len1, loc); pos += loc; len2 -= loc; } - if(len2 == 0) break; + if (len2 == 0) + break; do { pos++; len1--; - } while(len1 != 0 && Reads.compareValues(arr[pos], arr[pos + len1]) <= 0); + } while (len1 != 0 && Reads.compareValues(arr[pos], arr[pos + len1]) <= 0); } } else { - while(len2 != 0) { - //Binary Search right + while (len2 != 0) { + // Binary Search right int loc = this.grailBinSearch(arr, pos, len1, pos + (len1 + len2 - 1), false); - if(loc != len1) { + if (loc != len1) { this.grailRotate(arr, pos + loc, len1 - loc, len2); len1 = loc; } - if(len1 == 0) break; + if (len1 == 0) + break; do { len2--; - } while(len2 != 0 && Reads.compareValues(arr[pos + len1 - 1], arr[pos + len1 + len2 - 1]) <= 0); + } while (len2 != 0 && Reads.compareValues(arr[pos + len1 - 1], arr[pos + len1 + len2 - 1]) <= 0); } } } // arr - starting array. arr[0 - regBlockLen..-1] - buffer (if havebuf). - // regBlockLen - length of regular blocks. First blockCount blocks are stable sorted by 1st elements and key-coded - // keysPos - arrays of keys, in same order as blocks. keysPos < midkey means stream A + // regBlockLen - length of regular blocks. First blockCount blocks are stable + // sorted by 1st elements and key-coded + // keysPos - arrays of keys, in same order as blocks. keysPos < midkey means + // stream A // aBlockCount are regular blocks from stream A. - // lastLen is length of last (irregular) block from stream B, that should go before nblock2 blocks. - // lastLen = 0 requires aBlockCount = 0 (no irregular blocks). lastLen > 0, aBlockCount = 0 is possible. + // lastLen is length of last (irregular) block from stream B, that should go + // before nblock2 blocks. + // lastLen = 0 requires aBlockCount = 0 (no irregular blocks). lastLen > 0, + // aBlockCount = 0 is possible. private void grailMergeBuffersLeft(int[] arr, int keysPos, int midkey, int pos, int blockCount, int blockLen, boolean havebuf, int aBlockCount, int lastLen) { - if(blockCount == 0) { + if (blockCount == 0) { int aBlocksLen = aBlockCount * blockLen; - if(havebuf) this.grailMergeLeft(arr, pos, aBlocksLen, lastLen, 0 - blockLen); - else this.grailMergeWithoutBuffer(arr, pos, aBlocksLen, lastLen); + if (havebuf) + this.grailMergeLeft(arr, pos, aBlocksLen, lastLen, 0 - blockLen); + else + this.grailMergeWithoutBuffer(arr, pos, aBlocksLen, lastLen); return; } @@ -213,21 +222,24 @@ private void grailMergeBuffersLeft(int[] arr, int keysPos, int midkey, int pos, int processIndex = blockLen; int restToProcess; - for(int keyIndex = 1; keyIndex < blockCount; keyIndex++, processIndex += blockLen) { + for (int keyIndex = 1; keyIndex < blockCount; keyIndex++, processIndex += blockLen) { restToProcess = processIndex - leftOverLen; int nextFrag = Reads.compareValues(arr[keysPos + keyIndex], arr[midkey]) < 0 ? 0 : 1; - if(nextFrag == leftOverFrag) { - if(havebuf) this.grailMultiSwap(arr, pos + restToProcess - blockLen, pos + restToProcess, leftOverLen); + if (nextFrag == leftOverFrag) { + if (havebuf) + this.grailMultiSwap(arr, pos + restToProcess - blockLen, pos + restToProcess, leftOverLen); restToProcess = processIndex; leftOverLen = blockLen; } else { - if(havebuf) { - GrailPair results = this.grailSmartMergeWithBuffer(arr, pos + restToProcess, leftOverLen, leftOverFrag, blockLen); + if (havebuf) { + GrailPair results = this.grailSmartMergeWithBuffer(arr, pos + restToProcess, leftOverLen, + leftOverFrag, blockLen); leftOverLen = results.getLeftOverLen(); leftOverFrag = results.getLeftOverFrag(); } else { - GrailPair results = this.grailSmartMergeWithoutBuffer(arr, pos + restToProcess, leftOverLen, leftOverFrag, blockLen); + GrailPair results = this.grailSmartMergeWithoutBuffer(arr, pos + restToProcess, leftOverLen, + leftOverFrag, blockLen); leftOverLen = results.getLeftOverLen(); leftOverFrag = results.getLeftOverFrag(); } @@ -235,9 +247,9 @@ private void grailMergeBuffersLeft(int[] arr, int keysPos, int midkey, int pos, } restToProcess = processIndex - leftOverLen; - if(lastLen != 0) { - if(leftOverFrag != 0) { - if(havebuf) { + if (lastLen != 0) { + if (leftOverFrag != 0) { + if (havebuf) { this.grailMultiSwap(arr, pos + restToProcess - blockLen, pos + restToProcess, leftOverLen); } restToProcess = processIndex; @@ -246,20 +258,20 @@ private void grailMergeBuffersLeft(int[] arr, int keysPos, int midkey, int pos, } else { leftOverLen += blockLen * aBlockCount; } - if(havebuf) { + if (havebuf) { this.grailMergeLeft(arr, pos + restToProcess, leftOverLen, lastLen, -blockLen); - } - else { + } else { this.grailMergeWithoutBuffer(arr, pos + restToProcess, leftOverLen, lastLen); } } else { - if(havebuf) { + if (havebuf) { this.grailMultiSwap(arr, pos + restToProcess, pos + (restToProcess - blockLen), leftOverLen); } } } - // arr[dist..-1] - buffer, arr[0, leftLen - 1] ++ arr[leftLen, leftLen + rightLen - 1] + // arr[dist..-1] - buffer, arr[0, leftLen - 1] ++ arr[leftLen, leftLen + + // rightLen - 1] // -> arr[dist, dist + leftLen + rightLen - 1] private void grailMergeLeft(int[] arr, int pos, int leftLen, int rightLen, int dist) { int left = 0; @@ -267,86 +279,92 @@ private void grailMergeLeft(int[] arr, int pos, int leftLen, int rightLen, int d rightLen += leftLen; - while(right < rightLen) { - if(left == leftLen || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { + while (right < rightLen) { + if (left == leftLen || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { this.grailSwap(arr, pos + (dist++), pos + (right++)); - } - else this.grailSwap(arr, pos + (dist++), pos + (left++)); + } else + this.grailSwap(arr, pos + (dist++), pos + (left++)); Highlights.markArray(3, pos + left); Highlights.markArray(4, pos + right); } Highlights.clearMark(3); Highlights.clearMark(4); - if(dist != left) this.grailMultiSwap(arr, pos + dist, pos + left, leftLen - left); + if (dist != left) + this.grailMultiSwap(arr, pos + dist, pos + left, leftLen - left); } + private void grailMergeRight(int[] arr, int pos, int leftLen, int rightLen, int dist) { int mergedPos = leftLen + rightLen + dist - 1; int right = leftLen + rightLen - 1; int left = leftLen - 1; - while(left >= 0) { - if(right < leftLen || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { + while (left >= 0) { + if (right < leftLen || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { this.grailSwap(arr, pos + (mergedPos--), pos + (left--)); - } - else this.grailSwap(arr, pos + (mergedPos--), pos + (right--)); - if(pos + left >= 0) Highlights.markArray(3, pos + left); + } else + this.grailSwap(arr, pos + (mergedPos--), pos + (right--)); + if (pos + left >= 0) + Highlights.markArray(3, pos + left); Highlights.markArray(4, pos + right); } Highlights.clearMark(3); Highlights.clearMark(4); - if(right != mergedPos) { - while(right >= leftLen) this.grailSwap(arr, pos + (mergedPos--), pos + (right--)); + if (right != mergedPos) { + while (right >= leftLen) + this.grailSwap(arr, pos + (mergedPos--), pos + (right--)); } } - //returns the leftover length, then the leftover fragment - private GrailPair grailSmartMergeWithoutBuffer(int[] arr, int pos, int leftOverLen, int leftOverFrag, int regBlockLen) { - if(regBlockLen == 0) return new GrailPair(leftOverLen, leftOverFrag); + // returns the leftover length, then the leftover fragment + private GrailPair grailSmartMergeWithoutBuffer(int[] arr, int pos, int leftOverLen, int leftOverFrag, + int regBlockLen) { + if (regBlockLen == 0) + return new GrailPair(leftOverLen, leftOverFrag); int len1 = leftOverLen; int len2 = regBlockLen; - int typeFrag = 1 - leftOverFrag; //1 if inverted + int typeFrag = 1 - leftOverFrag; // 1 if inverted - if(len1 != 0 && Reads.compareValues(arr[pos + (len1 - 1)], arr[pos + len1]) - typeFrag >= 0) { + if (len1 != 0 && Reads.compareValues(arr[pos + (len1 - 1)], arr[pos + len1]) - typeFrag >= 0) { - while(len1 != 0) { + while (len1 != 0) { int foundLen; if (typeFrag != 0) { - //Binary Search left + // Binary Search left foundLen = this.grailBinSearch(arr, pos + len1, len2, pos, true); } else { - //Binary Search right + // Binary Search right foundLen = this.grailBinSearch(arr, pos + len1, len2, pos, false); } - if(foundLen != 0) { + if (foundLen != 0) { this.grailRotate(arr, pos, len1, foundLen); pos += foundLen; len2 -= foundLen; } - if(len2 == 0) { + if (len2 == 0) { return new GrailPair(len1, leftOverFrag); } do { pos++; len1--; - } while(len1 != 0 && Reads.compareValues(arr[pos], arr[pos + len1]) - typeFrag < 0); + } while (len1 != 0 && Reads.compareValues(arr[pos], arr[pos + len1]) - typeFrag < 0); } } return new GrailPair(len2, typeFrag); } - //returns the leftover length, then the leftover fragment + // returns the leftover length, then the leftover fragment private GrailPair grailSmartMergeWithBuffer(int[] arr, int pos, int leftOverLen, int leftOverFrag, int blockLen) { int dist = 0 - blockLen, left = 0, right = leftOverLen, leftEnd = right, rightEnd = right + blockLen; - int typeFrag = 1 - leftOverFrag; // 1 if inverted + int typeFrag = 1 - leftOverFrag; // 1 if inverted - while(left < leftEnd && right < rightEnd) { - if(Reads.compareValues(arr[pos + left], arr[pos + right]) - typeFrag < 0) { + while (left < leftEnd && right < rightEnd) { + if (Reads.compareValues(arr[pos + left], arr[pos + right]) - typeFrag < 0) { this.grailSwap(arr, pos + (dist++), pos + (left++)); - } - else this.grailSwap(arr, pos + (dist++), pos + (right++)); + } else + this.grailSwap(arr, pos + (dist++), pos + (right++)); Highlights.markArray(3, pos + left); Highlights.markArray(4, pos + right); } @@ -354,9 +372,10 @@ private GrailPair grailSmartMergeWithBuffer(int[] arr, int pos, int leftOverLen, Highlights.clearMark(4); int length, fragment = leftOverFrag; - if(left < leftEnd) { + if (left < leftEnd) { length = leftEnd - left; - while(left < leftEnd) this.grailSwap(arr, pos + (--leftEnd), pos + (--rightEnd)); + while (left < leftEnd) + this.grailSwap(arr, pos + (--leftEnd), pos + (--rightEnd)); } else { length = rightEnd - right; fragment = typeFrag; @@ -364,21 +383,20 @@ private GrailPair grailSmartMergeWithBuffer(int[] arr, int pos, int leftOverLen, return new GrailPair(length, fragment); } - /***** Sort With Extra Buffer *****/ - //returns the leftover length, then the leftover fragment + // returns the leftover length, then the leftover fragment private GrailPair grailSmartMergeWithXBuf(int[] arr, int pos, int leftOverLen, int leftOverFrag, int blockLen) { int dist = 0 - blockLen, left = 0, right = leftOverLen, leftEnd = right, rightEnd = right + blockLen; - int typeFrag = 1 - leftOverFrag; // 1 if inverted + int typeFrag = 1 - leftOverFrag; // 1 if inverted Highlights.clearMark(2); - while(left < leftEnd && right < rightEnd) { - if(Reads.compareValues(arr[pos + left], arr[pos + right]) - typeFrag < 0) { + while (left < leftEnd && right < rightEnd) { + if (Reads.compareValues(arr[pos + left], arr[pos + right]) - typeFrag < 0) { Writes.write(arr, pos + dist++, arr[pos + left++], 1, true, false); - } - else Writes.write(arr, pos + dist++, arr[pos + right++], 1, true, false); + } else + Writes.write(arr, pos + dist++, arr[pos + right++], 1, true, false); Highlights.markArray(2, pos + left); Highlights.markArray(3, pos + right); } @@ -386,9 +404,10 @@ private GrailPair grailSmartMergeWithXBuf(int[] arr, int pos, int leftOverLen, i Highlights.clearMark(3); int length, fragment = leftOverFrag; - if(left < leftEnd) { + if (left < leftEnd) { length = leftEnd - left; - while(left < leftEnd) Writes.write(arr, pos + --rightEnd, arr[pos + --leftEnd], 1, true, false); + while (left < leftEnd) + Writes.write(arr, pos + --rightEnd, arr[pos + --leftEnd], 1, true, false); } else { length = rightEnd - right; fragment = typeFrag; @@ -396,7 +415,8 @@ private GrailPair grailSmartMergeWithXBuf(int[] arr, int pos, int leftOverLen, i return new GrailPair(length, fragment); } - // arr[dist..-1] - free, arr[0, leftEnd - 1] ++ arr[leftEnd, leftEnd + rightEnd - 1] + // arr[dist..-1] - free, arr[0, leftEnd - 1] ++ arr[leftEnd, leftEnd + rightEnd + // - 1] // -> arr[dist, dist + leftEnd + rightEnd - 1] private void grailMergeLeftWithXBuf(int[] arr, int pos, int leftEnd, int rightEnd, int dist) { int left = 0; @@ -405,34 +425,39 @@ private void grailMergeLeftWithXBuf(int[] arr, int pos, int leftEnd, int rightEn Highlights.clearMark(2); - while(right < rightEnd) { - if(left == leftEnd || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { + while (right < rightEnd) { + if (left == leftEnd || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { Writes.write(arr, pos + dist++, arr[pos + right++], 1, true, false); - } - else Writes.write(arr, pos + dist++, arr[pos + left++], 1, true, false); + } else + Writes.write(arr, pos + dist++, arr[pos + left++], 1, true, false); Highlights.markArray(2, pos + left); Highlights.markArray(3, pos + right); } Highlights.clearMark(2); Highlights.clearMark(3); - if(dist != left) { - while(left < leftEnd) Writes.write(arr, pos + dist++, arr[pos + left++], 1, true, false); + if (dist != left) { + while (left < leftEnd) + Writes.write(arr, pos + dist++, arr[pos + left++], 1, true, false); } } // arr - starting array. arr[0 - regBlockLen..-1] - buffer (if havebuf). - // regBlockLen - length of regular blocks. First blockCount blocks are stable sorted by 1st elements and key-coded - // keysPos - where keys are in array, in same order as blocks. keysPos < midkey means stream A + // regBlockLen - length of regular blocks. First blockCount blocks are stable + // sorted by 1st elements and key-coded + // keysPos - where keys are in array, in same order as blocks. keysPos < midkey + // means stream A // aBlockCount are regular blocks from stream A. - // lastLen is length of last (irregular) block from stream B, that should go before aCountBlock blocks. - // lastLen = 0 requires aBlockCount = 0 (no irregular blocks). lastLen > 0, aBlockCount = 0 is possible. + // lastLen is length of last (irregular) block from stream B, that should go + // before aCountBlock blocks. + // lastLen = 0 requires aBlockCount = 0 (no irregular blocks). lastLen > 0, + // aBlockCount = 0 is possible. private void grailMergeBuffersLeftWithXBuf(int[] arr, int keysPos, int midkey, int pos, int blockCount, int regBlockLen, int aBlockCount, int lastLen) { Highlights.clearMark(2); - if(blockCount == 0) { + if (blockCount == 0) { int aBlocksLen = aBlockCount * regBlockLen; this.grailMergeLeftWithXBuf(arr, pos, aBlocksLen, lastLen, 0 - regBlockLen); return; @@ -443,26 +468,29 @@ private void grailMergeBuffersLeftWithXBuf(int[] arr, int keysPos, int midkey, i int processIndex = regBlockLen; int restToProcess; - for(int keyIndex = 1; keyIndex < blockCount; keyIndex++, processIndex += regBlockLen) { + for (int keyIndex = 1; keyIndex < blockCount; keyIndex++, processIndex += regBlockLen) { restToProcess = processIndex - leftOverLen; int nextFrag = Reads.compareValues(arr[keysPos + keyIndex], arr[midkey]) < 0 ? 0 : 1; - if(nextFrag == leftOverFrag) { - Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, false); + if (nextFrag == leftOverFrag) { + Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, + false); restToProcess = processIndex; leftOverLen = regBlockLen; } else { - GrailPair results = this.grailSmartMergeWithXBuf(arr, pos + restToProcess, leftOverLen, leftOverFrag, regBlockLen); + GrailPair results = this.grailSmartMergeWithXBuf(arr, pos + restToProcess, leftOverLen, leftOverFrag, + regBlockLen); leftOverLen = results.getLeftOverLen(); leftOverFrag = results.getLeftOverFrag(); } } restToProcess = processIndex - leftOverLen; - if(lastLen != 0) { - if(leftOverFrag != 0) { - Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, false); + if (lastLen != 0) { + if (leftOverFrag != 0) { + Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, + false); restToProcess = processIndex; leftOverLen = regBlockLen * aBlockCount; @@ -472,7 +500,8 @@ private void grailMergeBuffersLeftWithXBuf(int[] arr, int keysPos, int midkey, i } this.grailMergeLeftWithXBuf(arr, pos + restToProcess, leftOverLen, lastLen, 0 - regBlockLen); } else { - Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, false); + Writes.arraycopy(arr, pos + restToProcess, arr, pos + restToProcess - regBlockLen, leftOverLen, 1, true, + false); } } @@ -480,65 +509,71 @@ private void grailMergeBuffersLeftWithXBuf(int[] arr, int keysPos, int midkey, i // build blocks of length buildLen // input: [-buildLen, -1] elements are buffer - // output: first buildLen elements are buffer, blocks 2 * buildLen and last subblock sorted + // output: first buildLen elements are buffer, blocks 2 * buildLen and last + // subblock sorted private void grailBuildBlocks(int[] arr, int pos, int len, int buildLen, int[] extbuf, int bufferPos, int extBufLen) { int buildBuf = buildLen < extBufLen ? buildLen : extBufLen; - while((buildBuf & (buildBuf - 1)) != 0) buildBuf &= buildBuf - 1; // max power or 2 - just in case + while ((buildBuf & (buildBuf - 1)) != 0) + buildBuf &= buildBuf - 1; // max power or 2 - just in case int extraDist, part; - if(buildBuf != 0) { + if (buildBuf != 0) { Writes.arraycopy(arr, pos - buildBuf, extbuf, bufferPos, buildBuf, 1, true, true); - for(int dist = 1; dist < len; dist += 2) { + for (int dist = 1; dist < len; dist += 2) { extraDist = 0; - if(Reads.compareValues(arr[pos + (dist - 1)], arr[pos + dist]) > 0) extraDist = 1; + if (Reads.compareValues(arr[pos + (dist - 1)], arr[pos + dist]) > 0) + extraDist = 1; Writes.write(arr, pos + dist - 3, arr[pos + dist - 1 + extraDist], 1, true, false); Writes.write(arr, pos + dist - 2, arr[pos + dist - extraDist], 1, true, false); } - if(len % 2 != 0) Writes.write(arr, pos + len - 3, arr[pos + len - 1], 1, true, false); + if (len % 2 != 0) + Writes.write(arr, pos + len - 3, arr[pos + len - 1], 1, true, false); pos -= 2; - for(part = 2; part < buildBuf; part *= 2) { + for (part = 2; part < buildBuf; part *= 2) { int left = 0; int right = len - 2 * part; - while(left <= right) { + while (left <= right) { this.grailMergeLeftWithXBuf(arr, pos + left, part, part, 0 - part); left += 2 * part; } int rest = len - left; - if(rest > part) { + if (rest > part) { this.grailMergeLeftWithXBuf(arr, pos + left, part, rest - part, 0 - part); } else { - for(; left < len; left++) Writes.write(arr, pos + left - part, arr[pos + left], 1, true, false); + for (; left < len; left++) + Writes.write(arr, pos + left - part, arr[pos + left], 1, true, false); } pos -= part; } Writes.arraycopy(extbuf, bufferPos, arr, pos + len, buildBuf, 1, true, false); - } - else { - for(int dist = 1; dist < len; dist += 2) { + } else { + for (int dist = 1; dist < len; dist += 2) { extraDist = 0; - if(Reads.compareValues(arr[pos + (dist - 1)], arr[pos + dist]) > 0) extraDist = 1; + if (Reads.compareValues(arr[pos + (dist - 1)], arr[pos + dist]) > 0) + extraDist = 1; this.grailSwap(arr, pos + (dist - 3), pos + (dist - 1 + extraDist)); this.grailSwap(arr, pos + (dist - 2), pos + (dist - extraDist)); } - if(len % 2 != 0) this.grailSwap(arr, pos + (len - 1), pos + (len - 3)); + if (len % 2 != 0) + this.grailSwap(arr, pos + (len - 1), pos + (len - 3)); pos -= 2; part = 2; } - for(; part < buildLen; part *= 2) { + for (; part < buildLen; part *= 2) { int left = 0; int right = len - 2 * part; - while(left <= right) { + while (left <= right) { this.grailMergeLeft(arr, pos + left, part, part, 0 - part); left += 2 * part; } int rest = len - left; - if(rest > part) { + if (rest > part) { this.grailMergeLeft(arr, pos + left, part, rest - part, 0 - part); } else { this.grailRotate(arr, pos + left - part, part, rest); @@ -548,31 +583,37 @@ private void grailBuildBlocks(int[] arr, int pos, int len, int buildLen, int restToBuild = len % (2 * buildLen); int leftOverPos = len - restToBuild; - if(restToBuild <= buildLen) this.grailRotate(arr, pos + leftOverPos, restToBuild, buildLen); - else this.grailMergeRight(arr, pos + leftOverPos, buildLen, restToBuild - buildLen, buildLen); + if (restToBuild <= buildLen) + this.grailRotate(arr, pos + leftOverPos, restToBuild, buildLen); + else + this.grailMergeRight(arr, pos + leftOverPos, buildLen, restToBuild - buildLen, buildLen); - while(leftOverPos > 0) { + while (leftOverPos > 0) { leftOverPos -= 2 * buildLen; this.grailMergeRight(arr, pos + leftOverPos, buildLen, buildLen, buildLen); } } - // keys are on the left of arr. Blocks of length buildLen combined. We'll combine them in pairs - // buildLen and nkeys are powers of 2. (2 * buildLen / regBlockLen) keys are guaranteed + // keys are on the left of arr. Blocks of length buildLen combined. We'll + // combine them in pairs + // buildLen and nkeys are powers of 2. (2 * buildLen / regBlockLen) keys are + // guaranteed private void grailCombineBlocks(int[] arr, int keyPos, int pos, int len, int buildLen, int regBlockLen, boolean havebuf, int[] buffer, int bufferPos) { int combineLen = len / (2 * buildLen); int leftOver = len % (2 * buildLen); - if(leftOver <= buildLen) { + if (leftOver <= buildLen) { len -= leftOver; leftOver = 0; } - if(buffer != null) Writes.arraycopy(arr, pos - regBlockLen, buffer, bufferPos, regBlockLen, 1, true, true); + if (buffer != null) + Writes.arraycopy(arr, pos - regBlockLen, buffer, bufferPos, regBlockLen, 1, true, true); - for(int i = 0; i <= combineLen; i++) { - if(i == combineLen && leftOver == 0) break; + for (int i = 0; i <= combineLen; i++) { + if (i == combineLen && leftOver == 0) + break; int blockPos = pos + i * 2 * buildLen; int blockCount = (i == combineLen ? leftOver : 2 * buildLen) / regBlockLen; @@ -581,20 +622,22 @@ private void grailCombineBlocks(int[] arr, int keyPos, int pos, int len, int bui int midkey = buildLen / regBlockLen; - for(int index = 1; index < blockCount; index++) { + for (int index = 1; index < blockCount; index++) { int leftIndex = index - 1; - for(int rightIndex = index; rightIndex < blockCount; rightIndex++) { - int rightComp = Reads.compareValues(arr[blockPos + leftIndex * regBlockLen], - arr[blockPos + rightIndex * regBlockLen]); - if(rightComp > 0 || (rightComp == 0 && Reads.compareValues(arr[keyPos + leftIndex], arr[keyPos + rightIndex]) > 0)) { + for (int rightIndex = index; rightIndex < blockCount; rightIndex++) { + int rightComp = Reads.compareValues(arr[blockPos + leftIndex * regBlockLen], + arr[blockPos + rightIndex * regBlockLen]); + if (rightComp > 0 || (rightComp == 0 + && Reads.compareValues(arr[keyPos + leftIndex], arr[keyPos + rightIndex]) > 0)) { leftIndex = rightIndex; } } - if(leftIndex != index - 1) { - this.grailMultiSwap(arr, blockPos + (index - 1) * regBlockLen, blockPos + leftIndex * regBlockLen, regBlockLen); + if (leftIndex != index - 1) { + this.grailMultiSwap(arr, blockPos + (index - 1) * regBlockLen, blockPos + leftIndex * regBlockLen, + regBlockLen); this.grailSwap(arr, keyPos + (index - 1), keyPos + leftIndex); - if(midkey == index - 1 || midkey == leftIndex) { + if (midkey == index - 1 || midkey == leftIndex) { midkey ^= (index - 1) ^ leftIndex; } } @@ -602,36 +645,37 @@ private void grailCombineBlocks(int[] arr, int keyPos, int pos, int len, int bui int aBlockCount = 0; int lastLen = 0; - if(i == combineLen) lastLen = leftOver % regBlockLen; + if (i == combineLen) + lastLen = leftOver % regBlockLen; - if(lastLen != 0) { - while(aBlockCount < blockCount && Reads.compareValues(arr[blockPos + blockCount * regBlockLen], - arr[blockPos + (blockCount - aBlockCount - 1) * regBlockLen]) < 0) { + if (lastLen != 0) { + while (aBlockCount < blockCount && Reads.compareValues(arr[blockPos + blockCount * regBlockLen], + arr[blockPos + (blockCount - aBlockCount - 1) * regBlockLen]) < 0) { aBlockCount++; } } - if(buffer != null) { + if (buffer != null) { this.grailMergeBuffersLeftWithXBuf(arr, keyPos, keyPos + midkey, blockPos, blockCount - aBlockCount, regBlockLen, aBlockCount, lastLen); - } - else this.grailMergeBuffersLeft(arr, keyPos, keyPos + midkey, blockPos, - blockCount - aBlockCount, regBlockLen, havebuf, aBlockCount, lastLen); + } else + this.grailMergeBuffersLeft(arr, keyPos, keyPos + midkey, blockPos, + blockCount - aBlockCount, regBlockLen, havebuf, aBlockCount, lastLen); } - if(buffer != null) { - for(int i = len; --i >= 0;) Writes.write(arr, pos + i, arr[pos + i - regBlockLen], 1, true, false); + if (buffer != null) { + for (int i = len; --i >= 0;) + Writes.write(arr, pos + i, arr[pos + i - regBlockLen], 1, true, false); Writes.arraycopy(buffer, bufferPos, arr, pos - regBlockLen, regBlockLen, 1, true, false); - } - else if(havebuf) { - while(--len >= 0) { + } else if (havebuf) { + while (--len >= 0) { this.grailSwap(arr, pos + len, pos + len - regBlockLen); } } } protected void grailLazyStableSort(int[] arr, int pos, int len) { - for(int dist = 1; dist < len; dist += 2) { - if(Reads.compareValues(arr[pos + dist - 1], arr[pos + dist]) > 0) { + for (int dist = 1; dist < len; dist += 2) { + if (Reads.compareValues(arr[pos + dist - 1], arr[pos + dist]) > 0) { this.grailSwap(arr, pos + (dist - 1), pos + dist); } Highlights.markArray(3, pos + dist - 1); @@ -640,17 +684,17 @@ protected void grailLazyStableSort(int[] arr, int pos, int len) { Highlights.clearMark(3); Highlights.clearMark(4); - for(int part = 2; part < len; part *= 2) { + for (int part = 2; part < len; part *= 2) { int left = 0; int right = len - 2 * part; - while(left <= right) { + while (left <= right) { this.grailMergeWithoutBuffer(arr, pos + left, part, part); left += 2 * part; } int rest = len - left; - if(rest > part) { + if (rest > part) { this.grailMergeWithoutBuffer(arr, pos + left, part, rest - part); } } @@ -659,13 +703,14 @@ protected void grailLazyStableSort(int[] arr, int pos, int len) { protected void grailCommonSort(int[] arr, int pos, int len, int[] buffer, int bufferPos, int bufferLen) { this.grailInsertSorter = new OptimizedGnomeSort(this.arrayVisualizer); - if(len <= 16) { + if (len <= 16) { this.grailInsertSort(arr, pos, len); return; } int blockLen = 1; - while(blockLen * blockLen < len) blockLen *= 2; + while (blockLen * blockLen < len) + blockLen *= 2; int numKeys = (len - 1) / blockLen + 1; @@ -673,13 +718,14 @@ protected void grailCommonSort(int[] arr, int pos, int len, int[] buffer, int bu boolean bufferEnabled = true; - if(keysFound < numKeys + blockLen) { - if(keysFound < 4) { + if (keysFound < numKeys + blockLen) { + if (keysFound < 4) { this.grailLazyStableSort(arr, pos, len); return; } numKeys = blockLen; - while(numKeys > keysFound) numKeys /= 2; + while (numKeys > keysFound) + numKeys /= 2; bufferEnabled = false; blockLen = 0; } @@ -687,26 +733,25 @@ protected void grailCommonSort(int[] arr, int pos, int len, int[] buffer, int bu int dist = blockLen + numKeys; int buildLen = bufferEnabled ? blockLen : numKeys; - if(bufferEnabled) { + if (bufferEnabled) { this.grailBuildBlocks(arr, pos + dist, len - dist, buildLen, buffer, bufferPos, bufferLen); - } - else { + } else { this.grailBuildBlocks(arr, pos + dist, len - dist, buildLen, null, bufferPos, 0); } // 2 * buildLen are built - while(len - dist > (buildLen *= 2)) { + while (len - dist > (buildLen *= 2)) { int regBlockLen = blockLen; boolean buildBufEnabled = bufferEnabled; - if(!bufferEnabled) { - if(numKeys > 4 && numKeys / 8 * numKeys >= buildLen) { + if (!bufferEnabled) { + if (numKeys > 4 && numKeys / 8 * numKeys >= buildLen) { regBlockLen = numKeys / 2; buildBufEnabled = true; } else { int calcKeys = 1; int i = buildLen * keysFound / 2; - while(calcKeys < numKeys && i != 0) { + while (calcKeys < numKeys && i != 0) { calcKeys *= 2; i /= 8; } @@ -724,36 +769,40 @@ protected void grailCommonSort(int[] arr, int pos, int len, int[] buffer, int bu } private void grailInPlaceMerge(int[] arr, int pos, int len1, int len2) { - if(len1 < 3 || len2 < 3) { + if (len1 < 3 || len2 < 3) { this.grailMergeWithoutBuffer(arr, pos, len1, len2); return; } int midpoint; - if(len1 < len2) midpoint = len1 + len2 / 2; - else midpoint = len1 / 2; + if (len1 < len2) + midpoint = len1 + len2 / 2; + else + midpoint = len1 / 2; - //Left binary search + // Left binary search int len1Left, len1Right; len1Left = len1Right = this.grailBinSearch(arr, pos, len1, pos + midpoint, true); - //Right binary search - if(len1Right < len1 && Reads.compareValues(arr[pos + len1Right], arr[pos + midpoint]) == 0) { + // Right binary search + if (len1Right < len1 && Reads.compareValues(arr[pos + len1Right], arr[pos + midpoint]) == 0) { len1Right = this.grailBinSearch(arr, pos + len1Left, len1 - len1Left, pos + midpoint, false) + len1Left; } int len2Left, len2Right; len2Left = len2Right = this.grailBinSearch(arr, pos + len1, len2, pos + midpoint, true); - if(len2Right < len2 && Reads.compareValues(arr[pos + len1 + len2Right], arr[pos + midpoint]) == 0) { - len2Right = this.grailBinSearch(arr, pos + len1 + len2Left, len2 - len2Left, pos + midpoint, false) + len2Left; + if (len2Right < len2 && Reads.compareValues(arr[pos + len1 + len2Right], arr[pos + midpoint]) == 0) { + len2Right = this.grailBinSearch(arr, pos + len1 + len2Left, len2 - len2Left, pos + midpoint, false) + + len2Left; } - if(len1Left == len1Right) this.grailRotate(arr, pos + len1Right, len1 - len1Right, len2Right); + if (len1Left == len1Right) + this.grailRotate(arr, pos + len1Right, len1 - len1Right, len2Right); else { this.grailRotate(arr, pos + len1Left, len1 - len1Left, len2Left); - if(len2Right != len2Left) { + if (len2Right != len2Left) { this.grailRotate(arr, pos + (len1Right + len2Left), len1 - len1Right, len2Right - len2Left); } } @@ -761,20 +810,23 @@ private void grailInPlaceMerge(int[] arr, int pos, int len1, int len2) { this.grailInPlaceMerge(arr, pos + (len1Right + len2Right), len1 - len1Right, len2 - len2Right); this.grailInPlaceMerge(arr, pos, len1Left, len2Left); } + protected void grailInPlaceMergeSort(int[] arr, int start, int len) { - for(int dist = start + 1; dist < len; dist += 2) { - if(Reads.compareValues(arr[dist - 1], arr[dist]) > 0) this.grailSwap(arr, dist - 1, dist); + for (int dist = start + 1; dist < len; dist += 2) { + if (Reads.compareValues(arr[dist - 1], arr[dist]) > 0) + this.grailSwap(arr, dist - 1, dist); } - for(int part = 2; part < len; part *= 2) { + for (int part = 2; part < len; part *= 2) { int left = start, right = len - 2 * part; - while(left <= right) { + while (left <= right) { this.grailInPlaceMerge(arr, left, part, part); left += 2 * part; } int rest = len - left; - if(rest > part) this.grailInPlaceMerge(arr, left, part, rest - part); + if (rest > part) + this.grailInPlaceMerge(arr, left, part, rest - part); } } } diff --git a/src/main/java/io/github/arrayv/sorts/templates/HeapSorting.java b/src/main/java/io/github/arrayv/sorts/templates/HeapSorting.java index 3f74316a..8cd6b981 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/HeapSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/HeapSorting.java @@ -22,22 +22,21 @@ protected HeapSorting(ArrayVisualizer arrayVisualizer) { private void siftDown(int[] array, int root, int dist, int start, double sleep, boolean isMax) { int compareVal = 0; - if(isMax) compareVal = -1; - else compareVal = 1; + if (isMax) + compareVal = -1; + else + compareVal = 1; while (root <= dist / 2) { int leaf = 2 * root; if (leaf < dist && Reads.compareValues(array[start + leaf - 1], array[start + leaf]) == compareVal) { leaf++; } - Highlights.markArray(1, start + root - 1); - Highlights.markArray(2, start + leaf - 1); - Delays.sleep(sleep); - if (Reads.compareValues(array[start + root - 1], array[start + leaf - 1]) == compareVal) { + if (Reads.compareIndices(array, start + root - 1, start + leaf - 1, sleep, true) == compareVal) { Writes.swap(array, start + root - 1, start + leaf - 1, 0, true, false); root = leaf; - } - else break; + } else + break; } } @@ -58,7 +57,7 @@ protected void heapSort(int[] arr, int start, int length, double sleep, boolean siftDown(arr, 1, i - 1, start, sleep, isMax); } - if(!isMax) { + if (!isMax) { Writes.reversal(arr, start, start + length - 1, 1, true, false); } } diff --git a/src/main/java/io/github/arrayv/sorts/templates/InsertionSorting.java b/src/main/java/io/github/arrayv/sorts/templates/InsertionSorting.java index b912a648..84c8bf6b 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/InsertionSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/InsertionSorting.java @@ -37,11 +37,11 @@ protected void insertionSort(int[] array, int start, int end, double sleep, bool int pos; int current; - for(int i = start; i < end; i++) { + for (int i = start; i < end; i++) { current = array[i]; pos = i - 1; - while(pos >= start && Reads.compareValues(array[pos], current) > 0){ + while (pos >= start && Reads.compareValues(array[pos], current) > 0) { Writes.write(array, pos + 1, array[pos], sleep, true, auxwrite); pos--; } diff --git a/src/main/java/io/github/arrayv/sorts/templates/KotaSorting.java b/src/main/java/io/github/arrayv/sorts/templates/KotaSorting.java index 18945945..a179e295 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/KotaSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/KotaSorting.java @@ -29,25 +29,27 @@ of this software and associated documentation files (the "Software"), to deal */ /** -* KotaSort / EctaSort -* -* KotaSort is an in-place stable worst case O(n log n) sort with O(1) space -* and is also an implementation of "Block Merge Sort" that inherits some of -* Andrey Astrelin's GrailSort's functions and idea of a movement imitation buffer. -* -* A variant called EctaSort uses an extra 3*sqrt n space for merging in-place and tagging -* without depending on the amount of unique values in the data. -* -* Others: -* kotaSortDynamicBuf() - allocates 2*sqrt n space for merging only -* kotaSortStaticBuf() - makes the most use out of a fixed given amount of space -* -* @author aphitorite -*/ + * KotaSort / EctaSort + * + * KotaSort is an in-place stable worst case O(n log n) sort with O(1) space + * and is also an implementation of "Block Merge Sort" that inherits some of + * Andrey Astrelin's GrailSort's functions and idea of a movement imitation + * buffer. + * + * A variant called EctaSort uses an extra 3*sqrt n space for merging in-place + * and tagging + * without depending on the amount of unique values in the data. + * + * Others: + * kotaSortDynamicBuf() - allocates 2*sqrt n space for merging only + * kotaSortStaticBuf() - makes the most use out of a fixed given amount of space + * + * @author aphitorite + */ public abstract class KotaSorting extends Sort { protected KotaSorting(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - } + super(arrayVisualizer); + } private final int CACHE_SIZE = 32; @@ -63,87 +65,90 @@ protected KotaSorting(ArrayVisualizer arrayVisualizer) { private boolean ext; private void rotate(int[] array, int start, int split, int end) { - int temp; - while(split < end && split > start){ - if (end-split < split-start){ - if(end-split == 1) { + int temp; + while (split < end && split > start) { + if (end - split < split - start) { + if (end - split == 1) { Highlights.clearMark(2); temp = array[split]; this.shift(array, start, split, end, true, true); Writes.write(array, start, temp, 1, true, false); return; - } - else { - this.shift(array, 2*split-end, split, end, true, false); + } else { + this.shift(array, 2 * split - end, split, end, true, false); temp = end; end = split; - split -= temp-split; + split -= temp - split; } - } - else{ - if(split-start == 1) { + } else { + if (split - start == 1) { Highlights.clearMark(2); temp = array[start]; this.shift(array, start, split, end, false, true); - Writes.write(array, end-1, temp, 1, true, false); + Writes.write(array, end - 1, temp, 1, true, false); return; - } - else { - this.shift(array, start, split, 2*split-start, false, false); + } else { + this.shift(array, start, split, 2 * split - start, false, false); temp = start; start = split; - split += split-temp; + split += split - temp; } - } - } - } + } + } + } - /*private void rotate(int[] array, int a, int m, int b) { - Writes.reversal(array, a, b-1, 1, true, false); - m = a+b-m; - Writes.reversal(array, a, m-1, 1, true, false); - Writes.reversal(array, m, b-1, 1, true, false); - }*/ + /* + * private void rotate(int[] array, int a, int m, int b) { + * Writes.reversal(array, a, b-1, 1, true, false); + * m = a+b-m; + * Writes.reversal(array, a, m-1, 1, true, false); + * Writes.reversal(array, m, b-1, 1, true, false); + * } + */ private void kotaSwap(int[] array, int a, int b, boolean aux) { - if(aux) { + if (aux) { Highlights.markArray(2, b); Writes.write(array, a, array[b], 1, true, false); - } - else Writes.swap(array, a, b, 1, true, false); + } else + Writes.swap(array, a, b, 1, true, false); } private int binarySearch(int[] array, int start, int end, int value, boolean left) { int a = start, b = end; - while(a < b) { - int m = (a+b)/2; + while (a < b) { + int m = (a + b) / 2; boolean comp; - if(left) comp = Reads.compareValues(value, array[m]) <= 0; - else comp = Reads.compareValues(value, array[m]) < 0; + if (left) + comp = Reads.compareValues(value, array[m]) <= 0; + else + comp = Reads.compareValues(value, array[m]) < 0; - if(comp) b = m; - else a = m+1; + if (comp) + b = m; + else + a = m + 1; } return a; } private int findKeys(int[] array, int start, int end, int num) { - int numKeys = 1, pos = start, posEnd = start+1; + int numKeys = 1, pos = start, posEnd = start + 1; - for(int i = start+1; i < end && numKeys < num; i++) { + for (int i = start + 1; i < end && numKeys < num; i++) { Highlights.markArray(2, i); Delays.sleep(1); int loc = this.binarySearch(array, pos, posEnd, array[i], true); - if(i == loc || Reads.compareValues(array[i], array[loc]) != 0) { + if (i == loc || Reads.compareValues(array[i], array[loc]) != 0) { this.rotate(array, pos, posEnd, i); - int inc = i-posEnd; - loc += inc; - pos += inc; + int inc = i - posEnd; + loc += inc; + pos += inc; posEnd += inc; - this.rotate(array, loc, posEnd, posEnd+1); + this.rotate(array, loc, posEnd, posEnd + 1); numKeys++; posEnd++; } @@ -153,116 +158,125 @@ private int findKeys(int[] array, int start, int end, int num) { } private void swapToTags(int[] array, int a, int i, boolean aux) { - if(aux) { + if (aux) { Highlights.markArray(1, a); Highlights.markArray(2, i); int temp = this.tags[i]; Writes.write(this.tags, i, array[a], 0, false, true); Writes.write(array, a, temp, 10, false, false); - } - else { - this.kotaSwap(array, this.bufPos+i, a, false); + } else { + this.kotaSwap(array, this.bufPos + i, a, false); Delays.sleep(9); } } /** - Shifts values across a range determined by @param a, m, b - @param left determines which length's order is maintained - */ + * Shifts values across a range determined by @param a, m, b + * + * @param left determines which length's order is maintained + */ private void shift(int[] array, int a, int m, int b, boolean left, boolean aux) { - if(left) { - if(m == b) return; - while(m > a) + if (left) { + if (m == b) + return; + while (m > a) this.kotaSwap(array, --b, --m, aux); - } - else { - if(m == a) return; - while(m < b) + } else { + if (m == a) + return; + while (m < b) this.kotaSwap(array, a++, m++, aux); } } - //NOTE: BW = backwards version + // NOTE: BW = backwards version /** - Swap groups of items of blockLen at starting points @param a, b - (BW: the starting points here would be the end points inclusive) - */ + * Swap groups of items of blockLen at starting points @param a, b + * (BW: the starting points here would be the end points inclusive) + */ private void multiSwap(int[] array, int a, int b, int len, boolean aux) { - for(int i = 0; i < len; i++) - this.kotaSwap(array, a+i, b+i, aux); + for (int i = 0; i < len; i++) + this.kotaSwap(array, a + i, b + i, aux); } private void multiSwapBW(int[] array, int a, int b, int len, boolean aux) { - for(int i = 0; i < len; i++) - this.kotaSwap(array, a-i, b-i, aux); + for (int i = 0; i < len; i++) + this.kotaSwap(array, a - i, b - i, aux); } /** - Performs a selection sort on the tagged blocks - Tag values are unique so this doesn't affect stability - @param pos is the position of where the first tag is closest to start or end (BW) - @param count is the amount of them to select - */ + * Performs a selection sort on the tagged blocks + * Tag values are unique so this doesn't affect stability + * + * @param pos is the position of where the first tag is closest to start or + * end (BW) + * @param count is the amount of them to select + */ private void blockSelect(int[] array, int pos, int count) { - for(int j = 0; j < count; j++) { - int start = pos+j*this.blockLen, min = start; + for (int j = 0; j < count; j++) { + int start = pos + j * this.blockLen, min = start; - for(int i = j+1; i < count; i++) { - int sel = pos+i*this.blockLen; - if(Reads.compareValues(array[sel], array[min]) == -1) + for (int i = j + 1; i < count; i++) { + int sel = pos + i * this.blockLen; + if (Reads.compareValues(array[sel], array[min]) == -1) min = sel; } - if(start != min) this.multiSwap(array, start, min, this.blockLen, false); + if (start != min) + this.multiSwap(array, start, min, this.blockLen, false); this.swapToTags(array, start, j, false); } Highlights.clearMark(2); } private void blockSelectBW(int[] array, int pos, int count) { - for(int j = 0; j < count; j++) { - int start = pos-j*this.blockLen, min = start; + for (int j = 0; j < count; j++) { + int start = pos - j * this.blockLen, min = start; - for(int i = j+1; i < count; i++) { - int sel = pos-i*this.blockLen; - if(Reads.compareValues(array[sel], array[min]) == -1) + for (int i = j + 1; i < count; i++) { + int sel = pos - i * this.blockLen; + if (Reads.compareValues(array[sel], array[min]) == -1) min = sel; } - if(start != min) this.multiSwapBW(array, start, min, this.blockLen, false); + if (start != min) + this.multiSwapBW(array, start, min, this.blockLen, false); this.swapToTags(array, start, j, false); } Highlights.clearMark(2); } /** - (EctaSort) Performs a cycle sort on the tagged blocks to make optimal # of writes - EctaSort's [0, 1, 2, 3, 4...] generated tag values allows this to make O(n) comparisons during the merging process - @param pos is the position of where the first tag is closest to start or end (BW) - @param count is the amount of them to sort - */ + * (EctaSort) Performs a cycle sort on the tagged blocks to make optimal # of + * writes + * EctaSort's [0, 1, 2, 3, 4...] generated tag values allows this to make O(n) + * comparisons during the merging process + * + * @param pos is the position of where the first tag is closest to start or + * end (BW) + * @param count is the amount of them to sort + */ private void blockCycle(int[] array, int pos, int count, int p) { - for(int j = 0; j < count; j++) { - int start = pos+j*this.blockLen; + for (int j = 0; j < count; j++) { + int start = pos + j * this.blockLen; - if(j != array[start]) { + if (j != array[start]) { int first = array[start]; int val = j; this.multiSwap(array, p, start, this.blockLen, true); - while(val != first) { - int valStart = pos+val*this.blockLen; + while (val != first) { + int valStart = pos + val * this.blockLen; - int k = j+1, next = pos+k*this.blockLen; - while(Reads.compareValues(array[next], val) != 0) - next = pos+(++k)*this.blockLen; + int k = j + 1, next = pos + k * this.blockLen; + while (Reads.compareValues(array[next], val) != 0) + next = pos + (++k) * this.blockLen; val = k; this.multiSwap(array, valStart, next, this.blockLen, true); } - first = pos+first*this.blockLen; + first = pos + first * this.blockLen; this.multiSwap(array, first, p, this.blockLen, true); } @@ -271,27 +285,27 @@ private void blockCycle(int[] array, int pos, int count, int p) { } private void blockCycleBW(int[] array, int pos, int count, int p) { - for(int j = 0; j < count; j++) { - int start = pos-j*this.blockLen; + for (int j = 0; j < count; j++) { + int start = pos - j * this.blockLen; - if(j != array[start]) { + if (j != array[start]) { int first = array[start]; int val = j; this.multiSwapBW(array, p, start, this.blockLen, true); - while(val != first) { - int valStart = pos-val*this.blockLen; + while (val != first) { + int valStart = pos - val * this.blockLen; - int k = j+1, next = pos-k*this.blockLen; - while(Reads.compareValues(array[next], val) != 0) - next = pos-(++k)*this.blockLen; + int k = j + 1, next = pos - k * this.blockLen; + while (Reads.compareValues(array[next], val) != 0) + next = pos - (++k) * this.blockLen; val = k; this.multiSwapBW(array, valStart, next, this.blockLen, true); } - first = pos-first*this.blockLen; + first = pos - first * this.blockLen; this.multiSwapBW(array, first, p, this.blockLen, true); } @@ -300,39 +314,39 @@ private void blockCycleBW(int[] array, int pos, int count, int p) { } /** - O(n) worst case in-place merge algorithm - @param [a, m) is the first range - @param [m, b) is the second - */ + * O(n) worst case in-place merge algorithm + * + * @param [a, m) is the first range + * @param [m, b) is the second + */ private void blockMerge(int[] array, int a, int m, int b, boolean auxTag) { - if(b-m <= 2*this.bufLen) { + if (b - m <= 2 * this.bufLen) { this.dualMerge(array, a, m, b, this.bufLen); return; } /** - @var i, j are the pointers to the halves - @var k counts up to blockLen and resets - @var first keeps track of the starting point of a block - @var left, right keeps track of the locations of the buffer through the merge - @var leftAD, rightAD keeps track of the left and right buffer size - @var tagCount increments when a block is tagged - */ + * @var i, j are the pointers to the halves + * @var k counts up to blockLen and resets + * @var first keeps track of the starting point of a block + * @var left, right keeps track of the locations of the buffer through the merge + * @var leftAD, rightAD keeps track of the left and right buffer size + * @var tagCount increments when a block is tagged + */ int i = a, j = m, k, first; int leftAD = this.bufLen, rightAD = 0; - int left = i-this.bufLen, right = j; + int left = i - this.bufLen, right = j; int tagCount = 0; - //merge as many block sized sequences to the left - //no block tagging happens here - while(i < m && leftAD >= rightAD) { //j will never be >= b + // merge as many block sized sequences to the left + // no block tagging happens here + while (i < m && leftAD >= rightAD) { // j will never be >= b k = 0; - while(i < m && k < this.blockLen) { - if(Reads.compareValues(array[i], array[j]) <= 0) { + while (i < m && k < this.blockLen) { + if (Reads.compareValues(array[i], array[j]) <= 0) { this.kotaSwap(array, left++, i++, this.ext); - } - else { + } else { this.kotaSwap(array, left++, j++, this.ext); rightAD++; leftAD--; @@ -341,116 +355,117 @@ private void blockMerge(int[] array, int a, int m, int b, boolean auxTag) { } } - int selStart = left; //where to start selecting the blocks back in place + int selStart = left; // where to start selecting the blocks back in place - while(i < m && j < b) { - //merge as many block sized sequences to the right - while(i < m && j < b && rightAD > leftAD) { + while (i < m && j < b) { + // merge as many block sized sequences to the right + while (i < m && j < b && rightAD > leftAD) { first = right; k = 0; - while(i < m && j < b && k < this.blockLen) { - if(Reads.compareValues(array[i], array[j]) <= 0) { + while (i < m && j < b && k < this.blockLen) { + if (Reads.compareValues(array[i], array[j]) <= 0) { this.kotaSwap(array, right++, i++, this.ext); rightAD--; leftAD++; - } - else { + } else { this.kotaSwap(array, right++, j++, this.ext); } k++; } - //move as many elements as possible to the block before breaking out - while(i < m && k < this.blockLen) { + // move as many elements as possible to the block before breaking out + while (i < m && k < this.blockLen) { this.kotaSwap(array, right++, i++, this.ext); rightAD--; leftAD++; k++; } - while(j < b && k < this.blockLen) { + while (j < b && k < this.blockLen) { this.kotaSwap(array, right++, j++, this.ext); k++; } - if(k == this.blockLen) //if block is not complete don't tag + if (k == this.blockLen) // if block is not complete don't tag this.swapToTags(array, first, tagCount++, auxTag); else { - //if there was a leftover block shift the right buffer back - this.shift(array, first, first+k, b, true, this.ext); - j = b-k; + // if there was a leftover block shift the right buffer back + this.shift(array, first, first + k, b, true, this.ext); + j = b - k; right = first; } } - //merge as many block sized sequences to the left - while(i < m && j < b && leftAD >= rightAD) { + // merge as many block sized sequences to the left + while (i < m && j < b && leftAD >= rightAD) { first = left; k = 0; - while(i < m && j < b && k < this.blockLen) { - if(Reads.compareValues(array[i], array[j]) <= 0) { + while (i < m && j < b && k < this.blockLen) { + if (Reads.compareValues(array[i], array[j]) <= 0) { this.kotaSwap(array, left++, i++, this.ext); - } - else { + } else { this.kotaSwap(array, left++, j++, this.ext); rightAD++; leftAD--; } k++; } - while(i < m && k < this.blockLen) { + while (i < m && k < this.blockLen) { this.kotaSwap(array, left++, i++, this.ext); k++; } - while(j < b && k < this.blockLen) { + while (j < b && k < this.blockLen) { this.kotaSwap(array, left++, j++, this.ext); rightAD++; leftAD--; k++; } - if(k == this.blockLen) + if (k == this.blockLen) this.swapToTags(array, first, tagCount++, auxTag); else { - //rotates leftover block along with buffer to the end + // rotates leftover block along with buffer to the end this.rotate(array, first, m, right); - left += right-m; + left += right - m; leftAD = 0; } } } - if(i >= m && leftAD == this.blockLen && tagCount > 0) { //if the left buffer is the same size as a block - this.multiSwap(array, left, right-this.blockLen, this.blockLen, this.ext); //it can be swapped with the last tagged block - } - else { - if(i < m) { //if left range wasnt fully merged - this.rotate(array, left, m, right); //rotate it to the right buffer along with the left buffer - left += right-m; + if (i >= m && leftAD == this.blockLen && tagCount > 0) { // if the left buffer is the same size as a block + this.multiSwap(array, left, right - this.blockLen, this.blockLen, this.ext); // it can be swapped with the + // last tagged block + } else { + if (i < m) { // if left range wasnt fully merged + this.rotate(array, left, m, right); // rotate it to the right buffer along with the left buffer + left += right - m; } - this.shift(array, left, left+leftAD, right, false, this.ext); //shift left buffer to connect with right buffer + this.shift(array, left, left + leftAD, right, false, this.ext); // shift left buffer to connect with right + // buffer } - if(j < b) this.shift(array, j-this.bufLen, j, b, false, this.ext); //if right range wasnt fully merged - //shift the full buffer to the end - if(auxTag) this.blockCycle(array, selStart, tagCount, b-this.bufLen); - else this.blockSelect(array, selStart, tagCount); + if (j < b) + this.shift(array, j - this.bufLen, j, b, false, this.ext); // if right range wasnt fully merged + // shift the full buffer to the end + if (auxTag) + this.blockCycle(array, selStart, tagCount, b - this.bufLen); + else + this.blockSelect(array, selStart, tagCount); } private void blockMergeBW(int[] array, int a, int m, int b, boolean auxTag) { - int i = m-1, j = b-1, k, first; + int i = m - 1, j = b - 1, k, first; int leftAD = 0, rightAD = this.bufLen; - int left = i, right = j+this.bufLen; + int left = i, right = j + this.bufLen; int tagCount = 0; - while(j >= m && rightAD >= leftAD) { + while (j >= m && rightAD >= leftAD) { k = 0; - while(j >= m && k < this.blockLen) { - if(Reads.compareValues(array[i], array[j]) == 1) { + while (j >= m && k < this.blockLen) { + if (Reads.compareValues(array[i], array[j]) == 1) { this.kotaSwap(array, right--, i--, this.ext); leftAD++; rightAD--; - } - else { + } else { this.kotaSwap(array, right--, j--, this.ext); } k++; @@ -459,165 +474,170 @@ private void blockMergeBW(int[] array, int a, int m, int b, boolean auxTag) { int selStart = right; - while(j >= m && i >= a) { - while(j >= m && i >= a && leftAD > rightAD) { + while (j >= m && i >= a) { + while (j >= m && i >= a && leftAD > rightAD) { first = left; k = 0; - while(j >= m && i >= a && k < this.blockLen) { - if(Reads.compareValues(array[i], array[j]) == 1) { + while (j >= m && i >= a && k < this.blockLen) { + if (Reads.compareValues(array[i], array[j]) == 1) { this.kotaSwap(array, left--, i--, this.ext); - } - else { + } else { this.kotaSwap(array, left--, j--, this.ext); rightAD++; leftAD--; } k++; } - while(j >= m && k < this.blockLen) { + while (j >= m && k < this.blockLen) { this.kotaSwap(array, left--, j--, this.ext); rightAD++; leftAD--; k++; } - while(i >= a && k < this.blockLen) { + while (i >= a && k < this.blockLen) { this.kotaSwap(array, left--, i--, this.ext); k++; } - if(k == this.blockLen) + if (k == this.blockLen) this.swapToTags(array, first, tagCount++, auxTag); else { - this.shift(array, a, first+1-k, first+1, false, this.ext); - i = a-1+k; + this.shift(array, a, first + 1 - k, first + 1, false, this.ext); + i = a - 1 + k; left = first; } } - while(j >= m && i >= a && rightAD >= leftAD) { + while (j >= m && i >= a && rightAD >= leftAD) { first = right; k = 0; - while(j >= m && i >= a && k < this.blockLen) { - if(Reads.compareValues(array[i], array[j]) == 1) { + while (j >= m && i >= a && k < this.blockLen) { + if (Reads.compareValues(array[i], array[j]) == 1) { this.kotaSwap(array, right--, i--, this.ext); leftAD++; rightAD--; - } - else { + } else { this.kotaSwap(array, right--, j--, this.ext); } k++; } - while(j >= m && k < this.blockLen) { + while (j >= m && k < this.blockLen) { this.kotaSwap(array, right--, j--, this.ext); k++; } - while(i >= a && k < this.blockLen) { + while (i >= a && k < this.blockLen) { this.kotaSwap(array, right--, i--, this.ext); leftAD++; rightAD--; k++; } - if(k == this.blockLen) + if (k == this.blockLen) this.swapToTags(array, first, tagCount++, auxTag); else { - this.rotate(array, left+1, m, first+1); - right -= m-(left+1); + this.rotate(array, left + 1, m, first + 1); + right -= m - (left + 1); rightAD = 0; } } } - if(j < m && rightAD == this.blockLen && tagCount > 0) { - this.multiSwapBW(array, right, left+this.blockLen, this.blockLen, this.ext); - } - else { - if(j >= m) { - this.rotate(array, left+1, m, right+1); - right -= m-(left+1); + if (j < m && rightAD == this.blockLen && tagCount > 0) { + this.multiSwapBW(array, right, left + this.blockLen, this.blockLen, this.ext); + } else { + if (j >= m) { + this.rotate(array, left + 1, m, right + 1); + right -= m - (left + 1); } - this.shift(array, left+1, right+1-rightAD, right+1, true, this.ext); + this.shift(array, left + 1, right + 1 - rightAD, right + 1, true, this.ext); } - if(i >= a) this.shift(array, a, i+1, i+1+this.bufLen, true, this.ext); + if (i >= a) + this.shift(array, a, i + 1, i + 1 + this.bufLen, true, this.ext); - if(auxTag) this.blockCycleBW(array, selStart, tagCount, a-1+this.bufLen); - else this.blockSelectBW(array, selStart, tagCount); + if (auxTag) + this.blockCycleBW(array, selStart, tagCount, a - 1 + this.bufLen); + else + this.blockSelectBW(array, selStart, tagCount); } /** - O(n) worst case in-place merge algorithm when merging ~sqrt(n) sized sequences - @param [a, m) is the first range - @param [m, b) is the second - */ + * O(n) worst case in-place merge algorithm when merging ~sqrt(n) sized + * sequences + * + * @param [a, m) is the first range + * @param [m, b) is the second + */ private void inPlaceMerge(int[] array, int a, int m, int b) { int i = a, j = m, k; - while(i < j && j < b){ - if(Reads.compareValues(array[i], array[j]) == 1) { + while (i < j && j < b) { + if (Reads.compareValues(array[i], array[j]) == 1) { k = this.binarySearch(array, j, b, array[i], true); this.rotate(array, i, j, k); - i += k-j; + i += k - j; j = k; - } - else i++; + } else + i++; } } private void inPlaceMergeBW(int[] array, int a, int m, int b) { - int i = m-1, j = b-1, k; + int i = m - 1, j = b - 1, k; - while(j > i && i >= a){ - if(Reads.compareValues(array[i], array[j]) >= 0) { - k = this.binarySearch(array, a, i+1, array[j], true); - this.rotate(array, k, i+1, j+1); + while (j > i && i >= a) { + if (Reads.compareValues(array[i], array[j]) >= 0) { + k = this.binarySearch(array, a, i + 1, array[j], true); + this.rotate(array, k, i + 1, j + 1); - j -= (i+1)-k; - i = k-1; - } - else j--; + j -= (i + 1) - k; + i = k - 1; + } else + j--; } } /** - O(n^2) worst case in-place merge algorithm - Much faster for merging small lists and lists with very few unique values - @param [start, mid) is the first range - @param [mid, end) is the second - */ - private void inPlaceMerge2(int[] array, int start, int mid, int end) { + * O(n^2) worst case in-place merge algorithm + * Much faster for merging small lists and lists with very few unique values + * + * @param [start, mid) is the first range + * @param [mid, end) is the second + */ + private void inPlaceMerge2(int[] array, int start, int mid, int end) { int i = start, m = mid, k = mid, q; - while(m < end) { - if(Reads.compareValues(array[m-1], array[m]) <= 0) + while (m < end) { + if (Reads.compareValues(array[m - 1], array[m]) <= 0) return; - while(i < m-1 && Reads.compareValues(array[i], array[m]) <= 0) i++; + while (i < m - 1 && Reads.compareValues(array[i], array[m]) <= 0) + i++; Writes.swap(array, i++, k++, 1, true, false); - while(i < m) { + while (i < m) { Highlights.markArray(3, m); - while(i < m && k < end && Reads.compareValues(array[m], array[k]) == 1) + while (i < m && k < end && Reads.compareValues(array[m], array[k]) == 1) Writes.swap(array, i++, k++, 1, true, false); Highlights.clearMark(3); - if(i >= m) break; + if (i >= m) + break; - else if(k >= end) { + else if (k >= end) { this.rotate(array, i, m, end); return; } - else if(k-m >= m-i) { + else if (k - m >= m - i) { this.rotate(array, i, m, k); break; } q = m; - while(i < m && q < k && Reads.compareValues(array[q], array[k]) <= 0) + while (i < m && q < k && Reads.compareValues(array[q], array[k]) <= 0) Writes.swap(array, i++, q++, 1, true, false); this.rotate(array, m, q, k); } @@ -626,236 +646,256 @@ else if(k-m >= m-i) { } Highlights.clearMark(3); - } + } /** - O(n^2) worst case in-place stable sort - Makes fewer moves than binary insertion in the worst case but can make 2x more comparisons - Used for merging small lists and sorting lists with very few unique values in-place - @param [start, end) is the sorting range - */ + * O(n^2) worst case in-place stable sort + * Makes fewer moves than binary insertion in the worst case but can make 2x + * more comparisons + * Used for merging small lists and sorting lists with very few unique values + * in-place + * + * @param [start, end) is the sorting range + */ protected void inPlaceMergeSort2(int[] array, int start, int end) { int length = end - start, j; - for(int i = 1; i < length; i *= 2) { - for(j = start; j + 2*i < end; j += 2*i) - this.inPlaceMerge2(array, j, j+i, j+2*i); + for (int i = 1; i < length; i *= 2) { + for (j = start; j + 2 * i < end; j += 2 * i) + this.inPlaceMerge2(array, j, j + i, j + 2 * i); - if(j + i < end) - this.inPlaceMerge2(array, j, j+i, end); + if (j + i < end) + this.inPlaceMerge2(array, j, j + i, end); } } private void mergeWithBuf(int[] array, int a, int m, int b, int l) { - int i = a, j = m, k = a-l; + int i = a, j = m, k = a - l; - while(i < m && j < b) { - if(Reads.compareValues(array[i], array[j]) <= 0) + while (i < m && j < b) { + if (Reads.compareValues(array[i], array[j]) <= 0) this.kotaSwap(array, k++, i++, this.ext); else this.kotaSwap(array, k++, j++, this.ext); } - while(j < b) + while (j < b) this.kotaSwap(array, k++, j++, this.ext); this.shift(array, k, i, m, false, this.ext); } private void dualMerge(int[] array, int a, int m, int b, int l) { - if(b-m <= l) { + if (b - m <= l) { this.mergeWithBuf(array, a, m, b, l); - } - else { - int i = a, j = m, k = a-l; + } else { + int i = a, j = m, k = a - l; - while(k < i && i < m) { - if(Reads.compareValues(array[i], array[j]) <= 0) + while (k < i && i < m) { + if (Reads.compareValues(array[i], array[j]) <= 0) this.kotaSwap(array, k++, i++, this.ext); else this.kotaSwap(array, k++, j++, this.ext); } - if(k < i) - this.shift(array, j-l, j, b, false, this.ext); + if (k < i) + this.shift(array, j - l, j, b, false, this.ext); else { - int i2 = m-1, j2 = b-1; k = (m-1)+(b-j); + int i2 = m - 1, j2 = b - 1; + k = (m - 1) + (b - j); - while(i2 >= i && j2 >= j) { - if(Reads.compareValues(array[i2], array[j2]) == 1) + while (i2 >= i && j2 >= j) { + if (Reads.compareValues(array[i2], array[j2]) == 1) this.kotaSwap(array, k--, i2--, this.ext); else this.kotaSwap(array, k--, j2--, this.ext); } - while(j2 >= j) + while (j2 >= j) this.kotaSwap(array, k--, j2--, this.ext); } } } private void dualMergeBW(int[] array, int a, int m, int b, int l) { - int i = m-1, j = b-1, k = b-1+l; + int i = m - 1, j = b - 1, k = b - 1 + l; - while(k > j && j >= m) { - if(Reads.compareValues(array[i], array[j]) == 1) + while (k > j && j >= m) { + if (Reads.compareValues(array[i], array[j]) == 1) this.kotaSwap(array, k--, i--, this.ext); else this.kotaSwap(array, k--, j--, this.ext); } - if(j < m) - this.shift(array, a, i+1, i+1+l, true, this.ext); + if (j < m) + this.shift(array, a, i + 1, i + 1 + l, true, this.ext); else { int i2 = a, j2 = m; - i++; j++; k = m-(i-a); + i++; + j++; + k = m - (i - a); - while(i2 < i && j2 < j) { - if(Reads.compareValues(array[i2], array[j2]) <= 0) + while (i2 < i && j2 < j) { + if (Reads.compareValues(array[i2], array[j2]) <= 0) this.kotaSwap(array, k++, i2++, this.ext); else this.kotaSwap(array, k++, j2++, this.ext); } - while(i2 < i) + while (i2 < i) this.kotaSwap(array, k++, i2++, this.ext); } } private void mergeWithBufStatic(int[] array, int a, int m, int b, int p, boolean bw) { - if(m-a < 1 || b-m < 1) + if (m - a < 1 || b - m < 1) return; int i, j, k, q; - if(bw) { - i = (b-m)-1; j = m-1; k = b-1; - while(i >= 0 && j >= a) { - if(Reads.compareValues(array[j], array[p+i]) >= 0) { - q = this.binarySearch(array, a, j+1, array[p+i], true); - while(j >= q) Writes.swap(array, k--, j--, 1, true, false); + if (bw) { + i = (b - m) - 1; + j = m - 1; + k = b - 1; + while (i >= 0 && j >= a) { + if (Reads.compareValues(array[j], array[p + i]) >= 0) { + q = this.binarySearch(array, a, j + 1, array[p + i], true); + while (j >= q) + Writes.swap(array, k--, j--, 1, true, false); } - Writes.swap(array, k--, p+(i--), 1, true, false); + Writes.swap(array, k--, p + (i--), 1, true, false); } - while(i >= 0) { - Writes.swap(array, k--, p+(i--), 1, true, false); + while (i >= 0) { + Writes.swap(array, k--, p + (i--), 1, true, false); } - } - else { - i = 0; j = m; k = a; - while(i < m-a && j < b) { - if(Reads.compareValues(array[j], array[p+i]) == -1) { - q = this.binarySearch(array, j, b, array[p+i], true); - while(j < q) Writes.swap(array, k++, j++, 1, true, false); + } else { + i = 0; + j = m; + k = a; + while (i < m - a && j < b) { + if (Reads.compareValues(array[j], array[p + i]) == -1) { + q = this.binarySearch(array, j, b, array[p + i], true); + while (j < q) + Writes.swap(array, k++, j++, 1, true, false); } - Writes.swap(array, k++, p+(i++), 1, true, false); + Writes.swap(array, k++, p + (i++), 1, true, false); } - while(i < m-a) { - Writes.swap(array, k++, p+(i++), 1, true, false); + while (i < m - a) { + Writes.swap(array, k++, p + (i++), 1, true, false); } } } private void mergeExtBuf(int[] array, int a, int b, boolean bw) { int i, j, k, m; - if(bw) { - i = this.bufLen-1; j = (b-1)-this.bufLen; k = b-1; - Highlights.markArray(2, a+i); - while(i >= 0 && j >= a) { - if(Reads.compareValues(array[j], this.cache[i]) >= 0) { - m = this.binarySearch(array, a, j+1, this.cache[i], true); - while(j >= m) Writes.write(array, k--, array[j--], 1, true, false); + if (bw) { + i = this.bufLen - 1; + j = (b - 1) - this.bufLen; + k = b - 1; + Highlights.markArray(2, a + i); + while (i >= 0 && j >= a) { + if (Reads.compareValues(array[j], this.cache[i]) >= 0) { + m = this.binarySearch(array, a, j + 1, this.cache[i], true); + while (j >= m) + Writes.write(array, k--, array[j--], 1, true, false); } Writes.write(array, k--, this.cache[i--], 1, true, false); - if(i > 0) Highlights.markArray(2, a+i); + if (i > 0) + Highlights.markArray(2, a + i); } - while(i >= 0) { + while (i >= 0) { Writes.write(array, k--, this.cache[i--], 1, true, false); - if(i > 0) Highlights.markArray(2, a+i); + if (i > 0) + Highlights.markArray(2, a + i); } - } - else { - i = 0; j = a+this.bufLen; k = a; - Highlights.markArray(2, a+i); - while(i < this.bufLen && j < b) { - if(Reads.compareValues(array[j], this.cache[i]) == -1) { + } else { + i = 0; + j = a + this.bufLen; + k = a; + Highlights.markArray(2, a + i); + while (i < this.bufLen && j < b) { + if (Reads.compareValues(array[j], this.cache[i]) == -1) { m = this.binarySearch(array, j, b, this.cache[i], true); - while(j < m) Writes.write(array, k++, array[j++], 1, true, false); + while (j < m) + Writes.write(array, k++, array[j++], 1, true, false); } Writes.write(array, k++, this.cache[i++], 1, true, false); - Highlights.markArray(2, a+i); + Highlights.markArray(2, a + i); } - while(i < this.bufLen) { + while (i < this.bufLen) { Writes.write(array, k++, this.cache[i++], 1, true, false); - Highlights.markArray(2, a+i); + Highlights.markArray(2, a + i); } } } private boolean kotaIterator(int[] array, int start, int end, boolean auxTag) { - int i = 1, j, effStart = start+this.bufLen, length = end-effStart; + int i = 1, j, effStart = start + this.bufLen, length = end - effStart; - if(!this.ext) { - while(i < 16) { - for(j = effStart; j + 2*i < end; j += 2*i) - this.inPlaceMerge2(array, j, j+i, j+2*i); + if (!this.ext) { + while (i < 16) { + for (j = effStart; j + 2 * i < end; j += 2 * i) + this.inPlaceMerge2(array, j, j + i, j + 2 * i); - if(j + i < end) - this.inPlaceMerge2(array, j, j+i, end); + if (j + i < end) + this.inPlaceMerge2(array, j, j + i, end); i *= 2; } } - while(i <= this.bufLen) { + while (i <= this.bufLen) { int l = i; - for(j = effStart; j + 2*i < end; j += 2*i) - this.mergeWithBuf(array, j, j+i, j+2*i, l); + for (j = effStart; j + 2 * i < end; j += 2 * i) + this.mergeWithBuf(array, j, j + i, j + 2 * i, l); - if(j + i < end) - this.mergeWithBuf(array, j, j+i, end, l); + if (j + i < end) + this.mergeWithBuf(array, j, j + i, end, l); else - this.shift(array, j-l, j, end, false, this.ext); + this.shift(array, j - l, j, end, false, this.ext); i *= 2; - for(j = effStart-l; j + 2*i < end-l; j += 2*i); + for (j = effStart - l; j + 2 * i < end - l; j += 2 * i) + ; - if(j + i < end-l) - this.dualMergeBW(array, j, j+i, end-l, l); + if (j + i < end - l) + this.dualMergeBW(array, j, j + i, end - l, l); else - this.shift(array, j, end-l, end, true, this.ext); + this.shift(array, j, end - l, end, true, this.ext); - for(j -= 2*i; j >= effStart-l; j -= 2*i) - this.dualMergeBW(array, j, j+i, j+2*i, l); + for (j -= 2 * i; j >= effStart - l; j -= 2 * i) + this.dualMergeBW(array, j, j + i, j + 2 * i, l); i *= 2; - if(this.ext && this.effMem < Math.min(i, this.bufLen)) { + if (this.ext && this.effMem < Math.min(i, this.bufLen)) { Highlights.clearMark(2); - Writes.arraycopy(this.cache, 0, array, effStart-this.effMem, this.effMem, 1, true, false); + Writes.arraycopy(this.cache, 0, array, effStart - this.effMem, this.effMem, 1, true, false); this.ext = false; } } - while(i < length) { - for(j = effStart; j + 2*i < end; j += 2*i) - this.blockMerge(array, j, j+i, j+2*i, auxTag); + while (i < length) { + for (j = effStart; j + 2 * i < end; j += 2 * i) + this.blockMerge(array, j, j + i, j + 2 * i, auxTag); - if(j + i < end) - this.blockMerge(array, j, j+i, end, auxTag); + if (j + i < end) + this.blockMerge(array, j, j + i, end, auxTag); else - this.shift(array, j-this.bufLen, j, end, false, this.ext); + this.shift(array, j - this.bufLen, j, end, false, this.ext); i *= 2; - if(i >= length) return true; + if (i >= length) + return true; - for(j = start; j + 2*i < end-this.bufLen; j += 2*i); + for (j = start; j + 2 * i < end - this.bufLen; j += 2 * i) + ; - if(j + i < end-this.bufLen) - this.blockMergeBW(array, j, j+i, end-this.bufLen, auxTag); + if (j + i < end - this.bufLen) + this.blockMergeBW(array, j, j + i, end - this.bufLen, auxTag); else - this.shift(array, j, end-this.bufLen, end, true, this.ext); + this.shift(array, j, end - this.bufLen, end, true, this.ext); - for(j -= 2*i; j >= start; j -= 2*i) - this.blockMergeBW(array, j, j+i, j+2*i, auxTag); + for (j -= 2 * i; j >= start; j -= 2 * i) + this.blockMergeBW(array, j, j + i, j + 2 * i, auxTag); i *= 2; } @@ -863,7 +903,7 @@ private boolean kotaIterator(int[] array, int start, int end, boolean auxTag) { return false; } - //@param ignoredValues + // @param ignoredValues @SuppressWarnings("unused") private void kotaSortLimited(int[] array, int start, int end) { // TODO for aphitorite: implement @@ -871,84 +911,81 @@ private void kotaSortLimited(int[] array, int start, int end) { protected void kotaSort(int[] array, int start, int end) { int length = end - start; - if(length <= 128) { + if (length <= 128) { this.inPlaceMergeSort2(array, start, end); return; } this.ext = false; this.bufPos = start; - for(this.blockLen = 1; this.blockLen*this.blockLen < length; this.blockLen*=2); //ceiling power of 2 sqrt + for (this.blockLen = 1; this.blockLen * this.blockLen < length; this.blockLen *= 2) + ; // ceiling power of 2 sqrt - int ideal = this.blockLen*2; + int ideal = this.blockLen * 2; this.bufLen = this.findKeys(array, start, end, ideal); - if(this.bufLen < ideal) { - if(this.bufLen == 1) { + if (this.bufLen < ideal) { + if (this.bufLen == 1) { return; - } - else if(this.bufLen <= 16) { + } else if (this.bufLen <= 16) { this.inPlaceMergeSort2(array, start, end); return; - } - else { - //phase 2 + } else { + // phase 2 System.out.println("phase 2"); this.inPlaceMergeSort2(array, start, end); return; } } - ideal = length/this.blockLen; - this.tagLen = this.findKeys(array, start+this.bufLen, end, ideal); + ideal = length / this.blockLen; + this.tagLen = this.findKeys(array, start + this.bufLen, end, ideal); - if(this.tagLen < ideal) { - if(this.tagLen <= 16) { + if (this.tagLen < ideal) { + if (this.tagLen <= 16) { this.inPlaceMergeSort2(array, start, end); return; - } - else { - //phase 2 + } else { + // phase 2 System.out.println("phase 2"); this.inPlaceMergeSort2(array, start, end); return; } } - int bufStart = start+this.tagLen; - int effStart = bufStart+this.bufLen; - int bufEnd = start+this.bufLen; + int bufStart = start + this.tagLen; + int effStart = bufStart + this.bufLen; + int bufEnd = start + this.bufLen; this.shift(array, start, bufEnd, effStart, false, false); boolean bw = this.kotaIterator(array, bufStart, end, false); - if(bw) { - int endStart = end-this.bufLen; + if (bw) { + int endStart = end - this.bufLen; this.multiSwap(array, start, endStart, this.tagLen, false); this.mergeWithBufStatic(array, start, bufStart, endStart, endStart, false); this.inPlaceMergeSort2(array, endStart, end); - int mid = endStart+this.blockLen; - int pos = this.binarySearch(array, start, endStart, array[mid-1], true); + int mid = endStart + this.blockLen; + int pos = this.binarySearch(array, start, endStart, array[mid - 1], true); this.rotate(array, pos, endStart, mid); pos += this.blockLen; - this.multiSwapBW(array, end-1, pos-1, this.blockLen, false); - this.mergeWithBufStatic(array, start, pos-this.blockLen, pos, mid, true); + this.multiSwapBW(array, end - 1, pos - 1, this.blockLen, false); + this.mergeWithBufStatic(array, start, pos - this.blockLen, pos, mid, true); this.inPlaceMergeSort2(array, mid, end); this.inPlaceMergeBW(array, pos, mid, end); - } - else { + } else { this.mergeWithBufStatic(array, bufEnd, effStart, end, start, false); this.inPlaceMergeSort2(array, start, bufEnd); - int mid = start+this.blockLen; + int mid = start + this.blockLen; int pos = this.binarySearch(array, bufEnd, end, array[mid], true); this.rotate(array, mid, bufEnd, pos); pos -= this.blockLen; this.multiSwap(array, start, pos, this.blockLen, false); - this.mergeWithBufStatic(array, pos, pos+this.blockLen, end, start, false); + this.mergeWithBufStatic(array, pos, pos + this.blockLen, end, start, false); this.inPlaceMergeSort2(array, start, mid); this.inPlaceMerge(array, start, mid, pos); } @@ -956,28 +993,29 @@ else if(this.bufLen <= 16) { protected void ectaSort(int[] array, int start, int end) { int length = end - start; - if(length <= 16) { + if (length <= 16) { this.inPlaceMergeSort2(array, start, end); return; } this.ext = true; this.bufPos = start; - for(this.blockLen = 1; this.blockLen*this.blockLen < length; this.blockLen*=2); - this.bufLen = this.blockLen*2; + for (this.blockLen = 1; this.blockLen * this.blockLen < length; this.blockLen *= 2) + ; + this.bufLen = this.blockLen * 2; this.effMem = this.bufLen; this.cache = Writes.createExternalArray(this.bufLen); - int effStart = start+this.bufLen; + int effStart = start + this.bufLen; this.inPlaceMergeSort2(array, start, effStart); Highlights.clearMark(2); Writes.arraycopy(array, start, this.cache, 0, this.bufLen, 1, true, true); - if(this.bufLen < length/4) { - this.tagLen = length/this.blockLen; + if (this.bufLen < length / 4) { + this.tagLen = length / this.blockLen; this.tags = Writes.createExternalArray(this.tagLen); - for(int i = 0; i < this.tagLen; i++) + for (int i = 0; i < this.tagLen; i++) Writes.write(this.tags, i, i, 0, false, true); } @@ -990,39 +1028,40 @@ protected void ectaSort(int[] array, int start, int end) { protected void kotaSortDynamicBuf(int[] array, int start, int end) { int length = end - start; - if(length <= 16) { + if (length <= 16) { this.inPlaceMergeSort2(array, start, end); return; } this.ext = true; this.bufPos = start; - for(this.blockLen = 1; this.blockLen*this.blockLen < length; this.blockLen*=2); - this.bufLen = this.blockLen*2; + for (this.blockLen = 1; this.blockLen * this.blockLen < length; this.blockLen *= 2) + ; + this.bufLen = this.blockLen * 2; this.effMem = this.bufLen; - if(this.bufLen < length/4) { - int ideal = length/this.blockLen; + if (this.bufLen < length / 4) { + int ideal = length / this.blockLen; this.tagLen = this.findKeys(array, start, end, ideal); - if(this.tagLen < ideal) { - if(this.tagLen <= 16) { + if (this.tagLen < ideal) { + if (this.tagLen <= 16) { this.inPlaceMergeSort2(array, start, end); return; - } - else { - //phase 2 + } else { + // phase 2 System.out.println("phase 2"); this.inPlaceMergeSort2(array, start, end); return; } } - } else this.tagLen = 0; + } else + this.tagLen = 0; this.cache = Writes.createExternalArray(this.bufLen); - int bufStart = start+this.tagLen; - int effStart = bufStart+this.bufLen; + int bufStart = start + this.tagLen; + int effStart = bufStart + this.bufLen; this.inPlaceMergeSort2(array, bufStart, effStart); Highlights.clearMark(2); @@ -1036,103 +1075,101 @@ protected void kotaSortDynamicBuf(int[] array, int start, int end) { } protected void kotaSortStaticBuf(int[] array, int start, int end) { - if(this.CACHE_SIZE < 4) { + if (this.CACHE_SIZE < 4) { this.kotaSort(array, start, end); return; } int length = end - start; - if(length <= 16) { + if (length <= 16) { this.inPlaceMergeSort2(array, start, end); return; } this.ext = true; this.bufPos = start; - for(this.blockLen = 1; this.blockLen*this.blockLen < length; this.blockLen*=2); - this.bufLen = this.blockLen*2; + for (this.blockLen = 1; this.blockLen * this.blockLen < length; this.blockLen *= 2) + ; + this.bufLen = this.blockLen * 2; this.effMem = Math.min(CACHE_SIZE, this.bufLen); - if(this.effMem == this.bufLen) { + if (this.effMem == this.bufLen) { this.kotaSortDynamicBuf(array, start, end); return; } - int ideal = this.blockLen*2; + int ideal = this.blockLen * 2; this.bufLen = this.findKeys(array, start, end, ideal); - if(this.bufLen < ideal) { - if(this.bufLen == 1) { + if (this.bufLen < ideal) { + if (this.bufLen == 1) { return; - } - else if(this.bufLen <= 16) { + } else if (this.bufLen <= 16) { this.inPlaceMergeSort2(array, start, end); return; - } - else { - //phase 2 + } else { + // phase 2 System.out.println("phase 2"); this.inPlaceMergeSort2(array, start, end); return; } } - if(this.bufLen < length/4) { - ideal = length/this.blockLen; - this.tagLen = this.findKeys(array, start+this.bufLen, end, ideal); + if (this.bufLen < length / 4) { + ideal = length / this.blockLen; + this.tagLen = this.findKeys(array, start + this.bufLen, end, ideal); - if(this.tagLen < ideal) { - if(this.tagLen <= 16) { + if (this.tagLen < ideal) { + if (this.tagLen <= 16) { this.inPlaceMergeSort2(array, start, end); return; - } - else { - //phase 2 + } else { + // phase 2 System.out.println("phase 2"); this.inPlaceMergeSort2(array, start, end); return; } } - } else this.tagLen = 0; + } else + this.tagLen = 0; - int bufStart = start+this.tagLen; - int effStart = bufStart+this.bufLen; - int bufEnd = start+this.bufLen; + int bufStart = start + this.tagLen; + int effStart = bufStart + this.bufLen; + int bufEnd = start + this.bufLen; this.shift(array, start, bufEnd, effStart, false, false); this.cache = Writes.createExternalArray(this.effMem); Highlights.clearMark(2); - Writes.arraycopy(array, effStart-this.effMem, this.cache, 0, this.effMem, 1, true, true); + Writes.arraycopy(array, effStart - this.effMem, this.cache, 0, this.effMem, 1, true, true); boolean bw = this.kotaIterator(array, bufStart, end, false); - if(bw) { - int endStart = end-this.bufLen; + if (bw) { + int endStart = end - this.bufLen; this.multiSwap(array, start, endStart, this.tagLen, false); this.mergeWithBufStatic(array, start, bufStart, endStart, endStart, false); this.inPlaceMergeSort2(array, endStart, end); - int mid = endStart+this.blockLen; - int pos = this.binarySearch(array, start, endStart, array[mid-1], true); + int mid = endStart + this.blockLen; + int pos = this.binarySearch(array, start, endStart, array[mid - 1], true); this.rotate(array, pos, endStart, mid); pos += this.blockLen; - this.multiSwapBW(array, end-1, pos-1, this.blockLen, false); - this.mergeWithBufStatic(array, start, pos-this.blockLen, pos, mid, true); + this.multiSwapBW(array, end - 1, pos - 1, this.blockLen, false); + this.mergeWithBufStatic(array, start, pos - this.blockLen, pos, mid, true); this.inPlaceMergeSort2(array, mid, end); this.inPlaceMergeBW(array, pos, mid, end); - } - else { + } else { this.mergeWithBufStatic(array, bufEnd, effStart, end, start, false); this.inPlaceMergeSort2(array, start, bufEnd); - int mid = start+this.blockLen; + int mid = start + this.blockLen; int pos = this.binarySearch(array, bufEnd, end, array[mid], true); this.rotate(array, mid, bufEnd, pos); pos -= this.blockLen; this.multiSwap(array, start, pos, this.blockLen, false); - this.mergeWithBufStatic(array, pos, pos+this.blockLen, end, start, false); + this.mergeWithBufStatic(array, pos, pos + this.blockLen, end, start, false); this.inPlaceMergeSort2(array, start, mid); this.inPlaceMerge(array, start, mid, pos); } diff --git a/src/main/java/io/github/arrayv/sorts/templates/MergeSorting.java b/src/main/java/io/github/arrayv/sorts/templates/MergeSorting.java index 25385087..afc87b56 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/MergeSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/MergeSorting.java @@ -37,45 +37,42 @@ protected MergeSorting(ArrayVisualizer arrayVisualizer) { } private void merge(int[] array, int[] tmp, int start, int mid, int end, boolean binary) { - if(start == mid) return; + if (start == mid) + return; - if(end - start < 32 && binary) { + if (end - start < 32 && binary) { return; - } - else if(end - start < 64 && binary) { + } else if (end - start < 64 && binary) { binaryInserter.customBinaryInsert(array, start, end, 0.333); - } - else { - merge(array, tmp, start, (mid+start)/2, mid, binary); - merge(array, tmp, mid, (mid+end)/2, end, binary); + } else { + merge(array, tmp, start, (mid + start) / 2, mid, binary); + merge(array, tmp, mid, (mid + end) / 2, end, binary); int low = start; int high = mid; - for(int nxt = 0; nxt < end - start; nxt++){ - if(low >= mid && high >= end) break; + for (int nxt = 0; nxt < end - start; nxt++) { + if (low >= mid && high >= end) + break; Highlights.markArray(1, low); Highlights.markArray(2, high); - if(low < mid && high >= end){ + if (low < mid && high >= end) { Highlights.clearMark(2); Writes.write(tmp, nxt, array[low++], 1, false, true); - } - else if(low >= mid && high < end){ + } else if (low >= mid && high < end) { Highlights.clearMark(1); Writes.write(tmp, nxt, array[high++], 1, false, true); - } - else if(Reads.compareValues(array[low], array[high]) <= 0){ + } else if (Reads.compareValues(array[low], array[high]) <= 0) { Writes.write(tmp, nxt, array[low++], 1, false, true); - } - else{ + } else { Writes.write(tmp, nxt, array[high++], 1, false, true); } } Highlights.clearMark(2); - for(int i = 0; i < end - start; i++){ + for (int i = 0; i < end - start; i++) { Writes.write(array, start + i, tmp[i], 1, true, false); } } @@ -84,7 +81,7 @@ else if(Reads.compareValues(array[low], array[high]) <= 0){ protected void mergeSort(int[] array, int length, boolean binary) { binaryInserter = new BinaryInsertionSort(this.arrayVisualizer); - if(length < 32 && binary) { + if (length < 32 && binary) { binaryInserter.customBinaryInsert(array, 0, length, 0.333); return; } diff --git a/src/main/java/io/github/arrayv/sorts/templates/MultiWayMergeSorting.java b/src/main/java/io/github/arrayv/sorts/templates/MultiWayMergeSorting.java index ec312be3..30d51f0a 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/MultiWayMergeSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/MultiWayMergeSorting.java @@ -29,9 +29,9 @@ of this software and associated documentation files (the "Software"), to deal */ public abstract class MultiWayMergeSorting extends Sort { - protected MultiWayMergeSorting(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - } + protected MultiWayMergeSorting(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } protected boolean keyLessThan(int[] src, int[] pa, int a, int b) { int cmp = Reads.compareValues(src[pa[a]], src[pa[b]]); @@ -39,19 +39,19 @@ protected boolean keyLessThan(int[] src, int[] pa, int a, int b) { } protected void siftDown(int[] src, int[] heap, int[] pa, int t, int r, int size) { - while(2*r+2 < size) { - int nxt = 2*r+1; - int min = nxt + (this.keyLessThan(src, pa, heap[nxt], heap[nxt+1]) ? 0 : 1); + while (2 * r + 2 < size) { + int nxt = 2 * r + 1; + int min = nxt + (this.keyLessThan(src, pa, heap[nxt], heap[nxt + 1]) ? 0 : 1); - if(this.keyLessThan(src, pa, heap[min], t)) { + if (this.keyLessThan(src, pa, heap[min], t)) { Writes.write(heap, r, heap[min], 0.25, true, true); r = min; - } - else break; + } else + break; } - int min = 2*r+1; + int min = 2 * r + 1; - if(min < size && this.keyLessThan(src, pa, heap[min], t)) { + if (min < size && this.keyLessThan(src, pa, heap[min], t)) { Writes.write(heap, r, heap[min], 0.25, true, true); r = min; } @@ -59,21 +59,21 @@ protected void siftDown(int[] src, int[] heap, int[] pa, int t, int r, int size) } protected void kWayMerge(int[] src, int[] dest, int[] heap, int[] pa, int[] pb, int size, boolean auxWrite) { - for(int i = 0; i < size; i++) + for (int i = 0; i < size; i++) Writes.write(heap, i, i, 0, false, true); - for(int i = (size-1)/2; i >= 0; i--) + for (int i = (size - 1) / 2; i >= 0; i--) this.siftDown(src, heap, pa, heap[i], i, size); - for(int i = 0; size > 0; i++) { + for (int i = 0; size > 0; i++) { int min = heap[0]; Highlights.markArray(2, pa[min]); Writes.write(dest, i, src[pa[min]], 0.5, !auxWrite, auxWrite); - Writes.write(pa, min, pa[min]+1, 0, false, true); + Writes.write(pa, min, pa[min] + 1, 0, false, true); - if(pa[min] == pb[min]) + if (pa[min] == pb[min]) this.siftDown(src, heap, pa, heap[--size], 0, size); else this.siftDown(src, heap, pa, heap[0], 0, size); diff --git a/src/main/java/io/github/arrayv/sorts/templates/PDQSorting.java b/src/main/java/io/github/arrayv/sorts/templates/PDQSorting.java index fa98a977..5f290045 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/PDQSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/PDQSorting.java @@ -71,11 +71,13 @@ protected void deleteAux() { // Returns floor(log2(n)), assumes n > 0. public static int pdqLog(int n) { int log = 0; - while ((n >>= 1) != 0) ++log; + while ((n >>= 1) != 0) + ++log; return log; } - // We do not record laps here in order to better estimate Branchless PDQ's running time + // We do not record laps here in order to better estimate Branchless PDQ's + // running time private int pdqLessThan(int a, int b) { Reads.addComparison(); return 1 & (Boolean.hashCode(a < b) >> 1); @@ -83,15 +85,17 @@ private int pdqLessThan(int a, int b) { // Sorts [begin, end) using insertion sort with the given comparison function. private void pdqInsertSort(int[] array, int begin, int end) { - if (begin == end) return; + if (begin == end) + return; - double sleep = 1/3d; + double sleep = 1 / 3d; for (int cur = begin + 1; cur != end; ++cur) { int sift = cur; int siftMinusOne = cur - 1; - // Compare first so we can avoid 2 moves for an element already positioned correctly. + // Compare first so we can avoid 2 moves for an element already positioned + // correctly. if (Reads.compareValues(array[sift], array[siftMinusOne]) < 0) { int tmp = array[sift]; do { @@ -103,18 +107,22 @@ private void pdqInsertSort(int[] array, int begin, int end) { } } - // Sorts [begin, end) using insertion sort with the given comparison function. Assumes - // array[begin - 1] is an element smaller than or equal to any element in [begin, end). + // Sorts [begin, end) using insertion sort with the given comparison function. + // Assumes + // array[begin - 1] is an element smaller than or equal to any element in + // [begin, end). private void pdqUnguardInsertSort(int[] array, int begin, int end) { - if (begin == end) return; + if (begin == end) + return; - double sleep = 1/3d; + double sleep = 1 / 3d; for (int cur = begin + 1; cur != end; ++cur) { int sift = cur; int siftMinusOne = cur - 1; - // Compare first so we can avoid 2 moves for an element already positioned correctly. + // Compare first so we can avoid 2 moves for an element already positioned + // correctly. if (Reads.compareValues(array[sift], array[siftMinusOne]) < 0) { int tmp = array[sift]; @@ -127,22 +135,27 @@ private void pdqUnguardInsertSort(int[] array, int begin, int end) { } } - // Attempts to use insertion sort on [begin, end). Will return false if more than - // partialInsertSortLimit elements were moved, and abort sorting. Otherwise it will + // Attempts to use insertion sort on [begin, end). Will return false if more + // than + // partialInsertSortLimit elements were moved, and abort sorting. Otherwise it + // will // successfully sort and return true. private boolean pdqPartialInsertSort(int[] array, int begin, int end) { - if (begin == end) return true; + if (begin == end) + return true; - double sleep = 1/3d; + double sleep = 1 / 3d; int limit = 0; for (int cur = begin + 1; cur != end; ++cur) { - if (limit > partialInsertSortLimit) return false; + if (limit > partialInsertSortLimit) + return false; int sift = cur; int siftMinusOne = cur - 1; - // Compare first so we can avoid 2 moves for an element already positioned correctly. + // Compare first so we can avoid 2 moves for an element already positioned + // correctly. if (Reads.compareValues(array[sift], array[siftMinusOne]) < 0) { int tmp = array[sift]; @@ -164,23 +177,28 @@ private void pdqSortTwo(int[] array, int a, int b) { Highlights.clearMark(2); } - // Sorts the elements array[a], array[b] and array[c] using comparison function compare. + // Sorts the elements array[a], array[b] and array[c] using comparison function + // compare. private void pdqSortThree(int[] array, int a, int b, int c) { this.pdqSortTwo(array, a, b); this.pdqSortTwo(array, b, c); this.pdqSortTwo(array, a, b); } - // With Branchless PDQSort, in order to better estimate the gains in speed from branchless partioning, we treat the writes to the offset arrays - // and specialized less than comparison as negligible, and only record time from elements being swapped into position. By no means is this - // exact, yet it is a much closer estimate than what was happening before with recording time for every block being written. + // With Branchless PDQSort, in order to better estimate the gains in speed from + // branchless partioning, we treat the writes to the offset arrays + // and specialized less than comparison as negligible, and only record time from + // elements being swapped into position. By no means is this + // exact, yet it is a much closer estimate than what was happening before with + // recording time for every block being written. private void pdqSwapOffsets(int[] array, int first, int last, int[] leftOffsets, int leftOffsetsPos, - int[] rightOffsets, int rightOffsetsPos, int num, boolean useSwaps) { + int[] rightOffsets, int rightOffsetsPos, int num, boolean useSwaps) { if (useSwaps) { // This case is needed for the descending distribution, where we need // to have proper swapping for pdqsort to remain O(n). for (int i = 0; i < num; ++i) { - Writes.swap(array, first + leftOffsets[leftOffsetsPos + i], last - rightOffsets[rightOffsetsPos + i], 1, true, false); + Writes.swap(array, first + leftOffsets[leftOffsetsPos + i], last - rightOffsets[rightOffsetsPos + i], 1, + true, false); } Highlights.clearMark(2); } else if (num > 0) { @@ -198,29 +216,41 @@ private void pdqSwapOffsets(int[] array, int first, int last, int[] leftOffsets, } } - // Partitions [begin, end) around pivot array[begin] using comparison function compare. Elements equal - // to the pivot are put in the right-hand partition. Returns the position of the pivot after - // partitioning and whether the passed sequence already was correctly partitioned. Assumes the + // Partitions [begin, end) around pivot array[begin] using comparison function + // compare. Elements equal + // to the pivot are put in the right-hand partition. Returns the position of the + // pivot after + // partitioning and whether the passed sequence already was correctly + // partitioned. Assumes the // pivot is a median of at least 3 elements and that [begin, end) is at least // insertSortThreshold long. Uses branchless partitioning. - // We do not record laps throughout the vast majority of this method in order to better estimate Branchless PDQ's running time + // We do not record laps throughout the vast majority of this method in order to + // better estimate Branchless PDQ's running time private PDQPair pdqPartRightBranchless(int[] array, int begin, int end) { // Move pivot into local for speed. int pivot = array[begin]; int first = begin; int last = end; - // Find the first element greater than or equal than the pivot (the median of 3 guarantees + // Find the first element greater than or equal than the pivot (the median of 3 + // guarantees // this exists). - while (this.pdqLessThan(array[++first], pivot) == 1); + while (this.pdqLessThan(array[++first], pivot) == 1) + ; - // Find the first element strictly smaller than the pivot. We have to guard this search if + // Find the first element strictly smaller than the pivot. We have to guard this + // search if // there was no element before *first. - if (first - 1 == begin) while (first < last && this.pdqLessThan(array[--last], pivot) == 0); - else while ( this.pdqLessThan(array[--last], pivot) == 0); + if (first - 1 == begin) + while (first < last && this.pdqLessThan(array[--last], pivot) == 0) + ; + else + while (this.pdqLessThan(array[--last], pivot) == 0) + ; - // If the first pair of elements that should be swapped to partition are the same element, + // If the first pair of elements that should be swapped to partition are the + // same element, // the passed in sequence already was correctly partitioned. boolean alreadyParted = first >= last; if (!alreadyParted) { @@ -229,10 +259,11 @@ private PDQPair pdqPartRightBranchless(int[] array, int begin, int end) { Highlights.clearMark(2); } - // The following branchless partitioning is derived from "BlockQuicksort: How Branch + // The following branchless partitioning is derived from "BlockQuicksort: How + // Branch // Mispredictions don’t affect Quicksort" by Stefan Edelkamp and Armin Weiss. - //int[] leftOffsets = Writes.createExternalArray(blockSize + cachelineSize); - //int[] rightOffsets = Writes.createExternalArray(blockSize + cachelineSize); + // int[] leftOffsets = Writes.createExternalArray(blockSize + cachelineSize); + // int[] rightOffsets = Writes.createExternalArray(blockSize + cachelineSize); int leftNum, rightNum, leftStart, rightStart; leftNum = rightNum = leftStart = rightStart = 0; @@ -243,22 +274,46 @@ private PDQPair pdqPartRightBranchless(int[] array, int begin, int end) { int it = first; Highlights.clearMark(1); for (int i = 0; i < blockSize;) { - leftOffsets[leftNum] = i++; leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); - leftOffsets[leftNum] = i++; leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); - leftOffsets[leftNum] = i++; leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); - leftOffsets[leftNum] = i++; leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); - leftOffsets[leftNum] = i++; leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); - leftOffsets[leftNum] = i++; leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); - leftOffsets[leftNum] = i++; leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); - leftOffsets[leftNum] = i++; leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); + leftOffsets[leftNum] = i++; + leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); + leftOffsets[leftNum] = i++; + leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); + leftOffsets[leftNum] = i++; + leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); + leftOffsets[leftNum] = i++; + leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); + leftOffsets[leftNum] = i++; + leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); + leftOffsets[leftNum] = i++; + leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); + leftOffsets[leftNum] = i++; + leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); + leftOffsets[leftNum] = i++; + leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); } Highlights.clearMark(2); } @@ -267,33 +322,62 @@ private PDQPair pdqPartRightBranchless(int[] array, int begin, int end) { int it = last; Highlights.clearMark(1); for (int i = 0; i < blockSize;) { - rightOffsets[rightNum] = ++i; rightNum += this.pdqLessThan(array[--it], pivot); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); - rightOffsets[rightNum] = ++i; rightNum += this.pdqLessThan(array[--it], pivot); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); - rightOffsets[rightNum] = ++i; rightNum += this.pdqLessThan(array[--it], pivot); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); - rightOffsets[rightNum] = ++i; rightNum += this.pdqLessThan(array[--it], pivot); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); - rightOffsets[rightNum] = ++i; rightNum += this.pdqLessThan(array[--it], pivot); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); - rightOffsets[rightNum] = ++i; rightNum += this.pdqLessThan(array[--it], pivot); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); - rightOffsets[rightNum] = ++i; rightNum += this.pdqLessThan(array[--it], pivot); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); - rightOffsets[rightNum] = ++i; rightNum += this.pdqLessThan(array[--it], pivot); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); + rightOffsets[rightNum] = ++i; + rightNum += this.pdqLessThan(array[--it], pivot); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); + rightOffsets[rightNum] = ++i; + rightNum += this.pdqLessThan(array[--it], pivot); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); + rightOffsets[rightNum] = ++i; + rightNum += this.pdqLessThan(array[--it], pivot); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); + rightOffsets[rightNum] = ++i; + rightNum += this.pdqLessThan(array[--it], pivot); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); + rightOffsets[rightNum] = ++i; + rightNum += this.pdqLessThan(array[--it], pivot); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); + rightOffsets[rightNum] = ++i; + rightNum += this.pdqLessThan(array[--it], pivot); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); + rightOffsets[rightNum] = ++i; + rightNum += this.pdqLessThan(array[--it], pivot); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); + rightOffsets[rightNum] = ++i; + rightNum += this.pdqLessThan(array[--it], pivot); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); } Highlights.clearMark(2); } // Swap elements and update block sizes and first/last boundaries. int num = Math.min(leftNum, rightNum); - this.pdqSwapOffsets(array, first, last, leftOffsets, leftStart, rightOffsets, rightStart, num, leftNum == rightNum); - leftNum -= num; rightNum -= num; - leftStart += num; rightStart += num; - if (leftNum == 0) first += blockSize; - if (rightNum == 0) last -= blockSize; + this.pdqSwapOffsets(array, first, last, leftOffsets, leftStart, rightOffsets, rightStart, num, + leftNum == rightNum); + leftNum -= num; + rightNum -= num; + leftStart += num; + rightStart += num; + if (leftNum == 0) + first += blockSize; + if (rightNum == 0) + last -= blockSize; } int leftSize = 0, rightSize = 0; @@ -317,8 +401,11 @@ private PDQPair pdqPartRightBranchless(int[] array, int begin, int end) { int it = first; Highlights.clearMark(1); for (int i = 0; i < leftSize;) { - leftOffsets[leftNum] = i++; leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); + leftOffsets[leftNum] = i++; + leftNum += Math.abs(this.pdqLessThan(array[it++], pivot) - 1); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); } Highlights.clearMark(2); } @@ -327,32 +414,43 @@ private PDQPair pdqPartRightBranchless(int[] array, int begin, int end) { int it = last; Highlights.clearMark(1); for (int i = 0; i < rightSize;) { - rightOffsets[rightNum] = ++i; rightNum += this.pdqLessThan(array[--it], pivot); - Writes.changeAuxWrites(1); Highlights.markArray(2, it); Delays.sleep(0.5); + rightOffsets[rightNum] = ++i; + rightNum += this.pdqLessThan(array[--it], pivot); + Writes.changeAuxWrites(1); + Highlights.markArray(2, it); + Delays.sleep(0.5); } Highlights.clearMark(2); } int num = Math.min(leftNum, rightNum); - this.pdqSwapOffsets(array, first, last, leftOffsets, leftStart, rightOffsets, rightStart, num, leftNum == rightNum); - leftNum -= num; rightNum -= num; - leftStart += num; rightStart += num; - if (leftNum == 0) first += leftSize; - if (rightNum == 0) last -= rightSize; + this.pdqSwapOffsets(array, first, last, leftOffsets, leftStart, rightOffsets, rightStart, num, + leftNum == rightNum); + leftNum -= num; + rightNum -= num; + leftStart += num; + rightStart += num; + if (leftNum == 0) + first += leftSize; + if (rightNum == 0) + last -= rightSize; int leftOffsetsPos = 0; int rightOffsetsPos = 0; - // We have now fully identified [first, last)'s proper position. Swap the last elements. + // We have now fully identified [first, last)'s proper position. Swap the last + // elements. if (leftNum != 0) { leftOffsetsPos += leftStart; - while (leftNum-- != 0) Writes.swap(array, first + leftOffsets[leftOffsetsPos + leftNum], --last, 1, true, false); + while (leftNum-- != 0) + Writes.swap(array, first + leftOffsets[leftOffsetsPos + leftNum], --last, 1, true, false); Highlights.clearMark(2); first = last; } if (rightNum != 0) { rightOffsetsPos += rightStart; - while (rightNum-- != 0) Writes.swap(array, last - rightOffsets[rightOffsetsPos + rightNum], first++, 1, true, false); + while (rightNum-- != 0) + Writes.swap(array, last - rightOffsets[rightOffsetsPos + rightNum], first++, 1, true, false); Highlights.clearMark(2); last = first; } @@ -365,9 +463,12 @@ private PDQPair pdqPartRightBranchless(int[] array, int begin, int end) { return new PDQPair(pivotPos, alreadyParted); } - // Partitions [begin, end) around pivot array[begin] using comparison function compare. Elements equal - // to the pivot are put in the right-hand partition. Returns the position of the pivot after - // partitioning and whether the passed sequence already was correctly partitioned. Assumes the + // Partitions [begin, end) around pivot array[begin] using comparison function + // compare. Elements equal + // to the pivot are put in the right-hand partition. Returns the position of the + // pivot after + // partitioning and whether the passed sequence already was correctly + // partitioned. Assumes the // pivot is a median of at least 3 elements and that [begin, end) is at least // insertSortThreshold long. @@ -377,14 +478,16 @@ private PDQPair pdqPartRight(int[] array, int begin, int end) { int first = begin; int last = end; - // Find the first element greater than or equal than the pivot (the median of 3 guarantees + // Find the first element greater than or equal than the pivot (the median of 3 + // guarantees // this exists). while (Reads.compareValues(array[++first], pivot) < 0) { Highlights.markArray(1, first); Delays.sleep(0.25); } - // Find the first element strictly smaller than the pivot. We have to guard this search if + // Find the first element strictly smaller than the pivot. We have to guard this + // search if // there was no element before *first. if (first - 1 == begin) while (first < last && !(Reads.compareValues(array[--last], pivot) < 0)) { @@ -392,17 +495,20 @@ private PDQPair pdqPartRight(int[] array, int begin, int end) { Delays.sleep(0.25); } else - while ( !(Reads.compareValues(array[--last], pivot) < 0)) { + while (!(Reads.compareValues(array[--last], pivot) < 0)) { Highlights.markArray(2, last); Delays.sleep(0.25); } - // If the first pair of elements that should be swapped to partition are the same element, + // If the first pair of elements that should be swapped to partition are the + // same element, // the passed in sequence already was correctly partitioned. boolean alreadyParted = first >= last; - // Keep swapping pairs of elements that are on the wrong side of the pivot. Previously - // swapped pairs guard the searches, which is why the first iteration is special-cased + // Keep swapping pairs of elements that are on the wrong side of the pivot. + // Previously + // swapped pairs guard the searches, which is why the first iteration is + // special-cased // above. while (first < last) { Writes.swap(array, first, last, 1, true, false); @@ -425,9 +531,12 @@ private PDQPair pdqPartRight(int[] array, int begin, int end) { return new PDQPair(pivotPos, alreadyParted); } - // Similar function to the one above, except elements equal to the pivot are put to the left of - // the pivot and it doesn't check or return if the passed sequence already was partitioned. - // Since this is rarely used (the many equal case), and in that case pdqsort already has O(n) + // Similar function to the one above, except elements equal to the pivot are put + // to the left of + // the pivot and it doesn't check or return if the passed sequence already was + // partitioned. + // Since this is rarely used (the many equal case), and in that case pdqsort + // already has O(n) // performance, no block quicksort is applied here for simplicity. private int pdqPartLeft(int[] array, int begin, int end) { @@ -447,7 +556,7 @@ private int pdqPartLeft(int[] array, int begin, int end) { Delays.sleep(0.25); } else - while ( !(Reads.compareValues(pivot, array[++first]) < 0)) { + while (!(Reads.compareValues(pivot, array[++first]) < 0)) { Highlights.markArray(1, first); Delays.sleep(0.25); } @@ -481,8 +590,10 @@ protected void pdqLoop(int[] array, int begin, int end, boolean Branchless, int // Insertion sort is faster for small arrays. if (size < insertSortThreshold) { - if (leftmost) this.pdqInsertSort(array, begin, end); - else this.pdqUnguardInsertSort(array, begin, end); + if (leftmost) + this.pdqInsertSort(array, begin, end); + else + this.pdqUnguardInsertSort(array, begin, end); return; } @@ -495,12 +606,17 @@ protected void pdqLoop(int[] array, int begin, int end, boolean Branchless, int this.pdqSortThree(array, begin + (halfSize - 1), begin + halfSize, begin + (halfSize + 1)); Writes.swap(array, begin, begin + halfSize, 1, true, false); Highlights.clearMark(2); - } else this.pdqSortThree(array, begin + halfSize, begin, end - 1); - - // If array[begin - 1] is the end of the right partition of a previous partition operation - // there is no element in [begin, end) that is smaller than array[begin - 1]. Then if our - // pivot compares equal to array[begin - 1] we change strategy, putting equal elements in - // the left partition, greater elements in the right partition. We do not have to + } else + this.pdqSortThree(array, begin + halfSize, begin, end - 1); + + // If array[begin - 1] is the end of the right partition of a previous partition + // operation + // there is no element in [begin, end) that is smaller than array[begin - 1]. + // Then if our + // pivot compares equal to array[begin - 1] we change strategy, putting equal + // elements in + // the left partition, greater elements in the right partition. We do not have + // to // recurse on the left partition, since it's sorted (all equal). if (!leftmost && !(Reads.compareValues(array[begin - 1], array[begin]) < 0)) { begin = this.pdqPartLeft(array, begin, end) + 1; @@ -508,63 +624,65 @@ protected void pdqLoop(int[] array, int begin, int end, boolean Branchless, int } // Partition and get results. - PDQPair partResult = - Branchless ? this.pdqPartRightBranchless(array, begin, end) - : this.pdqPartRight(array, begin, end); - - int pivotPos = partResult.getPivotPosition(); - boolean alreadyParted = partResult.getPresortBool(); - - // Check for a highly unbalanced partition. - int leftSize = pivotPos - begin; - int rightSize = end - (pivotPos + 1); - boolean highUnbalance = leftSize < size / 8 || rightSize < size / 8; - - // If we got a highly unbalanced partition, we shuffle elements to break many patterns. - if (highUnbalance) { - // If we had too many bad partitions, switch to heapsort to guarantee O(n log n). - if (--badAllowed == 0) { - heapSorter.customHeapSort(array, begin, end, 1); - return; - } - - if (leftSize >= insertSortThreshold) { - Writes.swap(array, begin, begin + leftSize / 4, 65, true, false); - Writes.swap(array, pivotPos-1, pivotPos - leftSize / 4, 65, true, false); - - if (leftSize > nintherThreshold) { - Writes.swap(array, begin+1, begin + (leftSize / 4 + 1), 65, true, false); - Writes.swap(array, begin+2, begin + (leftSize / 4 + 2), 65, true, false); - Writes.swap(array, pivotPos-2, pivotPos - (leftSize / 4 + 1), 65, true, false); - Writes.swap(array, pivotPos-3, pivotPos - (leftSize / 4 + 2), 65, true, false); - } - } - - if (rightSize >= insertSortThreshold) { - Writes.swap(array, pivotPos+1, pivotPos + (1 + rightSize / 4), 65, true, false); - Writes.swap(array, end-1, end - rightSize / 4, 65, true, false); - - if (rightSize > nintherThreshold) { - Writes.swap(array, pivotPos+2, pivotPos + (2 + rightSize / 4), 65, true, false); - Writes.swap(array, pivotPos+3, pivotPos + (3 + rightSize / 4), 65, true, false); - Writes.swap(array, end-2, end - (1 + rightSize / 4), 65, true, false); - Writes.swap(array, end-3, end - (2 + rightSize / 4), 65, true, false); - } - } - Highlights.clearMark(2); - } else { - // If we were decently balanced and we tried to sort an already partitioned - // sequence, try to use insertion sort. - if (alreadyParted && pdqPartialInsertSort(array, begin, pivotPos) - && pdqPartialInsertSort(array, pivotPos + 1, end)) - return; + PDQPair partResult = Branchless ? this.pdqPartRightBranchless(array, begin, end) + : this.pdqPartRight(array, begin, end); + + int pivotPos = partResult.getPivotPosition(); + boolean alreadyParted = partResult.getPresortBool(); + + // Check for a highly unbalanced partition. + int leftSize = pivotPos - begin; + int rightSize = end - (pivotPos + 1); + boolean highUnbalance = leftSize < size / 8 || rightSize < size / 8; + + // If we got a highly unbalanced partition, we shuffle elements to break many + // patterns. + if (highUnbalance) { + // If we had too many bad partitions, switch to heapsort to guarantee O(n log + // n). + if (--badAllowed == 0) { + heapSorter.customHeapSort(array, begin, end, 1); + return; + } + + if (leftSize >= insertSortThreshold) { + Writes.swap(array, begin, begin + leftSize / 4, 65, true, false); + Writes.swap(array, pivotPos - 1, pivotPos - leftSize / 4, 65, true, false); + + if (leftSize > nintherThreshold) { + Writes.swap(array, begin + 1, begin + (leftSize / 4 + 1), 65, true, false); + Writes.swap(array, begin + 2, begin + (leftSize / 4 + 2), 65, true, false); + Writes.swap(array, pivotPos - 2, pivotPos - (leftSize / 4 + 1), 65, true, false); + Writes.swap(array, pivotPos - 3, pivotPos - (leftSize / 4 + 2), 65, true, false); } + } + + if (rightSize >= insertSortThreshold) { + Writes.swap(array, pivotPos + 1, pivotPos + (1 + rightSize / 4), 65, true, false); + Writes.swap(array, end - 1, end - rightSize / 4, 65, true, false); + + if (rightSize > nintherThreshold) { + Writes.swap(array, pivotPos + 2, pivotPos + (2 + rightSize / 4), 65, true, false); + Writes.swap(array, pivotPos + 3, pivotPos + (3 + rightSize / 4), 65, true, false); + Writes.swap(array, end - 2, end - (1 + rightSize / 4), 65, true, false); + Writes.swap(array, end - 3, end - (2 + rightSize / 4), 65, true, false); + } + } + Highlights.clearMark(2); + } else { + // If we were decently balanced and we tried to sort an already partitioned + // sequence, try to use insertion sort. + if (alreadyParted && pdqPartialInsertSort(array, begin, pivotPos) + && pdqPartialInsertSort(array, pivotPos + 1, end)) + return; + } - // Sort the left partition first using recursion and do tail recursion elimination for - // the right-hand partition. - this.pdqLoop(array, begin, pivotPos, Branchless, badAllowed); - begin = pivotPos + 1; - leftmost = false; + // Sort the left partition first using recursion and do tail recursion + // elimination for + // the right-hand partition. + this.pdqLoop(array, begin, pivotPos, Branchless, badAllowed); + begin = pivotPos + 1; + leftmost = false; } } } diff --git a/src/main/java/io/github/arrayv/sorts/templates/QuadSorting.java b/src/main/java/io/github/arrayv/sorts/templates/QuadSorting.java index 3673a391..15ac227c 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/QuadSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/QuadSorting.java @@ -47,97 +47,97 @@ public QuadSortBase(ArrayVisualizer arrayVisualizer) { } void swapTwo(int[] array, int start) { - if(Reads.compareIndices(array, start, start+1, 1, true) > 0) - Writes.swap(array, start, start+1, 1, true, false); + if (Reads.compareIndices(array, start, start + 1, 1, true) > 0) + Writes.swap(array, start, start + 1, 1, true, false); } void swapThree(int[] array, int start) { - if(Reads.compareIndices(array, start, start+1, 1, true) > 0) { - if(Reads.compareIndices(array, start, start+2, 1, true) <= 0) - Writes.swap(array, start, start+1, 1, true, false); + if (Reads.compareIndices(array, start, start + 1, 1, true) > 0) { + if (Reads.compareIndices(array, start, start + 2, 1, true) <= 0) + Writes.swap(array, start, start + 1, 1, true, false); - else if(Reads.compareIndices(array, start+1, start+2, 1, true) > 0) - Writes.swap(array, start, start+2, 1, true, false); + else if (Reads.compareIndices(array, start + 1, start + 2, 1, true) > 0) + Writes.swap(array, start, start + 2, 1, true, false); else { int temp = array[start]; - Writes.write(array, start, array[start+1], 1, true, false); - Writes.write(array, start+1, array[start+2], 1, true, false); - Writes.write(array, start+2, temp, 1, true, false); + Writes.write(array, start, array[start + 1], 1, true, false); + Writes.write(array, start + 1, array[start + 2], 1, true, false); + Writes.write(array, start + 2, temp, 1, true, false); } } - else if(Reads.compareIndices(array, start+1, start+2, 1, true) > 0) { - if(Reads.compareIndices(array, start, start+2, 1, true) > 0) { - int temp = array[start+2]; - Writes.write(array, start+2, array[start+1], 1, true, false); - Writes.write(array, start+1, array[start], 1, true, false); + else if (Reads.compareIndices(array, start + 1, start + 2, 1, true) > 0) { + if (Reads.compareIndices(array, start, start + 2, 1, true) > 0) { + int temp = array[start + 2]; + Writes.write(array, start + 2, array[start + 1], 1, true, false); + Writes.write(array, start + 1, array[start], 1, true, false); Writes.write(array, start, temp, 1, true, false); } else { - Writes.swap(array, start+2, start+1, 1, true, false); + Writes.swap(array, start + 2, start + 1, 1, true, false); } } } void swapFour(int[] array, int start) { - if(Reads.compareIndices(array, start, start+1, 1, true) > 0) - Writes.swap(array, start, start+1, 1, true, false); + if (Reads.compareIndices(array, start, start + 1, 1, true) > 0) + Writes.swap(array, start, start + 1, 1, true, false); - if(Reads.compareIndices(array, start+2, start+3, 1, true) > 0) - Writes.swap(array, start+2, start+3, 1, true, false); + if (Reads.compareIndices(array, start + 2, start + 3, 1, true) > 0) + Writes.swap(array, start + 2, start + 3, 1, true, false); - if(Reads.compareIndices(array, start+1, start+2, 1, true) > 0) { - if(Reads.compareIndices(array, start, start+2, 1, true) <= 0) { - if(Reads.compareIndices(array, start+1, start+3, 1, true) <= 0) - Writes.swap(array, start+1, start+2, 1, true, false); + if (Reads.compareIndices(array, start + 1, start + 2, 1, true) > 0) { + if (Reads.compareIndices(array, start, start + 2, 1, true) <= 0) { + if (Reads.compareIndices(array, start + 1, start + 3, 1, true) <= 0) + Writes.swap(array, start + 1, start + 2, 1, true, false); else { - int temp = array[start+1]; - Writes.write(array, start+1, array[start+2], 1, true, false); - Writes.write(array, start+2, array[start+3], 1, true, false); - Writes.write(array, start+3, temp, 1, true, false); + int temp = array[start + 1]; + Writes.write(array, start + 1, array[start + 2], 1, true, false); + Writes.write(array, start + 2, array[start + 3], 1, true, false); + Writes.write(array, start + 3, temp, 1, true, false); } } - else if(Reads.compareIndices(array, start, start+3, 1, true) > 0) { - Writes.swap(array, start+1, start+3, 1, true, false); - Writes.swap(array, start, start+2, 1, true, false); + else if (Reads.compareIndices(array, start, start + 3, 1, true) > 0) { + Writes.swap(array, start + 1, start + 3, 1, true, false); + Writes.swap(array, start, start + 2, 1, true, false); } - else if(Reads.compareIndices(array, start+1, start+3, 1, true) <= 0) { - int temp = array[start+1]; - Writes.write(array, start+1, array[start], 1, true, false); - Writes.write(array, start, array[start+2], 1, true, false); - Writes.write(array, start+2, temp, 1, true, false); + else if (Reads.compareIndices(array, start + 1, start + 3, 1, true) <= 0) { + int temp = array[start + 1]; + Writes.write(array, start + 1, array[start], 1, true, false); + Writes.write(array, start, array[start + 2], 1, true, false); + Writes.write(array, start + 2, temp, 1, true, false); } else { - int temp = array[start+1]; - Writes.write(array, start+1, array[start], 1, true, false); - Writes.write(array, start, array[start+2], 1, true, false); - Writes.write(array, start+2, array[start+3], 1, true, false); - Writes.write(array, start+3, temp, 1, true, false); + int temp = array[start + 1]; + Writes.write(array, start + 1, array[start], 1, true, false); + Writes.write(array, start, array[start + 2], 1, true, false); + Writes.write(array, start + 2, array[start + 3], 1, true, false); + Writes.write(array, start + 3, temp, 1, true, false); } } } void swapFive(int[] array, int start) { - end = start+4; + end = start + 4; pta = end++; ptt = pta--; - if(Reads.compareIndices(array, pta, ptt, 1, true) > 0) { + if (Reads.compareIndices(array, pta, ptt, 1, true) > 0) { key = array[ptt]; Writes.write(array, ptt--, array[pta--], 1, true, false); - if(pta > start && Reads.compareValues(array[pta-1], key) > 0) { + if (pta > start && Reads.compareValues(array[pta - 1], key) > 0) { Writes.write(array, ptt--, array[pta--], 1, true, false); Writes.write(array, ptt--, array[pta--], 1, true, false); } - if(pta >= start && Reads.compareValues(array[pta], key) > 0) { + if (pta >= start && Reads.compareValues(array[pta], key) > 0) { Writes.write(array, ptt--, array[pta--], 1, true, false); } @@ -149,21 +149,21 @@ void tailSwapEight(int[] array, int start) { pta = end++; ptt = pta--; - if(Reads.compareIndices(array, pta, ptt, 1, true) > 0) { + if (Reads.compareIndices(array, pta, ptt, 1, true) > 0) { key = array[ptt]; Writes.write(array, ptt--, array[pta--], 1, true, false); - if(Reads.compareValues(array[pta-2], key) > 0) { - for(int i=0; i<3; i++) + if (Reads.compareValues(array[pta - 2], key) > 0) { + for (int i = 0; i < 3; i++) Writes.write(array, ptt--, array[pta--], 1, true, false); } - if(pta > start && Reads.compareValues(array[pta-1], key) > 0) { + if (pta > start && Reads.compareValues(array[pta - 1], key) > 0) { Writes.write(array, ptt--, array[pta--], 1, true, false); Writes.write(array, ptt--, array[pta--], 1, true, false); } - if(pta >= start && Reads.compareValues(array[pta], key) > 0) { + if (pta >= start && Reads.compareValues(array[pta], key) > 0) { Writes.write(array, ptt--, array[pta--], 1, true, false); } @@ -201,71 +201,71 @@ public QuadSorting(ArrayVisualizer arrayVisualizer) { protected void tailSwap(int[] array, int start, int nmemb) { int mid, top, offset; - switch(nmemb) { - case 0: - case 1: - return; + switch (nmemb) { + case 0: + case 1: + return; - case 2: - qs.swapTwo(array, start); - return; + case 2: + qs.swapTwo(array, start); + return; - case 3: - qs.swapThree(array, start); - return; + case 3: + qs.swapThree(array, start); + return; - case 4: - qs.swapFour(array, start); - return; + case 4: + qs.swapFour(array, start); + return; - case 5: - qs.swapFour(array, start); - qs.swapFive(array, start); - return; + case 5: + qs.swapFour(array, start); + qs.swapFive(array, start); + return; - case 6: - qs.swapFour(array, start); - qs.swapSix(array, start); - return; + case 6: + qs.swapFour(array, start); + qs.swapSix(array, start); + return; - case 7: - qs.swapFour(array, start); - qs.swapSeven(array, start); - return; + case 7: + qs.swapFour(array, start); + qs.swapSeven(array, start); + return; - case 8: - qs.swapFour(array, start); - qs.swapEight(array, start); - return; + case 8: + qs.swapFour(array, start); + qs.swapEight(array, start); + return; } qs.swapFour(array, start); qs.swapEight(array, start); - qs.end = start+8; + qs.end = start + 8; offset = 8; - while(offset < nmemb) { + while (offset < nmemb) { top = offset++; qs.pta = qs.end++; qs.ptt = qs.pta--; - if(Reads.compareIndices(array, qs.pta, qs.ptt, 1, true) <= 0) + if (Reads.compareIndices(array, qs.pta, qs.ptt, 1, true) <= 0) continue; int temp = array[qs.ptt]; - while(top > 1) { - mid = top/2; - if(Reads.compareValues(array[qs.pta-mid], temp) > 0) + while (top > 1) { + mid = top / 2; + if (Reads.compareValues(array[qs.pta - mid], temp) > 0) qs.pta -= mid; top -= mid; } // memmove(pta+1, pta, (ptt-pta) * sizeof(VAR)); - for(int i=qs.ptt; i > qs.pta; i--) - Writes.write(array, i, array[i-1], 1, true, false); + for (int i = qs.ptt; i > qs.pta; i--) + Writes.write(array, i, array[i - 1], 1, true, false); Writes.write(array, qs.pta, temp, 1, true, false); } @@ -280,13 +280,13 @@ void parityMerge4(int[] from, int start, int[] dest, int auxOffset) { int auxP = auxOffset; ptl = start; - ptr = start+4; + ptr = start + 4; - for(int i=0; i<3; i++) { + for (int i = 0; i < 3; i++) { Highlights.markArray(2, ptl); Highlights.markArray(3, ptr); - if(Reads.compareValues(from[ptl], from[ptr]) <= 0) + if (Reads.compareValues(from[ptl], from[ptr]) <= 0) Writes.write(dest, auxP++, from[ptl++], 1, true, true); else @@ -296,21 +296,21 @@ void parityMerge4(int[] from, int start, int[] dest, int auxOffset) { Highlights.markArray(2, ptl); Highlights.markArray(3, ptr); - if(Reads.compareValues(from[ptl], from[ptr]) <= 0) + if (Reads.compareValues(from[ptl], from[ptr]) <= 0) Writes.write(dest, auxP, from[ptl], 1, true, true); else Writes.write(dest, auxP, from[ptr], 1, true, true); - ptl = start+3; - ptr = start+7; + ptl = start + 3; + ptr = start + 7; auxP += 4; - for(int i=0; i<3; i++) { + for (int i = 0; i < 3; i++) { Highlights.markArray(2, ptl); Highlights.markArray(3, ptr); - if(Reads.compareValues(from[ptl], from[ptr]) > 0) + if (Reads.compareValues(from[ptl], from[ptr]) > 0) Writes.write(dest, auxP--, from[ptl--], 1, true, true); else @@ -320,7 +320,7 @@ void parityMerge4(int[] from, int start, int[] dest, int auxOffset) { Highlights.markArray(2, ptl); Highlights.markArray(3, ptr); - if(Reads.compareValues(from[ptl], from[ptr]) > 0) + if (Reads.compareValues(from[ptl], from[ptr]) > 0) Writes.write(dest, auxP, from[ptl], 1, true, true); else @@ -337,11 +337,11 @@ void parityMerge8(int[] from, int start, int[] dest) { ptl = 0; ptr = 8; - for(int i=0; i<7; i++) { + for (int i = 0; i < 7; i++) { Highlights.markArray(2, ptl); Highlights.markArray(3, ptr); - if(Reads.compareValues(from[ptl], from[ptr]) <= 0) + if (Reads.compareValues(from[ptl], from[ptr]) <= 0) Writes.write(dest, mainP++, from[ptl++], 1, true, false); else @@ -351,7 +351,7 @@ void parityMerge8(int[] from, int start, int[] dest) { Highlights.markArray(2, ptl); Highlights.markArray(3, ptr); - if(Reads.compareValues(from[ptl], from[ptr]) <= 0) + if (Reads.compareValues(from[ptl], from[ptr]) <= 0) Writes.write(dest, mainP, from[ptl], 1, true, false); else @@ -361,11 +361,11 @@ void parityMerge8(int[] from, int start, int[] dest) { ptr = 15; mainP += 8; - for(int i=0; i<7; i++) { + for (int i = 0; i < 7; i++) { Highlights.markArray(2, ptl); Highlights.markArray(3, ptr); - if(Reads.compareValues(from[ptl], from[ptr]) > 0) + if (Reads.compareValues(from[ptl], from[ptr]) > 0) Writes.write(dest, mainP--, from[ptl--], 1, true, false); else @@ -375,7 +375,7 @@ void parityMerge8(int[] from, int start, int[] dest) { Highlights.markArray(2, ptl); Highlights.markArray(3, ptr); - if(Reads.compareValues(from[ptl], from[ptr]) > 0) + if (Reads.compareValues(from[ptl], from[ptr]) > 0) Writes.write(dest, mainP, from[ptl], 1, true, false); else @@ -387,18 +387,19 @@ void parityMerge8(int[] from, int start, int[] dest) { // merge 4 4 4 4 into 16 using the above two methods // with analyzing already sorted runs void parityMerge16(int[] array, int start, int[] aux) { - if(Reads.compareIndices(array, start+3, start+4, 4, true) <= 0 && - Reads.compareIndices(array, start+7, start+8, 4, true) <= 0 && - Reads.compareIndices(array, start+11, start+12, 4, true) <= 0) + if (Reads.compareIndices(array, start + 3, start + 4, 4, true) <= 0 && + Reads.compareIndices(array, start + 7, start + 8, 4, true) <= 0 && + Reads.compareIndices(array, start + 11, start + 12, 4, true) <= 0) return; this.parityMerge4(array, start, aux, 0); - this.parityMerge4(array, start+8, aux, 8); + this.parityMerge4(array, start + 8, aux, 8); this.parityMerge8(aux, start, array); } - // (partially) writes second block into aux array and then merge with first block + // (partially) writes second block into aux array and then merge with first + // block void partialBackwardMerge(int[] array, int[] aux, int start, int nmemb, int block) { int r, m, e, s; // right, middle, end, swap @@ -407,63 +408,64 @@ void partialBackwardMerge(int[] array, int[] aux, int start, int nmemb, int bloc e = start + nmemb - 1; r = m--; - if(Reads.compareIndices(array, m, r, 1, true) <= 0) + if (Reads.compareIndices(array, m, r, 1, true) <= 0) return; - while(Reads.compareIndices(array, m, e, 1, true) <= 0) + while (Reads.compareIndices(array, m, e, 1, true) <= 0) e--; Highlights.clearAllMarks(); - for(int i=r; i < r+(e-m); i++) { - Writes.write(aux, i-r, array[i], 1, false, true); + for (int i = r; i < r + (e - m); i++) { + Writes.write(aux, i - r, array[i], 1, false, true); Highlights.markArray(1, i); } - s = e-r; + s = e - r; Writes.write(array, e--, array[m--], 1, true, false); - if(Reads.compareValues(array[start], aux[0]) <= 0) { + if (Reads.compareValues(array[start], aux[0]) <= 0) { do { - while(Reads.compareValues(array[m], aux[s]) > 0) { + while (Reads.compareValues(array[m], aux[s]) > 0) { Highlights.markArray(2, m); Writes.write(array, e--, array[m--], 1, true, false); } Highlights.markArray(2, m); Writes.write(array, e--, aux[s--], 1, true, false); - } while(s >= 0); + } while (s >= 0); } else { do { - while(Reads.compareValues(array[m], aux[s]) <= 0) { + while (Reads.compareValues(array[m], aux[s]) <= 0) { Highlights.markArray(2, m); Writes.write(array, e--, aux[s--], 1, true, false); } Highlights.markArray(2, m); Writes.write(array, e--, array[m--], 1, true, false); - } while(m >= start); + } while (m >= start); - do Writes.write(array, e--, aux[s--], 1, true, false); while (s >= 0); + do + Writes.write(array, e--, aux[s--], 1, true, false); + while (s >= 0); } } - // bottom up merge sort, performs on array size from 16 to 255 after parity merge + // bottom up merge sort, performs on array size from 16 to 255 after parity + // merge // or performs after quad merge on array size from 256 void tailMerge(int[] array, int[] aux, int start, int nmemb, int block) { int pta, pte; // different from qs.pta pte = start + nmemb; - while(block < nmemb) { + while (block < nmemb) { pta = start; - for (pta = start ; pta + block < pte ; pta += block * 2) - { - if (pta + block * 2 < pte) - { - this.partialBackwardMerge(array, aux, pta, block*2, block); + for (pta = start; pta + block < pte; pta += block * 2) { + if (pta + block * 2 < pte) { + this.partialBackwardMerge(array, aux, pta, block * 2, block); continue; } @@ -483,23 +485,22 @@ void forwardMerge(int[] dest, int[] from, int start, int auxStart, int block, bo int mergeP = toAux ? auxStart : start; l = toAux ? start : auxStart; - r = toAux ? (start+block) : (auxStart+block); + r = toAux ? (start + block) : (auxStart + block); m = r; e = r + block; Highlights.clearAllMarks(); - if(toAux) { - Highlights.markArray(1, r-1); - Highlights.markArray(2, e-1); + if (toAux) { + Highlights.markArray(1, r - 1); + Highlights.markArray(2, e - 1); Delays.sleep(1); } - if(Reads.compareValues(from[r-1], from[e-1]) <= 0) { - leftFirst: - do { - for(int i=0; i<3; i++) { - if(Reads.compareValues(from[l], from[r]) <= 0) { - if(toAux) { + if (Reads.compareValues(from[r - 1], from[e - 1]) <= 0) { + leftFirst: do { + for (int i = 0; i < 3; i++) { + if (Reads.compareValues(from[l], from[r]) <= 0) { + if (toAux) { Highlights.markArray(1, l); Highlights.markArray(2, r); Delays.sleep(1); @@ -508,31 +509,30 @@ void forwardMerge(int[] dest, int[] from, int start, int auxStart, int block, bo continue leftFirst; } - if(toAux) { + if (toAux) { Highlights.markArray(1, l); Highlights.markArray(2, r); Delays.sleep(1); } Writes.write(dest, mergeP++, from[r++], toAux ? 0 : 1, !toAux, toAux); } - } while(l < m); + } while (l < m); do { - if(toAux) { - Highlights.markArray(1, l-1); + if (toAux) { + Highlights.markArray(1, l - 1); Highlights.markArray(2, r); Delays.sleep(1); } Writes.write(dest, mergeP++, from[r++], toAux ? 0 : 1, !toAux, toAux); - } while(r < e); + } while (r < e); } else { - rightFirst: - do { - for(int i=0; i<3; i++) { - if(Reads.compareValues(from[l], from[r]) > 0) { - if(toAux) { + rightFirst: do { + for (int i = 0; i < 3; i++) { + if (Reads.compareValues(from[l], from[r]) > 0) { + if (toAux) { Highlights.markArray(1, l); Highlights.markArray(2, r); Delays.sleep(1); @@ -541,48 +541,48 @@ void forwardMerge(int[] dest, int[] from, int start, int auxStart, int block, bo continue rightFirst; } - if(toAux) { + if (toAux) { Highlights.markArray(1, l); Highlights.markArray(2, r); Delays.sleep(1); } Writes.write(dest, mergeP++, from[l++], toAux ? 0 : 1, !toAux, toAux); } - } while(r < e); + } while (r < e); do { - if(toAux) { + if (toAux) { Highlights.markArray(1, l); - Highlights.markArray(2, r-1); + Highlights.markArray(2, r - 1); Delays.sleep(1); } Writes.write(dest, mergeP++, from[l++], toAux ? 0 : 1, !toAux, toAux); - } while(l < m); + } while (l < m); } } // main memory: [A][B][C][D] - // swap memory: [A B] step 1 - // swap memory: [A B][C D] step 2 - // main memory: [A B C D] step 3 + // swap memory: [A B] step 1 + // swap memory: [A B][C D] step 2 + // main memory: [A B C D] step 3 // merge 4 blocks into 1 block like above comment void quadMergeBlock(int[] array, int start, int[] aux, int block) { int pts, c, cMax; - int blockX2 = block*2; + int blockX2 = block * 2; cMax = start + block; // if first 2 blocks are sorted - if(Reads.compareIndices(array, cMax-1, cMax, 20, true) <= 0) { + if (Reads.compareIndices(array, cMax - 1, cMax, 20, true) <= 0) { cMax += blockX2; // if second 2 blocks are sorted - if(Reads.compareIndices(array, cMax-1, cMax, 20, true) <= 0) { + if (Reads.compareIndices(array, cMax - 1, cMax, 20, true) <= 0) { cMax -= block; // ...and entire 4 blocks are sorted - if(Reads.compareIndices(array, cMax-1, cMax, 20, true) <= 0) { + if (Reads.compareIndices(array, cMax - 1, cMax, 20, true) <= 0) { return; } @@ -591,16 +591,16 @@ void quadMergeBlock(int[] array, int start, int[] aux, int block) { do { Writes.write(aux, pts, array[c++], 1, false, true); - Highlights.markArray(1, pts+start); + Highlights.markArray(1, pts + start); pts++; - } while(c < cMax); // step 1 + } while (c < cMax); // step 1 cMax = c + blockX2; do { Writes.write(aux, pts, array[c++], 1, false, true); - Highlights.markArray(1, pts+start); + Highlights.markArray(1, pts + start); pts++; - } while(c < cMax); // step 2 + } while (c < cMax); // step 2 this.forwardMerge(array, aux, start, 0, blockX2, false); // step 3 return; @@ -612,20 +612,21 @@ void quadMergeBlock(int[] array, int start, int[] aux, int block) { do { Writes.write(aux, pts, array[c++], 1, false, true); - Highlights.markArray(1, pts+start); + Highlights.markArray(1, pts + start); pts++; - } while(c < cMax); // step 1 + } while (c < cMax); // step 1 } else this.forwardMerge(aux, array, start, 0, block, true); // step 1 - this.forwardMerge(aux, array, start+blockX2, blockX2, block, true); // step 2 + this.forwardMerge(aux, array, start + blockX2, blockX2, block, true); // step 2 this.forwardMerge(array, aux, start, 0, blockX2, false); // step 3 } // quad merges the entire array - // this fallbacks to tail merge if (current block size)*2 is greater than array size + // this fallbacks to tail merge if (current block size)*2 is greater than array + // size void quadMerge(int[] array, int[] aux, int start, int nmemb, int block) { int pta, pte; // different from qs.pta @@ -633,19 +634,19 @@ void quadMerge(int[] array, int[] aux, int start, int nmemb, int block) { pte = start + nmemb; block *= 4; - while(block*2 <= nmemb) { + while (block * 2 <= nmemb) { pta = start; do { - this.quadMergeBlock(array, pta, aux, block/4); + this.quadMergeBlock(array, pta, aux, block / 4); pta += block; - } while(pta+block <= pte); + } while (pta + block <= pte); - this.tailMerge(array, aux, pta, pte-pta, block/4); + this.tailMerge(array, aux, pta, pte - pta, block / 4); block *= 4; } - this.tailMerge(array, aux, start, nmemb, block/4); + this.tailMerge(array, aux, start, nmemb, block / 4); } // pre-sorting process; basically 4-item sorting network @@ -658,176 +659,175 @@ int quadSwap(int[] array, int start, int nmemb) { int pta, pts = 0, ptt = 0, temp = 0; pta = start; - count = nmemb/4; - - swapper: - while(count-- > 0) { - while(true) { - if(Reads.compareIndices(array, pta, pta+1, 1, true) > 0) { - if(Reads.compareIndices(array, pta+2, pta+3, 1, true) > 0) { - if(Reads.compareIndices(array, pta+1, pta+2, 1, true) > 0) { + count = nmemb / 4; + + swapper: while (count-- > 0) { + while (true) { + if (Reads.compareIndices(array, pta, pta + 1, 1, true) > 0) { + if (Reads.compareIndices(array, pta + 2, pta + 3, 1, true) > 0) { + if (Reads.compareIndices(array, pta + 1, pta + 2, 1, true) > 0) { pts = pta; pta += 4; break; } - Writes.swap(array, pta+2, pta+3, 1, true, false); + Writes.swap(array, pta + 2, pta + 3, 1, true, false); } - Writes.swap(array, pta, pta+1, 1, true, false); + Writes.swap(array, pta, pta + 1, 1, true, false); } - else if(Reads.compareIndices(array, pta+2, pta+3, 1, true) > 0) - Writes.swap(array, pta+2, pta+3, 1, true, false); + else if (Reads.compareIndices(array, pta + 2, pta + 3, 1, true) > 0) + Writes.swap(array, pta + 2, pta + 3, 1, true, false); - if(Reads.compareIndices(array, pta+1, pta+2, 1, true) > 0) { - if(Reads.compareIndices(array, pta, pta+2, 1, true) <= 0) { - if(Reads.compareIndices(array, pta+1, pta+3, 1, true) <= 0) - Writes.swap(array, pta+1, pta+2, 1, true, false); + if (Reads.compareIndices(array, pta + 1, pta + 2, 1, true) > 0) { + if (Reads.compareIndices(array, pta, pta + 2, 1, true) <= 0) { + if (Reads.compareIndices(array, pta + 1, pta + 3, 1, true) <= 0) + Writes.swap(array, pta + 1, pta + 2, 1, true, false); else { - temp = array[pta+1]; - Writes.write(array, pta+1, array[pta+2], 1, true, false); - Writes.write(array, pta+2, array[pta+3], 1, true, false); - Writes.write(array, pta+3, temp, 1, true, false); + temp = array[pta + 1]; + Writes.write(array, pta + 1, array[pta + 2], 1, true, false); + Writes.write(array, pta + 2, array[pta + 3], 1, true, false); + Writes.write(array, pta + 3, temp, 1, true, false); } } - else if(Reads.compareIndices(array, pta, pta+3, 1, true) > 0) { - Writes.swap(array, pta+1, pta+3, 1, true, false); - Writes.swap(array, pta, pta+2, 1, true, false); + else if (Reads.compareIndices(array, pta, pta + 3, 1, true) > 0) { + Writes.swap(array, pta + 1, pta + 3, 1, true, false); + Writes.swap(array, pta, pta + 2, 1, true, false); } - else if(Reads.compareIndices(array, pta+1, pta+3, 1, true) <= 0) { - temp = array[pta+1]; - Writes.write(array, pta+1, array[pta], 1, true, false); - Writes.write(array, pta, array[pta+2], 1, true, false); - Writes.write(array, pta+2, temp, 1, true, false); + else if (Reads.compareIndices(array, pta + 1, pta + 3, 1, true) <= 0) { + temp = array[pta + 1]; + Writes.write(array, pta + 1, array[pta], 1, true, false); + Writes.write(array, pta, array[pta + 2], 1, true, false); + Writes.write(array, pta + 2, temp, 1, true, false); } else { - temp = array[pta+1]; - Writes.write(array, pta+1, array[pta], 1, true, false); - Writes.write(array, pta, array[pta+2], 1, true, false); - Writes.write(array, pta+2, array[pta+3], 1, true, false); - Writes.write(array, pta+3, temp, 1, true, false); + temp = array[pta + 1]; + Writes.write(array, pta + 1, array[pta], 1, true, false); + Writes.write(array, pta, array[pta + 2], 1, true, false); + Writes.write(array, pta + 2, array[pta + 3], 1, true, false); + Writes.write(array, pta + 3, temp, 1, true, false); } } pta += 4; continue swapper; } - while(true) { - if(count-- > 0) { - if(Reads.compareIndices(array, pta, pta+1, 1, true) > 0) { - if(Reads.compareIndices(array, pta+2, pta+3, 1, true) > 0) { - if(Reads.compareIndices(array, pta+1, pta+2, 1, true) > 0) { - if(Reads.compareIndices(array, pta-1, pta, 1, true) > 0) { + while (true) { + if (count-- > 0) { + if (Reads.compareIndices(array, pta, pta + 1, 1, true) > 0) { + if (Reads.compareIndices(array, pta + 2, pta + 3, 1, true) > 0) { + if (Reads.compareIndices(array, pta + 1, pta + 2, 1, true) > 0) { + if (Reads.compareIndices(array, pta - 1, pta, 1, true) > 0) { pta += 4; continue; } } - Writes.swap(array, pta+2, pta+3, 1, true, false); + Writes.swap(array, pta + 2, pta + 3, 1, true, false); } - Writes.swap(array, pta, pta+1, 1, true, false); + Writes.swap(array, pta, pta + 1, 1, true, false); } - else if(Reads.compareIndices(array, pta+2, pta+3, 1, true) > 0) - Writes.swap(array, pta+2, pta+3, 1, true, false); + else if (Reads.compareIndices(array, pta + 2, pta + 3, 1, true) > 0) + Writes.swap(array, pta + 2, pta + 3, 1, true, false); - if(Reads.compareIndices(array, pta+1, pta+2, 1, true) > 0) { - if(Reads.compareIndices(array, pta, pta+2, 1, true) <= 0) { - if(Reads.compareIndices(array, pta+1, pta+3, 1, true) <= 0) - Writes.swap(array, pta+1, pta+2, 1, true, false); + if (Reads.compareIndices(array, pta + 1, pta + 2, 1, true) > 0) { + if (Reads.compareIndices(array, pta, pta + 2, 1, true) <= 0) { + if (Reads.compareIndices(array, pta + 1, pta + 3, 1, true) <= 0) + Writes.swap(array, pta + 1, pta + 2, 1, true, false); else { - temp = array[pta+1]; - Writes.write(array, pta+1, array[pta+2], 1, true, false); - Writes.write(array, pta+2, array[pta+3], 1, true, false); - Writes.write(array, pta+3, temp, 1, true, false); + temp = array[pta + 1]; + Writes.write(array, pta + 1, array[pta + 2], 1, true, false); + Writes.write(array, pta + 2, array[pta + 3], 1, true, false); + Writes.write(array, pta + 3, temp, 1, true, false); } } - else if(Reads.compareIndices(array, pta, pta+3, 1, true) > 0) { - Writes.swap(array, pta, pta+2, 1, true, false); - Writes.swap(array, pta+1, pta+3, 1, true, false); + else if (Reads.compareIndices(array, pta, pta + 3, 1, true) > 0) { + Writes.swap(array, pta, pta + 2, 1, true, false); + Writes.swap(array, pta + 1, pta + 3, 1, true, false); } - else if(Reads.compareIndices(array, pta+1, pta+3, 1, true) <= 0) { + else if (Reads.compareIndices(array, pta + 1, pta + 3, 1, true) <= 0) { temp = array[pta]; - Writes.write(array, pta, array[pta+2], 1, true, false); - Writes.write(array, pta+2, array[pta+1], 1, true, false); - Writes.write(array, pta+1, temp, 1, true, false); + Writes.write(array, pta, array[pta + 2], 1, true, false); + Writes.write(array, pta + 2, array[pta + 1], 1, true, false); + Writes.write(array, pta + 1, temp, 1, true, false); } else { temp = array[pta]; - Writes.write(array, pta, array[pta+2], 1, true, false); - Writes.write(array, pta+2, array[pta+3], 1, true, false); - Writes.write(array, pta+3, array[pta+1], 1, true, false); - Writes.write(array, pta+1, temp, 1, true, false); + Writes.write(array, pta, array[pta + 2], 1, true, false); + Writes.write(array, pta + 2, array[pta + 3], 1, true, false); + Writes.write(array, pta + 3, array[pta + 1], 1, true, false); + Writes.write(array, pta + 1, temp, 1, true, false); } } - ptt = pta-1; - reverse = (ptt-pts)/2; + ptt = pta - 1; + reverse = (ptt - pts) / 2; Writes.changeReversals(1); do { Writes.swap(array, pts++, ptt--, 1, true, false); - } while(reverse-- > 0); + } while (reverse-- > 0); pta += 4; continue swapper; } - if(pts == start) { - switch(nmemb % 4) { - case 3: - if(Reads.compareIndices(array, pta+1, pta+2, 1, true) <= 0) - break; + if (pts == start) { + switch (nmemb % 4) { + case 3: + if (Reads.compareIndices(array, pta + 1, pta + 2, 1, true) <= 0) + break; - case 2: - if(Reads.compareIndices(array, pta, pta+1, 1, true) <= 0) - break; + case 2: + if (Reads.compareIndices(array, pta, pta + 1, 1, true) <= 0) + break; - case 1: - if(Reads.compareIndices(array, pta-1, pta, 1, true) <= 0) - break; + case 1: + if (Reads.compareIndices(array, pta - 1, pta, 1, true) <= 0) + break; - case 0: - ptt = pts+nmemb-1; - reverse = (ptt-pts)/2; + case 0: + ptt = pts + nmemb - 1; + reverse = (ptt - pts) / 2; - Writes.changeReversals(1); - do { - Writes.swap(array, pts++, ptt--, 1, true, false); - } while(reverse-- > 0); + Writes.changeReversals(1); + do { + Writes.swap(array, pts++, ptt--, 1, true, false); + } while (reverse-- > 0); - Writes.deleteExternalArray(swap); - return 1; + Writes.deleteExternalArray(swap); + return 1; } } ptt = pta - 1; - reverse = (ptt-pts)/2; + reverse = (ptt - pts) / 2; Writes.changeReversals(1); do { Writes.swap(array, pts++, ptt--, 1, true, false); - } while(reverse-- > 0); + } while (reverse-- > 0); break swapper; } } - this.tailSwap(array, pta, nmemb%4); + this.tailSwap(array, pta, nmemb % 4); pta = start; - count = nmemb/16; - while(count-- > 0) { + count = nmemb / 16; + while (count-- > 0) { this.parityMerge16(array, pta, swap); pta += 16; } - if(nmemb%16 > 4) - this.tailMerge(array, swap, pta, nmemb%16, 4); + if (nmemb % 16 > 4) + this.tailMerge(array, swap, pta, nmemb % 16, 4); Writes.deleteExternalArray(swap); return 0; @@ -835,12 +835,12 @@ else if(Reads.compareIndices(array, pta+1, pta+3, 1, true) <= 0) { // main sorting method protected void quadSort(int[] array, int start, int length) { - if(length < 16) { + if (length < 16) { this.tailSwap(array, start, length); } - else if(length < 256) { - if(this.quadSwap(array, start, length) == 0) { + else if (length < 256) { + if (this.quadSwap(array, start, length) == 0) { int[] swap = Writes.createExternalArray(128); this.tailMerge(array, swap, start, length, 16); Writes.deleteExternalArray(swap); @@ -848,8 +848,8 @@ else if(length < 256) { } else { - if(this.quadSwap(array, start, length) == 0) { - int[] swap = Writes.createExternalArray(length/2); + if (this.quadSwap(array, start, length) == 0) { + int[] swap = Writes.createExternalArray(length / 2); this.quadMerge(array, swap, start, length, 16); Writes.deleteExternalArray(swap); } @@ -858,17 +858,17 @@ else if(length < 256) { // main sorting method with given swap array protected void quadSortSwap(int[] array, int[] swap, int start, int length) { - if(length < 16) { + if (length < 16) { this.tailSwap(array, start, length); } - else if(length < 256) { - if(this.quadSwap(array, start, length) == 0) + else if (length < 256) { + if (this.quadSwap(array, start, length) == 0) this.tailMerge(array, swap, start, length, 16); } else { - if(this.quadSwap(array, start, length) == 0) + if (this.quadSwap(array, start, length) == 0) this.quadMerge(array, swap, start, length, 16); } } diff --git a/src/main/java/io/github/arrayv/sorts/templates/ShatterSorting.java b/src/main/java/io/github/arrayv/sorts/templates/ShatterSorting.java index 7da06c02..16d98326 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/ShatterSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/ShatterSorting.java @@ -31,7 +31,7 @@ of this software and associated documentation files (the "Software"), to deal */ public abstract class ShatterSorting extends Sort { - //TODO: The "sort time" for both shatter sorts is *wildly* too generous. + // TODO: The "sort time" for both shatter sorts is *wildly* too generous. protected ShatterSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); } @@ -42,11 +42,11 @@ protected void shatterPartition(int[] array, int length, int num) { @SuppressWarnings("unchecked") ArrayList[] registers = new ArrayList[shatters]; - for(int i = 0; i < shatters; i++) { + for (int i = 0; i < shatters; i++) { registers[i] = new ArrayList<>(); } - for(int i = 0; i < length; i++){ + for (int i = 0; i < length; i++) { Writes.arrayListAdd(registers[array[i] / num], array[i]); Highlights.markArray(1, i); @@ -64,9 +64,9 @@ protected void shatterSort(int[] array, int length, int num) { shatterPartition(array, length, num); int[] tmp = Writes.createExternalArray(num); - for(int i = 0; i < shatters; i++) { - for(int j = 0; j < num; j++) { - if(i * num + j >= length) + for (int i = 0; i < shatters; i++) { + for (int j = 0; j < num; j++) { + if (i * num + j >= length) Writes.write(tmp, j, -1, 0.5, false, true); else Writes.write(tmp, j, array[i * num + j], 0.5, false, true); @@ -76,10 +76,10 @@ protected void shatterSort(int[] array, int length, int num) { Highlights.clearMark(2); - for(int j = 0; j < tmp.length; j++) { + for (int j = 0; j < tmp.length; j++) { int tmpj = tmp[j]; - if(i * num + (tmpj % num) >= length || tmpj == -1) { + if (i * num + (tmpj % num) >= length || tmpj == -1) { break; } @@ -94,7 +94,7 @@ protected void shatterSort(int[] array, int length, int num) { } protected void simpleShatterSort(int[] array, int length, int num, int rate) { - for(int i = num; i > 1; i = i / rate) { + for (int i = num; i > 1; i = i / rate) { shatterPartition(array, length, i); } shatterPartition(array, length, 1); diff --git a/src/main/java/io/github/arrayv/sorts/templates/ShellSorting.java b/src/main/java/io/github/arrayv/sorts/templates/ShellSorting.java index 09e7a5ea..2e39d73e 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/ShellSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/ShellSorting.java @@ -6,22 +6,22 @@ // https://www.cs.princeton.edu/~rs/talks/shellsort.ps public abstract class ShellSorting extends Sort { - final protected int[] OriginalGaps = {2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1}; - final protected int[] PowTwoPlusOneGaps = {2049, 1025, 513, 257, 129, 65, 33, 17, 9, 5, 3, 1}; - final protected int[] PowTwoMinusOneGaps = {4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1}; - final protected int[] ThreeSmoothGaps = {3888, 3456, 3072, 2916, 2592, 2304, 2187, 2048, 1944, 1728, - 1536, 1458, 1296, 1152, 1024, 972, 864, 768, 729, 648, 576, - 512, 486, 432, 384, 324, 288, 256, 243, 216, 192, 162, 144, - 128, 108, 96, 81, 72, 64, 54, 48, 36, 32, 27, 24, 18, 16, 12, - 9, 8, 6, 4, 3, 2, 1}; - final protected int[] PowersOfThreeGaps = {3280, 1093, 364, 121, 40, 13, 4, 1}; - final protected int[] SedgewickIncerpiGaps = {1968, 861, 336, 112, 48, 21, 7, 3, 1}; - final protected int[] SedgewickGaps = {1073, 281, 77, 23, 8, 1}; - final protected int[] OddEvenSedgewickGaps = {3905, 2161, 929, 505, 209, 109, 41, 19, 5, 1}; - final protected int[] GonnetBaezaYatesGaps = {1861, 846, 384, 174, 79, 36, 16, 7, 3, 1}; - final protected int[] TokudaGaps = {2660, 1182, 525, 233, 103, 46, 20, 9, 4, 1}; - final protected int[] CiuraGaps = {1750, 701, 301, 132, 57, 23, 10, 4, 1}; - final protected int[] ExtendedCiuraGaps = {8861, 3938, 1750, 701, 301, 132, 57, 23, 10, 4, 1}; + final protected int[] OriginalGaps = { 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1 }; + final protected int[] PowTwoPlusOneGaps = { 2049, 1025, 513, 257, 129, 65, 33, 17, 9, 5, 3, 1 }; + final protected int[] PowTwoMinusOneGaps = { 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1 }; + final protected int[] ThreeSmoothGaps = { 3888, 3456, 3072, 2916, 2592, 2304, 2187, 2048, 1944, 1728, + 1536, 1458, 1296, 1152, 1024, 972, 864, 768, 729, 648, 576, + 512, 486, 432, 384, 324, 288, 256, 243, 216, 192, 162, 144, + 128, 108, 96, 81, 72, 64, 54, 48, 36, 32, 27, 24, 18, 16, 12, + 9, 8, 6, 4, 3, 2, 1 }; + final protected int[] PowersOfThreeGaps = { 3280, 1093, 364, 121, 40, 13, 4, 1 }; + final protected int[] SedgewickIncerpiGaps = { 1968, 861, 336, 112, 48, 21, 7, 3, 1 }; + final protected int[] SedgewickGaps = { 1073, 281, 77, 23, 8, 1 }; + final protected int[] OddEvenSedgewickGaps = { 3905, 2161, 929, 505, 209, 109, 41, 19, 5, 1 }; + final protected int[] GonnetBaezaYatesGaps = { 1861, 846, 384, 174, 79, 36, 16, 7, 3, 1 }; + final protected int[] TokudaGaps = { 2660, 1182, 525, 233, 103, 46, 20, 9, 4, 1 }; + final protected int[] CiuraGaps = { 1750, 701, 301, 132, 57, 23, 10, 4, 1 }; + final protected int[] ExtendedCiuraGaps = { 8861, 3938, 1750, 701, 301, 132, 57, 23, 10, 4, 1 }; protected ShellSorting(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -31,10 +31,10 @@ protected void shellSort(int[] array, int length) { int incs[] = ExtendedCiuraGaps; for (int k = 0; k < incs.length; k++) { - if(incs == PowersOfThreeGaps) { - if(incs[k] < length/3) { + if (incs == PowersOfThreeGaps) { + if (incs[k] < length / 3) { for (int h = incs[k], i = h; i < length; i++) { - //ArrayVisualizer.setCurrentGap(incs[k]); + // ArrayVisualizer.setCurrentGap(incs[k]); int v = array[i]; int j = i; @@ -42,28 +42,25 @@ protected void shellSort(int[] array, int length) { Highlights.markArray(1, j); Highlights.markArray(2, j - h); - while (j >= h && Reads.compareValues(array[j - h], v) == 1) - { + while (j >= h && Reads.compareValues(array[j - h], v) == 1) { Writes.write(array, j, array[j - h], 1, false, false); j -= h; Highlights.markArray(1, j); - if(j - h >= 0) { + if (j - h >= 0) { Highlights.markArray(2, j - h); - } - else { + } else { Highlights.clearMark(2); } } Writes.write(array, j, v, 1, true, false); } } - } - else { - if(incs[k] < length) { + } else { + if (incs[k] < length) { for (int h = incs[k], i = h; i < length; i++) { - //ArrayVisualizer.setCurrentGap(incs[k]); + // ArrayVisualizer.setCurrentGap(incs[k]); int v = array[i]; int j = i; @@ -71,17 +68,15 @@ protected void shellSort(int[] array, int length) { Highlights.markArray(1, j); Highlights.markArray(2, j - h); - while (j >= h && Reads.compareValues(array[j - h], v) == 1) - { + while (j >= h && Reads.compareValues(array[j - h], v) == 1) { Writes.write(array, j, array[j - h], 1, false, false); j -= h; Highlights.markArray(1, j); - if(j - h >= 0) { + if (j - h >= 0) { Highlights.markArray(2, j - h); - } - else { + } else { Highlights.clearMark(2); } } @@ -93,16 +88,14 @@ protected void shellSort(int[] array, int length) { } protected void quickShellSort(int[] array, int lo, int hi) { - int incs[] = {48, 21, 7, 3, 1}; + int incs[] = { 48, 21, 7, 3, 1 }; for (int k = 0; k < incs.length; k++) { - for (int h = incs[k], i = h + lo; i < hi; i++) - { + for (int h = incs[k], i = h + lo; i < hi; i++) { int v = array[i]; int j = i; - while (j >= h && Reads.compareValues(array[j-h], v) == 1) - { + while (j >= h && Reads.compareValues(array[j - h], v) == 1) { Highlights.markArray(1, j); Writes.write(array, j, array[j - h], 1, true, false); diff --git a/src/main/java/io/github/arrayv/sorts/templates/Sort.java b/src/main/java/io/github/arrayv/sorts/templates/Sort.java index 33dbbe19..9d7fb2d2 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/Sort.java +++ b/src/main/java/io/github/arrayv/sorts/templates/Sort.java @@ -1,11 +1,11 @@ package io.github.arrayv.sorts.templates; import io.github.arrayv.main.ArrayVisualizer; +import io.github.arrayv.sortdata.SortMeta; import io.github.arrayv.utils.Delays; import io.github.arrayv.utils.Highlights; import io.github.arrayv.utils.Reads; import io.github.arrayv.utils.Writes; -import io.github.arrayv.sortdata.SortMeta; public abstract class Sort { private Object[] deprecatedMetadataTable = null; @@ -27,9 +27,10 @@ protected Sort(ArrayVisualizer arrayVisualizer) { } private void initDeprecatedMetadataTable() { - if (deprecatedMetadataTable != null) return; + if (deprecatedMetadataTable != null) + return; deprecatedMetadataTable = new Object[] { - true, "", "", "", "", false, false, false, 0, null, 0 + true, "", "", "", "", false, false, false, 0, null, 0 }; } @@ -47,7 +48,7 @@ public boolean isFromExtraSorts() { @Deprecated public boolean isSortEnabled() { initDeprecatedMetadataTable(); - return (boolean)deprecatedMetadataTable[0]; + return (boolean) deprecatedMetadataTable[0]; } /** @@ -56,7 +57,7 @@ public boolean isSortEnabled() { @Deprecated public String getSortListName() { initDeprecatedMetadataTable(); - return (String)deprecatedMetadataTable[1]; + return (String) deprecatedMetadataTable[1]; } /** @@ -65,7 +66,7 @@ public String getSortListName() { @Deprecated public String getRunAllSortsName() { initDeprecatedMetadataTable(); - return (String)deprecatedMetadataTable[2]; + return (String) deprecatedMetadataTable[2]; } /** @@ -74,7 +75,7 @@ public String getRunAllSortsName() { @Deprecated public String getRunSortName() { initDeprecatedMetadataTable(); - return (String)deprecatedMetadataTable[3]; + return (String) deprecatedMetadataTable[3]; } /** @@ -83,12 +84,14 @@ public String getRunSortName() { @Deprecated public String getCategory() { initDeprecatedMetadataTable(); - return (String)deprecatedMetadataTable[4]; + return (String) deprecatedMetadataTable[4]; } /** * Whether this sort is a comparison sort or a distribution sort - * @deprecated This method now always returns false, as this information is no longer stored + * + * @deprecated This method now always returns false, as this information is no + * longer stored * @return false */ @Deprecated @@ -102,7 +105,7 @@ public boolean isComparisonBased() { @Deprecated public boolean usesBuckets() { initDeprecatedMetadataTable(); - return (boolean)deprecatedMetadataTable[5]; + return (boolean) deprecatedMetadataTable[5]; } /** @@ -111,7 +114,7 @@ public boolean usesBuckets() { @Deprecated public boolean isRadixSort() { initDeprecatedMetadataTable(); - return (boolean)deprecatedMetadataTable[6]; + return (boolean) deprecatedMetadataTable[6]; } /** @@ -120,7 +123,7 @@ public boolean isRadixSort() { @Deprecated public boolean isUnreasonablySlow() { initDeprecatedMetadataTable(); - return (int)deprecatedMetadataTable[8] > 0; + return (int) deprecatedMetadataTable[8] > 0; } /** @@ -129,7 +132,7 @@ public boolean isUnreasonablySlow() { @Deprecated public int getUnreasonableLimit() { initDeprecatedMetadataTable(); - return (int)deprecatedMetadataTable[8]; + return (int) deprecatedMetadataTable[8]; } /** @@ -138,7 +141,7 @@ public int getUnreasonableLimit() { @Deprecated public boolean isBogoSort() { initDeprecatedMetadataTable(); - return (boolean)deprecatedMetadataTable[7]; + return (boolean) deprecatedMetadataTable[7]; } /** @@ -147,7 +150,7 @@ public boolean isBogoSort() { @Deprecated public String getQuestion() { initDeprecatedMetadataTable(); - return (String)deprecatedMetadataTable[9]; + return (String) deprecatedMetadataTable[9]; } /** @@ -156,7 +159,7 @@ public String getQuestion() { @Deprecated public int getDefaultAnswer() { initDeprecatedMetadataTable(); - return (int)deprecatedMetadataTable[10]; + return (int) deprecatedMetadataTable[10]; } /** @@ -177,19 +180,11 @@ protected void setSortListName(String listName) { deprecatedMetadataTable[1] = listName; } - /** - * @deprecated Please move to the new {@link SortMeta} API. - */ - @Deprecated protected void setRunAllSortsName(String showcaseName) { initDeprecatedMetadataTable(); deprecatedMetadataTable[2] = showcaseName; } - /** - * @deprecated Please move to the new {@link SortMeta} API. - */ - @Deprecated protected void setRunSortName(String runName) { initDeprecatedMetadataTable(); deprecatedMetadataTable[3] = runName; @@ -206,8 +201,11 @@ protected void setCategory(String category) { /** * Sets whether this sort is a comparison sort or a distribution sort - * @deprecated This method doesn't do anything, as this information is no longer stored - * @param comparisonBased Whether this sort is a comparison sort or a distribution sort + * + * @deprecated This method doesn't do anything, as this information is no longer + * stored + * @param comparisonBased Whether this sort is a comparison sort or a + * distribution sort */ @Deprecated public void setComparisonBased(boolean comparisonBased) { @@ -232,7 +230,8 @@ protected void setRadixSort(boolean radixSort) { } /** - * @deprecated Please move to the new {@link SortMeta} API. This method also no longer does anything. + * @deprecated Please move to the new {@link SortMeta} API. This method also no + * longer does anything. */ @Deprecated public void setUnreasonablySlow(boolean unreasonableSlow) { @@ -279,5 +278,8 @@ public static int validateAnswer(int answer) { return answer; } - public abstract void runSort(int[] array, int sortLength, int bucketCount) throws Exception; //bucketCount will be zero for comparison-based sorts + public abstract void runSort(int[] array, int sortLength, int bucketCount) throws Exception; // bucketCount will be + // zero for + // comparison-based + // sorts } diff --git a/src/main/java/io/github/arrayv/sorts/templates/TimSorting.java b/src/main/java/io/github/arrayv/sorts/templates/TimSorting.java index 12737237..252bf860 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/TimSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/TimSorting.java @@ -26,27 +26,27 @@ * A stable, adaptive, iterative mergesort that requires far fewer than * n lg(n) comparisons when running on partially sorted arrays, while * offering performance comparable to a traditional mergesort when run - * on random arrays. Like all proper mergesorts, this sort is stable and - * runs O(n log n) time (worst case). In the worst case, this sort requires + * on random arrays. Like all proper mergesorts, this sort is stable and + * runs O(n log n) time (worst case). In the worst case, this sort requires * temporary storage space for n/2 object references; in the best case, * it requires only a small constant amount of space. * * This implementation was adapted from Tim Peters's list sort for * Python, which is described in detail here: * - * http://svn.python.org/projects/python/trunk/Objects/listsort.txt + * http://svn.python.org/projects/python/trunk/Objects/listsort.txt * * Tim's C code may be found here: * - * http://svn.python.org/projects/python/trunk/Objects/listobject.c + * http://svn.python.org/projects/python/trunk/Objects/listobject.c * * The underlying techniques are described in this paper (and may have * even earlier origins): * - * "Optimistic Sorting and Information Theoretic Complexity" - * Peter McIlroy - * SODA (Fourth Annual ACM-SIAM Symposium on Discrete Algorithms), - * pp 467-474, Austin, Texas, 25-27 January 1993. + * "Optimistic Sorting and Information Theoretic Complexity" + * Peter McIlroy + * SODA (Fourth Annual ACM-SIAM Symposium on Discrete Algorithms), + * pp 467-474, Austin, Texas, 25-27 January 1993. * * While the API to this class consists solely of static methods, it is * (privately) instantiable; a TimSort instance holds the state of an ongoing @@ -55,7 +55,7 @@ * * @author Josh Bloch * - * Tailored to ArrayVisualizer by MusicTheorist + * Tailored to ArrayVisualizer by MusicTheorist */ public final class TimSorting { @@ -65,19 +65,19 @@ public final class TimSorting { private Writes Writes; /** - * This is the minimum sized sequence that will be merged. Shorter - * sequences will be lengthened by calling binarySort. If the entire + * This is the minimum sized sequence that will be merged. Shorter + * sequences will be lengthened by calling binarySort. If the entire * array is less than this length, no merges will be performed. * - * This constant should be a power of two. It was 64 in Tim Peter's C + * This constant should be a power of two. It was 64 in Tim Peter's C * implementation, but 32 was empirically determined to work better in - * this implementation. In the unlikely event that you set this constant + * this implementation. In the unlikely event that you set this constant * to be a number that's not a power of two, you'll need to change the * {@link #minRunLength} computation. * * If you decrease this constant, you must change the stackLen * computation in the TimSort constructor, or you risk an - * ArrayOutOfBounds exception. See listsort.txt for a discussion + * ArrayOutOfBounds exception. See listsort.txt for a discussion * of the minimum stack length required as a function of the length * of the array being sorted and the minimum merge sequence length. */ @@ -96,17 +96,17 @@ public final class TimSorting { */ private static final int MIN_GALLOP = 7; /** - * This controls when we get *into* galloping mode. It is initialized - * to MIN_GALLOP. The mergeLo and mergeHi methods nudge it higher for + * This controls when we get *into* galloping mode. It is initialized + * to MIN_GALLOP. The mergeLo and mergeHi methods nudge it higher for * random data, and lower for highly structured data. */ private int minGallop = MIN_GALLOP; /** - * Maximum initial size of tmp array, which is used for merging. The array + * Maximum initial size of tmp array, which is used for merging. The array * can grow to accommodate demand. * * Unlike Tim's original C version, we do not allocate this much storage - * when sorting smaller arrays. This change was required for performance. + * when sorting smaller arrays. This change was required for performance. */ private static final int INITIAL_TMP_STORAGE_LENGTH = 256; /** @@ -114,16 +114,16 @@ public final class TimSorting { */ private int[] tmp; /** - * A stack of pending runs yet to be merged. Run i starts at - * address base[i] and extends for len[i] elements. It's always + * A stack of pending runs yet to be merged. Run i starts at + * address base[i] and extends for len[i] elements. It's always * true (so long as the indices are in bounds) that: * - * runBase[i] + runLen[i] == runBase[i + 1] + * runBase[i] + runLen[i] == runBase[i + 1] * * so we could cut the storage for this, but it's a minor amount, * and keeping all the info explicit simplifies the code. */ - private int stackSize = 0; // Number of pending runs on stack + private int stackSize = 0; // Number of pending runs on stack private final int[] runBase; private final int[] runLen; @@ -133,7 +133,7 @@ public static int getMinRun() { // Easy patch for preventing gallop and merge methods from going out-of-bounds private void markArray(int marker, int markPosition) { - if(markPosition >= 0 && markPosition < this.len) { + if (markPosition >= 0 && markPosition < this.len) { this.Highlights.markArray(marker, markPosition); } } @@ -153,22 +153,20 @@ public TimSorting(int[] a, int currentLen, ArrayVisualizer arrayVisualizer) { this.Writes = arrayVisualizer.getWrites(); // Allocate temp storage (which may be increased later if necessary) - int[] newArray = Writes.createExternalArray(this.len < 2 * INITIAL_TMP_STORAGE_LENGTH ? - this.len >>> 1 : INITIAL_TMP_STORAGE_LENGTH); + int[] newArray = Writes.createExternalArray( + this.len < 2 * INITIAL_TMP_STORAGE_LENGTH ? this.len >>> 1 : INITIAL_TMP_STORAGE_LENGTH); this.tmp = newArray; /* - * Allocate runs-to-be-merged stack (which cannot be expanded). The - * stack length requirements are described in listsort.txt. The C + * Allocate runs-to-be-merged stack (which cannot be expanded). The + * stack length requirements are described in listsort.txt. The C * version always uses the same stack length (85), but this was * measured to be too expensive when sorting "mid-sized" arrays (e.g., - * 100 elements) in Java. Therefore, we use smaller (but sufficiently - * large) stack lengths for smaller arrays. The "magic numbers" in the - * computation below must be changed if MIN_MERGE is decreased. See + * 100 elements) in Java. Therefore, we use smaller (but sufficiently + * large) stack lengths for smaller arrays. The "magic numbers" in the + * computation below must be changed if MIN_MERGE is decreased. See * the MIN_MERGE declaration above for more information. */ - int stackLen = (this.len < 120 ? 5 : - this.len < 1542 ? 10 : - this.len < 119151 ? 19 : 40); + int stackLen = (this.len < 120 ? 5 : this.len < 1542 ? 10 : this.len < 119151 ? 19 : 40); this.runBase = Writes.createExternalArray(stackLen); this.runLen = Writes.createExternalArray(stackLen); } @@ -182,7 +180,7 @@ public void customSort(int[] a, int start, int length) { /* * The next two methods (which are static, one being package private) constitute - * the entire API of this class. Each of these methods obeys the contract + * the entire API of this class. Each of these methods obeys the contract * of the public method with the same signature in java.util.Arrays. */ public static void sort(TimSorting timSort, int[] a, int length) { @@ -191,6 +189,7 @@ public static void sort(TimSorting timSort, int[] a, int length) { timSort.Writes.deleteExternalArray(timSort.runBase); timSort.Writes.deleteExternalArray(timSort.runLen); } + static void sort(TimSorting timSort, int[] a, int lo, int hi) { TimSorting ts = timSort; @@ -232,8 +231,8 @@ static void sort(TimSorting timSort, int[] a, int lo, int hi) { /** * Sorts the specified portion of the specified array using a binary - * insertion sort. This is the best method for sorting small numbers - * of elements. It requires O(n log n) compares, but O(n^2) data + * insertion sort. This is the best method for sorting small numbers + * of elements. It requires O(n log n) compares, but O(n^2) data * movement (worst case). * * If the initial part of the specified range is already sorted, @@ -241,15 +240,16 @@ static void sort(TimSorting timSort, int[] a, int lo, int hi) { * elements from index {@code lo}, inclusive, to {@code start}, * exclusive are already sorted. * - * @param a the array in which a range is to be sorted - * @param lo the index of the first element in the range to be sorted - * @param hi the index after the last element in the range to be sorted + * @param a the array in which a range is to be sorted + * @param lo the index of the first element in the range to be sorted + * @param hi the index after the last element in the range to be sorted * @param start the index of the first element in the range that is - * not already known to be sorted (@code lo <= start <= hi} - * @param c comparator to used for the sort + * not already known to be sorted (@code lo <= start <= hi} + * @param c comparator to used for the sort */ - // Here, we do not use the Binary Insertion Sort included in ArrayVisualizer, as TimSort + // Here, we do not use the Binary Insertion Sort included in ArrayVisualizer, as + // TimSort // outfits it with a start index and uses the arraycopy method @SuppressWarnings("fallthrough") @@ -257,7 +257,7 @@ private static void binarySort(TimSorting ts, int[] a, int lo, int hi, int start if (start == lo) start++; - for ( ; start < hi; start++) { + for (; start < hi; start++) { int pivot = a[start]; // Set left (and right) to the index where a[start] (pivot) belongs @@ -266,8 +266,8 @@ private static void binarySort(TimSorting ts, int[] a, int lo, int hi, int start /* * Invariants: - * pivot >= all in [lo, left). - * pivot < all in [right, start). + * pivot >= all in [lo, left). + * pivot < all in [right, start). */ while (left < right) { // Another good way to prevent integer overflow with left + right! @@ -281,18 +281,21 @@ private static void binarySort(TimSorting ts, int[] a, int lo, int hi, int start /* * The invariants still hold: pivot >= all in [lo, left) and - * pivot < all in [left, start), so pivot belongs at left. Note + * pivot < all in [left, start), so pivot belongs at left. Note * that if there are elements equal to pivot, left points to the * first slot after them -- that's why this sort is stable. * Slide elements over to make room for pivot. */ - int n = start - left; // The number of elements to move + int n = start - left; // The number of elements to move // Switch is just an optimization for arraycopy in default case - switch(n) { - case 2: ts.Writes.write(a, left + 2, a[left + 1], 1, true, false); - case 1: ts.Writes.write(a, left + 1, a[left], 1, true, false); - break; - default: ts.Writes.arraycopy(a, left, a, left + 1, n, 1, true, false); + switch (n) { + case 2: + ts.Writes.write(a, left + 2, a[left + 1], 1, true, false); + case 1: + ts.Writes.write(a, left + 1, a[left], 1, true, false); + break; + default: + ts.Writes.arraycopy(a, left, a, left + 1, n, 1, true, false); } ts.Writes.write(a, left, pivot, 1, true, false); } @@ -305,23 +308,23 @@ private static void binarySort(TimSorting ts, int[] a, int lo, int hi, int start * * A run is the longest ascending sequence with: * - * a[lo] <= a[lo + 1] <= a[lo + 2] <= ... + * a[lo] <= a[lo + 1] <= a[lo + 2] <= ... * * or the longest descending sequence with: * - * a[lo] > a[lo + 1] > a[lo + 2] > ... + * a[lo] > a[lo + 1] > a[lo + 2] > ... * * For its intended use in a stable mergesort, the strictness of the * definition of "descending" is needed so that the call can safely * reverse a descending sequence without violating stability. * - * @param a the array in which a run is to be counted and possibly reversed + * @param a the array in which a run is to be counted and possibly reversed * @param lo index of the first element in the run * @param hi index after the last element that may be contained in the run. - It is required that @code{lo < hi}. - * @param c the comparator to used for the sort - * @return the length of the run beginning at the specified position in - * the specified array + * It is required that @code{lo < hi}. + * @param c the comparator to used for the sort + * @return the length of the run beginning at the specified position in + * the specified array */ private static int countRunAndMakeAscending(TimSorting ts, int[] a, int lo, int hi) { int runHi = lo + 1; @@ -330,18 +333,14 @@ private static int countRunAndMakeAscending(TimSorting ts, int[] a, int lo, int // Find end of run, and reverse range if descending if (ts.Reads.compareValues(a[runHi++], a[lo]) < 0) { // Descending - while(runHi < hi && ts.Reads.compareValues(a[runHi], a[runHi - 1]) < 0) { - ts.markArray(1, runHi); - ts.Delays.sleep(1); + while (runHi < hi && ts.Reads.compareIndices(a, runHi, runHi - 1, 1, true) < 0) runHi++; - } + reverseRange(ts, a, lo, runHi); - } else { // Ascending - while (runHi < hi && ts.Reads.compareValues(a[runHi], a[runHi - 1]) >= 0) { - ts.markArray(1, runHi); - ts.Delays.sleep(1); + } else { // Ascending + while (runHi < hi && ts.Reads.compareIndices(a, runHi, runHi - 1, 1, true) >= 0) runHi++; - } + } return runHi - lo; } @@ -349,7 +348,7 @@ private static int countRunAndMakeAscending(TimSorting ts, int[] a, int lo, int /** * Reverse the specified range of the specified array. * - * @param a the array in which a range is to be reversed + * @param a the array in which a range is to be reversed * @param lo the index of the first element in the range to be reversed * @param hi the index after the last element in the range to be reversed */ @@ -365,10 +364,10 @@ private static void reverseRange(TimSorting ts, int[] a, int lo, int hi) { * * Roughly speaking, the computation is: * - * If n < MIN_MERGE, return n (it's too small to bother with fancy stuff). - * Else if n is an exact power of 2, return MIN_MERGE/2. - * Else return an int k, MIN_MERGE/2 <= k <= MIN_MERGE, such that n/k - * is close to, but strictly less than, an exact power of 2. + * If n < MIN_MERGE, return n (it's too small to bother with fancy stuff). + * Else if n is an exact power of 2, return MIN_MERGE/2. + * Else return an int k, MIN_MERGE/2 <= k <= MIN_MERGE, such that n/k + * is close to, but strictly less than, an exact power of 2. * * For the rationale, see listsort.txt. * @@ -376,7 +375,7 @@ private static void reverseRange(TimSorting ts, int[] a, int lo, int hi) { * @return the length of the minimum run to be merged */ public static int minRunLength(int n) { - int r = 0; // Becomes 1 if any 1 bits are shifted off + int r = 0; // Becomes 1 if any 1 bits are shifted off while (n >= MIN_MERGE) { r |= (n & 1); n >>= 1; @@ -400,8 +399,8 @@ private void pushRun(int runBase, int runLen) { * Examines the stack of runs waiting to be merged and merges adjacent runs * until the stack invariants are reestablished: * - * 1. runLen[i - 3] > runLen[i - 2] + runLen[i - 1] - * 2. runLen[i - 2] > runLen[i - 1] + * 1. runLen[i - 3] > runLen[i - 2] + runLen[i - 1] + * 2. runLen[i - 2] > runLen[i - 1] * * This method is called each time a new run is pushed onto the stack, * so the invariants are guaranteed to hold for i < stackSize upon @@ -412,22 +411,22 @@ private void pushRun(int runBase, int runLen) { * the analysis in "On the Worst-Case Complexity of TimSort" by * Nicolas Auger, Vincent Jug, Cyril Nicaud, and Carine Pivoteau. */ - private void mergeCollapse() { - while (this.stackSize > 1) { - int n = this.stackSize - 2; - if ((n >= 1 && this.runLen[n-1] <= this.runLen[n] + this.runLen[n+1]) || - (n >= 2 && this.runLen[n-2] <= this.runLen[n] + this.runLen[n-1])) { - if (this.runLen[n - 1] < this.runLen[n + 1]) - n--; - } else if (this.runLen[n] > this.runLen[n + 1]) { - break; // Invariant is established - } - mergeAt(n); - } - } + private void mergeCollapse() { + while (this.stackSize > 1) { + int n = this.stackSize - 2; + if ((n >= 1 && this.runLen[n - 1] <= this.runLen[n] + this.runLen[n + 1]) || + (n >= 2 && this.runLen[n - 2] <= this.runLen[n] + this.runLen[n - 1])) { + if (this.runLen[n - 1] < this.runLen[n + 1]) + n--; + } else if (this.runLen[n] > this.runLen[n + 1]) { + break; // Invariant is established + } + mergeAt(n); + } + } /** - * Merges all runs on the stack until only one remains. This method is + * Merges all runs on the stack until only one remains. This method is * called once, to complete the sort. */ private void mergeForceCollapse() { @@ -440,8 +439,8 @@ private void mergeForceCollapse() { } /** - * Merges the two runs at stack indices i and i+1. Run i must be - * the penultimate or antepenultimate run on the stack. In other words, + * Merges the two runs at stack indices i and i+1. Run i must be + * the penultimate or antepenultimate run on the stack. In other words, * i must be equal to stackSize-2 or stackSize-3. * * @param i stack index of the first of the two runs to merge @@ -458,7 +457,7 @@ private void mergeAt(int i) { /* * Record the length of the combined runs; if i is the 3rd-last * run now, also slide over the last run (which isn't involved - * in this merge). The current run (i+1) goes away in any case. + * in this merge). The current run (i+1) goes away in any case. */ this.runLen[i] = len1 + len2; if (i == this.stackSize - 3) { @@ -500,18 +499,19 @@ private void mergeAt(int i) { * specified sorted range; if the range contains an element equal to key, * returns the index of the leftmost equal element. * - * @param key the key whose insertion point to search for - * @param a the array in which to search + * @param key the key whose insertion point to search for + * @param a the array in which to search * @param base the index of the first element in the range - * @param len the length of the range; must be > 0 + * @param len the length of the range; must be > 0 * @param hint the index at which to begin the search, 0 <= hint < n. - * The closer hint is to the result, the faster this method will run. - * @param c the comparator used to order the range, and to search - * @return the int k, 0 <= k <= n such that a[b + k - 1] < key <= a[b + k], - * pretending that a[b - 1] is minus infinity and a[b + n] is infinity. - * In other words, key belongs at index b + k; or in other words, - * the first k elements of a should precede key, and the last n - k - * should follow it. + * The closer hint is to the result, the faster this method will + * run. + * @param c the comparator used to order the range, and to search + * @return the int k, 0 <= k <= n such that a[b + k - 1] < key <= a[b + k], + * pretending that a[b - 1] is minus infinity and a[b + n] is infinity. + * In other words, key belongs at index b + k; or in other words, + * the first k elements of a should precede key, and the last n - k + * should follow it. */ private static int gallopLeft(TimSorting ts, int key, int[] a, int base, int len, int hint) { int lastOfs = 0; @@ -530,7 +530,7 @@ private static int gallopLeft(TimSorting ts, int key, int[] a, int base, int len while (ofs < maxOfs && ts.Reads.compareValues(key, a[base + hint + ofs]) > 0) { lastOfs = ofs; ofs = (ofs * 2) + 1; - if (ofs <= 0) // int overflow + if (ofs <= 0) // int overflow ofs = maxOfs; ts.markArray(3, base + hint + ofs); @@ -552,7 +552,7 @@ private static int gallopLeft(TimSorting ts, int key, int[] a, int base, int len while (ofs < maxOfs && ts.Reads.compareValues(key, a[base + hint - ofs]) <= 0) { lastOfs = ofs; ofs = (ofs * 2) + 1; - if (ofs <= 0) // int overflow + if (ofs <= 0) // int overflow ofs = maxOfs; ts.markArray(3, base + hint - ofs); @@ -569,7 +569,7 @@ private static int gallopLeft(TimSorting ts, int key, int[] a, int base, int len /* * Now a[base+lastOfs] < key <= a[base+ofs], so key belongs somewhere - * to the right of lastOfs but no farther right than ofs. Do a binary + * to the right of lastOfs but no farther right than ofs. Do a binary * search, with invariant a[base + lastOfs - 1] < key <= a[base + ofs]. */ lastOfs++; @@ -580,25 +580,27 @@ private static int gallopLeft(TimSorting ts, int key, int[] a, int base, int len ts.Delays.sleep(1); if (ts.Reads.compareValues(key, a[base + m]) > 0) - lastOfs = m + 1; // a[base + m] < key + lastOfs = m + 1; // a[base + m] < key else - ofs = m; // key <= a[base + m] + ofs = m; // key <= a[base + m] } ts.Highlights.clearMark(3); return ofs; } + /** * Like gallopLeft, except that if the range contains an element equal to * key, gallopRight returns the index after the rightmost equal element. * - * @param key the key whose insertion point to search for - * @param a the array in which to search + * @param key the key whose insertion point to search for + * @param a the array in which to search * @param base the index of the first element in the range - * @param len the length of the range; must be > 0 + * @param len the length of the range; must be > 0 * @param hint the index at which to begin the search, 0 <= hint < n. - * The closer hint is to the result, the faster this method will run. - * @param c the comparator used to order the range, and to search - * @return the int k, 0 <= k <= n such that a[b + k - 1] <= key < a[b + k] + * The closer hint is to the result, the faster this method will + * run. + * @param c the comparator used to order the range, and to search + * @return the int k, 0 <= k <= n such that a[b + k - 1] <= key < a[b + k] */ private static int gallopRight(TimSorting ts, int key, int[] a, int base, int len, int hint) { int ofs = 1; @@ -617,7 +619,7 @@ private static int gallopRight(TimSorting ts, int key, int[] a, int base, int le while (ofs < maxOfs && ts.Reads.compareValues(key, a[base + hint - ofs]) < 0) { lastOfs = ofs; ofs = (ofs * 2) + 1; - if (ofs <= 0) // int overflow + if (ofs <= 0) // int overflow ofs = maxOfs; ts.markArray(3, base + hint - ofs); @@ -640,7 +642,7 @@ private static int gallopRight(TimSorting ts, int key, int[] a, int base, int le while (ofs < maxOfs && ts.Reads.compareValues(key, a[base + hint + ofs]) >= 0) { lastOfs = ofs; ofs = (ofs * 2) + 1; - if (ofs <= 0) // int overflow + if (ofs <= 0) // int overflow ofs = maxOfs; ts.markArray(3, base + hint + ofs); @@ -656,7 +658,7 @@ private static int gallopRight(TimSorting ts, int key, int[] a, int base, int le /* * Now a[b + lastOfs] <= key < a[b + ofs], so key belongs somewhere to - * the right of lastOfs but no farther right than ofs. Do a binary + * the right of lastOfs but no farther right than ofs. Do a binary * search, with invariant a[b + lastOfs - 1] <= key < a[b + ofs]. */ lastOfs++; @@ -667,27 +669,28 @@ private static int gallopRight(TimSorting ts, int key, int[] a, int base, int le ts.Delays.sleep(1); if (ts.Reads.compareValues(key, a[base + m]) < 0) - ofs = m; // key < a[b + m] + ofs = m; // key < a[b + m] else - lastOfs = m + 1; // a[b + m] <= key + lastOfs = m + 1; // a[b + m] <= key } ts.Highlights.clearMark(3); return ofs; } + /** - * Merges two adjacent runs in place, in a stable fashion. The first + * Merges two adjacent runs in place, in a stable fashion. The first * element of the first run must be greater than the first element of the * second run (a[base1] > a[base2]), and the last element of the first run * (a[base1 + len1-1]) must be greater than all elements of the second run. * * For performance, this method should be called only when len1 <= len2; - * its twin, mergeHi should be called if len1 >= len2. (Either method + * its twin, mergeHi should be called if len1 >= len2. (Either method * may be called if len1 == len2.) * * @param base1 index of first element in first run to be merged * @param len1 length of first run to be merged (must be > 0) * @param base2 index of first element in second run to be merged - * (must be aBase + aLen) + * (must be aBase + aLen) * @param len2 length of second run to be merged (must be > 0) */ private void mergeLo(TimSorting ts, int base1, int len1, int base2, int len2) { @@ -696,9 +699,9 @@ private void mergeLo(TimSorting ts, int base1, int len1, int base2, int len2) { int[] tmp = ensureCapacity(len1); ts.Writes.arraycopy(a, base1, tmp, 0, len1, 1, true, true); - int cursor1 = 0; // Indexes into tmp array - int cursor2 = base2; // Indexes int a - int dest = base1; // Indexes int a + int cursor1 = 0; // Indexes into tmp array + int cursor2 = base2; // Indexes int a + int dest = base1; // Indexes int a // Move first element of second run and deal with degenerate cases ts.Writes.write(a, dest++, a[cursor2++], 1, false, false); @@ -715,9 +718,8 @@ private void mergeLo(TimSorting ts, int base1, int len1, int base2, int len2) { return; } - int minGallop = ts.minGallop; // " " " " " - outer: - while (true) { + int minGallop = ts.minGallop; // " " " " " + outer: while (true) { int count1 = 0; // Number of times in a row that first run won int count2 = 0; // Number of times in a row that second run won /* @@ -781,17 +783,17 @@ private void mergeLo(TimSorting ts, int base1, int len1, int base2, int len2) { } while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP); if (minGallop < 0) minGallop = 0; - minGallop += 2; // Penalize for leaving gallop mode - } // End of "outer" loop - ts.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field + minGallop += 2; // Penalize for leaving gallop mode + } // End of "outer" loop + ts.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field if (len1 == 1) { ts.Writes.arraycopy(a, cursor2, a, dest, len2, 1, true, false); - ts.Writes.write(a, dest + len2, tmp[cursor1], 1, false, false); // Last elt of run 1 to end of merge + ts.Writes.write(a, dest + len2, tmp[cursor1], 1, false, false); // Last elt of run 1 to end of merge ts.markArray(1, dest + len2); } else if (len1 == 0) { throw new IllegalArgumentException( - "Comparison method violates its general contract!"); + "Comparison method violates its general contract!"); } else { ts.Writes.arraycopy(tmp, cursor1, a, dest, len1, 1, true, false); } @@ -799,13 +801,13 @@ private void mergeLo(TimSorting ts, int base1, int len1, int base2, int len2) { /** * Like mergeLo, except that this method should be called only if - * len1 >= len2; mergeLo should be called if len1 <= len2. (Either method + * len1 >= len2; mergeLo should be called if len1 <= len2. (Either method * may be called if len1 == len2.) * * @param base1 index of first element in first run to be merged * @param len1 length of first run to be merged (must be > 0) * @param base2 index of first element in second run to be merged - * (must be aBase + aLen) + * (must be aBase + aLen) * @param len2 length of second run to be merged (must be > 0) */ private void mergeHi(TimSorting ts, int base1, int len1, int base2, int len2) { @@ -814,9 +816,9 @@ private void mergeHi(TimSorting ts, int base1, int len1, int base2, int len2) { int[] tmp = ensureCapacity(len2); ts.Writes.arraycopy(a, base2, tmp, 0, len2, 1, true, true); - int cursor1 = base1 + len1 - 1; // Indexes into a - int cursor2 = len2 - 1; // Indexes into tmp array - int dest = base2 + len2 - 1; // Indexes into a + int cursor1 = base1 + len1 - 1; // Indexes into a + int cursor2 = len2 - 1; // Indexes into tmp array + int dest = base2 + len2 - 1; // Indexes into a // Move last element of first run and deal with degenerate cases ts.Writes.write(a, dest--, a[cursor1--], 1, false, false); @@ -835,9 +837,8 @@ private void mergeHi(TimSorting ts, int base1, int len1, int base2, int len2) { return; } - int minGallop = ts.minGallop; // " " " " " - outer: - while (true) { + int minGallop = ts.minGallop; // " " " " " + outer: while (true) { int count1 = 0; // Number of times in a row that first run won int count2 = 0; // Number of times in a row that second run won @@ -890,7 +891,7 @@ private void mergeHi(TimSorting ts, int base1, int len1, int base2, int len2) { cursor2 -= count2; len2 -= count2; ts.Writes.arraycopy(tmp, cursor2 + 1, a, dest + 1, count2, 1, true, false); - if (len2 <= 1) // len2 == 1 || len2 == 0 + if (len2 <= 1) // len2 == 1 || len2 == 0 break outer; } ts.Writes.write(a, dest--, a[cursor1--], 1, false, false); @@ -902,9 +903,9 @@ private void mergeHi(TimSorting ts, int base1, int len1, int base2, int len2) { } while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP); if (minGallop < 0) minGallop = 0; - minGallop += 2; // Penalize for leaving gallop mode - } // End of "outer" loop - ts.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field + minGallop += 2; // Penalize for leaving gallop mode + } // End of "outer" loop + ts.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field if (len2 == 1) { dest -= len1; @@ -914,14 +915,15 @@ private void mergeHi(TimSorting ts, int base1, int len1, int base2, int len2) { ts.markArray(1, dest); } else if (len2 == 0) { throw new IllegalArgumentException( - "Comparison method violates its general contract!"); + "Comparison method violates its general contract!"); } else { ts.Writes.arraycopy(tmp, 0, a, dest - (len2 - 1), len2, 1, true, false); } } + /** * Ensures that the external array tmp has at least the specified - * number of elements, increasing its size if necessary. The size + * number of elements, increasing its size if necessary. The size * increases exponentially to ensure amortized linear time complexity. * * @param minCapacity the minimum required capacity of the tmp array diff --git a/src/main/java/io/github/arrayv/sorts/templates/TwinSorting.java b/src/main/java/io/github/arrayv/sorts/templates/TwinSorting.java index e1547f7c..308b0242 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/TwinSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/TwinSorting.java @@ -37,9 +37,9 @@ a copy of this software and associated documentation files (the */ public abstract class TwinSorting extends Sort { - public TwinSorting(ArrayVisualizer arrayVisualizer) { - super(arrayVisualizer); - } + public TwinSorting(ArrayVisualizer arrayVisualizer) { + super(arrayVisualizer); + } // nmemb = item count private int twinSwap(int[] array, int left, int nmemb) { @@ -48,8 +48,8 @@ private int twinSwap(int[] array, int left, int nmemb) { index = 0; end = nmemb - 2; - while(index <= end) { - if(Reads.compareIndices(array, index+left, index+1+left, 1, true) <= 0) { + while (index <= end) { + if (Reads.compareIndices(array, index + left, index + 1 + left, 1, true) <= 0) { index += 2; continue; } @@ -57,16 +57,17 @@ private int twinSwap(int[] array, int left, int nmemb) { start = index; index += 2; - while(true) { - if(index > end) { - if(start == 0) { - if(nmemb % 2 == 0 || Reads.compareIndices(array, index-1+left, index+left, 1, true) > 0) { + while (true) { + if (index > end) { + if (start == 0) { + if (nmemb % 2 == 0 + || Reads.compareIndices(array, index - 1 + left, index + left, 1, true) > 0) { // the entire array was reversed Writes.changeReversals(1); end = nmemb - 1; while (start < end) - Writes.swap(array, (start++)+left, (end--)+left, 1, true, false); + Writes.swap(array, (start++) + left, (end--) + left, 1, true, false); return 1; } @@ -74,13 +75,13 @@ private int twinSwap(int[] array, int left, int nmemb) { break; } - if(Reads.compareIndices(array, index+left, index+1+left, 1, true) > 0) { - if(Reads.compareIndices(array, index-1+left, index+left, 1, true) > 0) { + if (Reads.compareIndices(array, index + left, index + 1 + left, 1, true) > 0) { + if (Reads.compareIndices(array, index - 1 + left, index + left, 1, true) > 0) { index += 2; continue; } - Writes.swap(array, index+left, index+1+left, 1, true, false); + Writes.swap(array, index + left, index + 1 + left, 1, true, false); } break; } @@ -89,7 +90,7 @@ private int twinSwap(int[] array, int left, int nmemb) { Writes.changeReversals(1); while (start < end) - Writes.swap(array, (start++)+left, (end--)+left, 1, true, false); + Writes.swap(array, (start++) + left, (end--) + left, 1, true, false); end = nmemb - 2; @@ -109,14 +110,14 @@ private void tailMerge(int array[], int left, int swap[], int nmemb, int block) s = 0; while (block < nmemb) { - for (offset = 0 ; offset + block < nmemb ; offset += block * 2) { + for (offset = 0; offset + block < nmemb; offset += block * 2) { a = offset; e = a + block - 1; - if(Reads.compareIndices(array, e+left, e+1+left, 1, true) <= 0) + if (Reads.compareIndices(array, e + left, e + 1 + left, 1, true) <= 0) continue; - if(offset + block * 2 <= nmemb) { + if (offset + block * 2 <= nmemb) { c_max = s + block; d_max = a + block * 2; } @@ -128,7 +129,7 @@ private void tailMerge(int array[], int left, int swap[], int nmemb, int block) d = d_max - 1; - while(Reads.compareIndices(array, e+left, d+left, 1, true) <= 0) { + while (Reads.compareIndices(array, e + left, d + left, 1, true) <= 0) { d_max--; d--; c_max--; @@ -138,9 +139,9 @@ private void tailMerge(int array[], int left, int swap[], int nmemb, int block) d = a + block; Highlights.clearMark(2); - while(c < c_max) { - Writes.write(swap, c++, array[d+left], 0, false, true); - Highlights.markArray(1, (d++)+left); + while (c < c_max) { + Writes.write(swap, c++, array[d + left], 0, false, true); + Highlights.markArray(1, (d++) + left); Delays.sleep(1); } c--; @@ -148,38 +149,37 @@ private void tailMerge(int array[], int left, int swap[], int nmemb, int block) d = a + block - 1; e = d_max - 1; - if(Reads.compareIndices(array, a+left, a+block+left, 1, true) <= 0) { + if (Reads.compareIndices(array, a + left, a + block + left, 1, true) <= 0) { Highlights.clearMark(2); - Writes.write(array, (e--)+left, array[(d--)+left], 1, true, false); + Writes.write(array, (e--) + left, array[(d--) + left], 1, true, false); - while(c >= s) { - while (Reads.compareValues(array[d+left], swap[c]) > 0) { - Highlights.markArray(2, c+left+offset); - Writes.write(array, (e--)+left, array[(d--)+left], 1, true, false); + while (c >= s) { + while (Reads.compareValues(array[d + left], swap[c]) > 0) { + Highlights.markArray(2, c + left + offset); + Writes.write(array, (e--) + left, array[(d--) + left], 1, true, false); } - Highlights.markArray(2, c+left+offset); - Writes.write(array, (e--)+left, swap[c--], 1, true, false); + Highlights.markArray(2, c + left + offset); + Writes.write(array, (e--) + left, swap[c--], 1, true, false); } } else { Highlights.clearMark(2); - Writes.write(array, (e--)+left, array[(d--)+left], 1, true, false); + Writes.write(array, (e--) + left, array[(d--) + left], 1, true, false); - while(d >= a) - { - while(Reads.compareValues(array[d+left], swap[c]) <= 0) { - Highlights.markArray(2, c+left+offset); - Writes.write(array, (e--)+left, swap[c--], 1, true, false); + while (d >= a) { + while (Reads.compareValues(array[d + left], swap[c]) <= 0) { + Highlights.markArray(2, c + left + offset); + Writes.write(array, (e--) + left, swap[c--], 1, true, false); } - Writes.write(array, (e--)+left, array[(d--)+left], 1, true, false); + Writes.write(array, (e--) + left, array[(d--) + left], 1, true, false); } - while(c >= s) { - Highlights.markArray(2, c+left+offset); - Writes.write(array, (e--)+left, swap[c--], 1, true, false); + while (c >= s) { + Highlights.markArray(2, c + left + offset); + Writes.write(array, (e--) + left, swap[c--], 1, true, false); } } @@ -188,15 +188,14 @@ private void tailMerge(int array[], int left, int swap[], int nmemb, int block) } } - protected void twinsortSwap(int[] array, int start, int[] swap, int nmemb) - { - if(twinSwap(array, start, nmemb) == 0) + protected void twinsortSwap(int[] array, int start, int[] swap, int nmemb) { + if (twinSwap(array, start, nmemb) == 0) tailMerge(array, start, swap, nmemb, 2); } public void twinsort(int[] array, int nmemb) { - if(twinSwap(array, 0, nmemb) == 0) { - int[] swap = Writes.createExternalArray(nmemb/2); + if (twinSwap(array, 0, nmemb) == 0) { + int[] swap = Writes.createExternalArray(nmemb / 2); tailMerge(array, 0, swap, nmemb, 2); @@ -204,12 +203,11 @@ public void twinsort(int[] array, int nmemb) { } } - public void tailsort(int[] array, int nmemb) - { - if(nmemb < 2) + public void tailsort(int[] array, int nmemb) { + if (nmemb < 2) return; - int[] swap = Writes.createExternalArray(nmemb/2); + int[] swap = Writes.createExternalArray(nmemb / 2); tailMerge(array, 0, swap, nmemb, 1); Writes.deleteExternalArray(swap); diff --git a/src/main/java/io/github/arrayv/sorts/templates/UnstableGrailSorting.java b/src/main/java/io/github/arrayv/sorts/templates/UnstableGrailSorting.java index 2a2aaab5..e33d0135 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/UnstableGrailSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/UnstableGrailSorting.java @@ -59,20 +59,19 @@ private void grailSwap(int[] arr, int a, int b) { } private void grailMultiSwap(int[] arr, int a, int b, int swapsLeft) { - while(swapsLeft != 0) { + while (swapsLeft != 0) { this.grailSwap(arr, a++, b++); swapsLeft--; } } protected void grailRotate(int[] array, int pos, int lenA, int lenB) { - while(lenA != 0 && lenB != 0) { - if(lenA <= lenB) { + while (lenA != 0 && lenB != 0) { + if (lenA <= lenB) { this.grailMultiSwap(array, pos, pos + lenA, lenA); pos += lenA; lenB -= lenA; - } - else { + } else { this.grailMultiSwap(array, pos + (lenA - lenB), pos + lenA, lenB); lenA -= lenB; } @@ -83,21 +82,22 @@ private void grailInsertSort(int[] arr, int pos, int len) { grailInsertSorter.customSort(arr, pos, pos + len, 0.75); } - //boolean argument determines direction + // boolean argument determines direction private int grailBinSearch(int[] arr, int pos, int len, int keyPos, boolean isLeft) { int left = -1, right = len; - while(left < right - 1) { + while (left < right - 1) { int mid = left + ((right - left) >> 1); - if(isLeft) { - if(Reads.compareValues(arr[pos + mid], arr[keyPos]) >= 0) { + if (isLeft) { + if (Reads.compareValues(arr[pos + mid], arr[keyPos]) >= 0) { right = mid; } else { left = mid; } } else { - if(Reads.compareValues(arr[pos + mid], arr[keyPos]) > 0) { + if (Reads.compareValues(arr[pos + mid], arr[keyPos]) > 0) { right = mid; - } else left = mid; + } else + left = mid; } Highlights.markArray(1, pos + mid); } @@ -106,45 +106,51 @@ private int grailBinSearch(int[] arr, int pos, int len, int keyPos, boolean isLe // cost: min(len1, len2)^2 + max(len1, len2) private void grailMergeWithoutBuffer(int[] arr, int pos, int len1, int len2) { - if(len1 < len2) { - while(len1 != 0) { - //Binary Search left + if (len1 < len2) { + while (len1 != 0) { + // Binary Search left int loc = this.grailBinSearch(arr, pos + len1, len2, pos, true); - if(loc != 0) { + if (loc != 0) { this.grailRotate(arr, pos, len1, loc); pos += loc; len2 -= loc; } - if(len2 == 0) break; + if (len2 == 0) + break; do { pos++; len1--; - } while(len1 != 0 && Reads.compareValues(arr[pos], arr[pos + len1]) <= 0); + } while (len1 != 0 && Reads.compareValues(arr[pos], arr[pos + len1]) <= 0); } } else { - while(len2 != 0) { - //Binary Search right + while (len2 != 0) { + // Binary Search right int loc = this.grailBinSearch(arr, pos, len1, pos + (len1 + len2 - 1), false); - if(loc != len1) { + if (loc != len1) { this.grailRotate(arr, pos + loc, len1 - loc, len2); len1 = loc; } - if(len1 == 0) break; + if (len1 == 0) + break; do { len2--; - } while(len2 != 0 && Reads.compareValues(arr[pos + len1 - 1], arr[pos + len1 + len2 - 1]) <= 0); + } while (len2 != 0 && Reads.compareValues(arr[pos + len1 - 1], arr[pos + len1 + len2 - 1]) <= 0); } } } // arr - starting array. arr[0 - regBlockLen..-1] - buffer (if havebuf). - // regBlockLen - length of regular blocks. First blockCount blocks are stable sorted by 1st elements and key-coded - // keysPos - arrays of keys, in same order as blocks. keysPos < midkey means stream A + // regBlockLen - length of regular blocks. First blockCount blocks are stable + // sorted by 1st elements and key-coded + // keysPos - arrays of keys, in same order as blocks. keysPos < midkey means + // stream A // aBlockCount are regular blocks from stream A. - // lastLen is length of last (irregular) block from stream B, that should go before nblock2 blocks. - // lastLen = 0 requires aBlockCount = 0 (no irregular blocks). lastLen > 0, aBlockCount = 0 is possible. + // lastLen is length of last (irregular) block from stream B, that should go + // before nblock2 blocks. + // lastLen = 0 requires aBlockCount = 0 (no irregular blocks). lastLen > 0, + // aBlockCount = 0 is possible. private void grailMergeBuffersLeft(int[] arr, int pos, int blockCount, int blockLen, int aBlockCount, int lastLen) { - if(blockCount == 0) { + if (blockCount == 0) { int aBlocksLen = aBlockCount * blockLen; this.grailMergeLeft(arr, pos, aBlocksLen, lastLen, 0 - blockLen); return; @@ -154,13 +160,13 @@ private void grailMergeBuffersLeft(int[] arr, int pos, int blockCount, int block int processIndex = blockLen; int restToProcess; - for(int keyIndex = 1; keyIndex < blockCount; keyIndex++, processIndex += blockLen) { + for (int keyIndex = 1; keyIndex < blockCount; keyIndex++, processIndex += blockLen) { restToProcess = processIndex - leftOverLen; leftOverLen = this.grailSmartMergeWithBuffer(arr, pos + restToProcess, leftOverLen, blockLen); } restToProcess = processIndex - leftOverLen; - if(lastLen != 0) { + if (lastLen != 0) { leftOverLen += blockLen * aBlockCount; this.grailMergeLeft(arr, pos + restToProcess, leftOverLen, lastLen, -blockLen); @@ -169,7 +175,8 @@ private void grailMergeBuffersLeft(int[] arr, int pos, int blockCount, int block } } - // arr[dist..-1] - buffer, arr[0, leftLen - 1] ++ arr[leftLen, leftLen + rightLen - 1] + // arr[dist..-1] - buffer, arr[0, leftLen - 1] ++ arr[leftLen, leftLen + + // rightLen - 1] // -> arr[dist, dist + leftLen + rightLen - 1] private void grailMergeLeft(int[] arr, int pos, int leftLen, int rightLen, int dist) { int left = 0; @@ -177,49 +184,53 @@ private void grailMergeLeft(int[] arr, int pos, int leftLen, int rightLen, int d rightLen += leftLen; - while(right < rightLen) { - if(left == leftLen || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { + while (right < rightLen) { + if (left == leftLen || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { this.grailSwap(arr, pos + (dist++), pos + (right++)); - } - else this.grailSwap(arr, pos + (dist++), pos + (left++)); + } else + this.grailSwap(arr, pos + (dist++), pos + (left++)); Highlights.markArray(3, pos + left); Highlights.markArray(4, pos + right); } Highlights.clearMark(3); Highlights.clearMark(4); - if(dist != left) this.grailMultiSwap(arr, pos + dist, pos + left, leftLen - left); + if (dist != left) + this.grailMultiSwap(arr, pos + dist, pos + left, leftLen - left); } + private void grailMergeRight(int[] arr, int pos, int leftLen, int rightLen, int dist) { int mergedPos = leftLen + rightLen + dist - 1; int right = leftLen + rightLen - 1; int left = leftLen - 1; - while(left >= 0) { - if(right < leftLen || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { + while (left >= 0) { + if (right < leftLen || Reads.compareValues(arr[pos + left], arr[pos + right]) > 0) { this.grailSwap(arr, pos + (mergedPos--), pos + (left--)); - } - else this.grailSwap(arr, pos + (mergedPos--), pos + (right--)); - if(pos + left >= 0) Highlights.markArray(3, pos + left); + } else + this.grailSwap(arr, pos + (mergedPos--), pos + (right--)); + if (pos + left >= 0) + Highlights.markArray(3, pos + left); Highlights.markArray(4, pos + right); } Highlights.clearMark(3); Highlights.clearMark(4); - if(right != mergedPos) { - while(right >= leftLen) this.grailSwap(arr, pos + (mergedPos--), pos + (right--)); + if (right != mergedPos) { + while (right >= leftLen) + this.grailSwap(arr, pos + (mergedPos--), pos + (right--)); } } - //returns just the leftover length + // returns just the leftover length private int grailSmartMergeWithBuffer(int[] arr, int pos, int leftOverLen, int blockLen) { int dist = 0 - blockLen, left = 0, right = leftOverLen, leftEnd = right, rightEnd = right + blockLen; - while(left < leftEnd && right < rightEnd) { - if(Reads.compareValues(arr[pos + left], arr[pos + right]) <= 0) { + while (left < leftEnd && right < rightEnd) { + if (Reads.compareValues(arr[pos + left], arr[pos + right]) <= 0) { this.grailSwap(arr, pos + (dist++), pos + (left++)); - } - else this.grailSwap(arr, pos + (dist++), pos + (right++)); + } else + this.grailSwap(arr, pos + (dist++), pos + (right++)); Highlights.markArray(3, pos + left); Highlights.markArray(4, pos + right); } @@ -227,9 +238,10 @@ private int grailSmartMergeWithBuffer(int[] arr, int pos, int leftOverLen, int b Highlights.clearMark(4); int length; - if(left < leftEnd) { + if (left < leftEnd) { length = leftEnd - left; - while(left < leftEnd) this.grailSwap(arr, pos + (--leftEnd), pos + (--rightEnd)); + while (left < leftEnd) + this.grailSwap(arr, pos + (--leftEnd), pos + (--rightEnd)); } else { length = rightEnd - right; } @@ -238,28 +250,31 @@ private int grailSmartMergeWithBuffer(int[] arr, int pos, int leftOverLen, int b // build blocks of length buildLen // input: [-buildLen, -1] elements are buffer - // output: first buildLen elements are buffer, blocks 2 * buildLen and last subblock sorted + // output: first buildLen elements are buffer, blocks 2 * buildLen and last + // subblock sorted private void grailBuildBlocks(int[] arr, int pos, int len, int buildLen) { int extraDist, part; - for(int dist = 1; dist < len; dist += 2) { - extraDist = 0; - if(Reads.compareValues(arr[pos + (dist - 1)], arr[pos + dist]) > 0) extraDist = 1; - this.grailSwap(arr, pos + (dist - 3), pos + (dist - 1 + extraDist)); - this.grailSwap(arr, pos + (dist - 2), pos + (dist - extraDist)); - } - if(len % 2 != 0) this.grailSwap(arr, pos + (len - 1), pos + (len - 3)); - pos -= 2; - part = 2; + for (int dist = 1; dist < len; dist += 2) { + extraDist = 0; + if (Reads.compareValues(arr[pos + (dist - 1)], arr[pos + dist]) > 0) + extraDist = 1; + this.grailSwap(arr, pos + (dist - 3), pos + (dist - 1 + extraDist)); + this.grailSwap(arr, pos + (dist - 2), pos + (dist - extraDist)); + } + if (len % 2 != 0) + this.grailSwap(arr, pos + (len - 1), pos + (len - 3)); + pos -= 2; + part = 2; - for(; part < buildLen; part *= 2) { + for (; part < buildLen; part *= 2) { int left = 0; int right = len - 2 * part; - while(left <= right) { + while (left <= right) { this.grailMergeLeft(arr, pos + left, part, part, 0 - part); left += 2 * part; } int rest = len - left; - if(rest > part) { + if (rest > part) { this.grailMergeLeft(arr, pos + left, part, rest - part, 0 - part); } else { this.grailRotate(arr, pos + left - part, part, rest); @@ -269,61 +284,68 @@ private void grailBuildBlocks(int[] arr, int pos, int len, int buildLen) { int restToBuild = len % (2 * buildLen); int leftOverPos = len - restToBuild; - if(restToBuild <= buildLen) this.grailRotate(arr, pos + leftOverPos, restToBuild, buildLen); - else this.grailMergeRight(arr, pos + leftOverPos, buildLen, restToBuild - buildLen, buildLen); + if (restToBuild <= buildLen) + this.grailRotate(arr, pos + leftOverPos, restToBuild, buildLen); + else + this.grailMergeRight(arr, pos + leftOverPos, buildLen, restToBuild - buildLen, buildLen); - while(leftOverPos > 0) { + while (leftOverPos > 0) { leftOverPos -= 2 * buildLen; this.grailMergeRight(arr, pos + leftOverPos, buildLen, buildLen, buildLen); } } - // keys are on the left of arr. Blocks of length buildLen combined. We'll combine them in pairs - // buildLen and nkeys are powers of 2. (2 * buildLen / regBlockLen) keys are guaranteed + // keys are on the left of arr. Blocks of length buildLen combined. We'll + // combine them in pairs + // buildLen and nkeys are powers of 2. (2 * buildLen / regBlockLen) keys are + // guaranteed private void grailCombineBlocks(int[] arr, int pos, int len, int buildLen, int regBlockLen) { int combineLen = len / (2 * buildLen); int leftOver = len % (2 * buildLen); - if(leftOver <= buildLen) { + if (leftOver <= buildLen) { len -= leftOver; leftOver = 0; } - for(int i = 0; i <= combineLen; i++) { - if(i == combineLen && leftOver == 0) break; + for (int i = 0; i <= combineLen; i++) { + if (i == combineLen && leftOver == 0) + break; int blockPos = pos + i * 2 * buildLen; int blockCount = (i == combineLen ? leftOver : 2 * buildLen) / regBlockLen; - for(int index = 1; index < blockCount; index++) { + for (int index = 1; index < blockCount; index++) { int leftIndex = index - 1; - for(int rightIndex = index; rightIndex < blockCount; rightIndex++) { + for (int rightIndex = index; rightIndex < blockCount; rightIndex++) { int rightComp = Reads.compareValues(arr[blockPos + leftIndex * regBlockLen], - arr[blockPos + rightIndex * regBlockLen]); - if(rightComp > 0 || (rightComp == 0 && Reads.compareValues(arr[blockPos + (leftIndex + 1) * regBlockLen - 1], - arr[blockPos + (rightIndex + 1) * regBlockLen - 1]) > 0)) { + arr[blockPos + rightIndex * regBlockLen]); + if (rightComp > 0 + || (rightComp == 0 && Reads.compareValues(arr[blockPos + (leftIndex + 1) * regBlockLen - 1], + arr[blockPos + (rightIndex + 1) * regBlockLen - 1]) > 0)) { leftIndex = rightIndex; } } - if(leftIndex != index - 1) { - this.grailMultiSwap(arr, blockPos + (index - 1) * regBlockLen, blockPos + leftIndex * regBlockLen, regBlockLen); + if (leftIndex != index - 1) { + this.grailMultiSwap(arr, blockPos + (index - 1) * regBlockLen, blockPos + leftIndex * regBlockLen, + regBlockLen); } } int aBlockCount = 0; int lastLen = 0; - if(i == combineLen) lastLen = leftOver % regBlockLen; + if (i == combineLen) + lastLen = leftOver % regBlockLen; - if(lastLen != 0) { - while(aBlockCount < blockCount && Reads.compareValues(arr[blockPos + blockCount * regBlockLen], - arr[blockPos + (blockCount - aBlockCount - 1) * regBlockLen]) - < 0) { + if (lastLen != 0) { + while (aBlockCount < blockCount && Reads.compareValues(arr[blockPos + blockCount * regBlockLen], + arr[blockPos + (blockCount - aBlockCount - 1) * regBlockLen]) < 0) { aBlockCount++; } } this.grailMergeBuffersLeft(arr, blockPos, blockCount - aBlockCount, regBlockLen, aBlockCount, lastLen); } - while(--len >= 0) { + while (--len >= 0) { this.grailSwap(arr, pos + len, pos + len - regBlockLen); } } @@ -331,19 +353,20 @@ private void grailCombineBlocks(int[] arr, int pos, int len, int buildLen, int r protected void grailCommonSort(int[] arr, int pos, int len) { this.grailInsertSorter = new OptimizedGnomeSort(this.arrayVisualizer); - if(len <= 16) { + if (len <= 16) { this.grailInsertSort(arr, pos, len); return; } int blockLen = 1; - while(blockLen * blockLen < len) blockLen *= 2; + while (blockLen * blockLen < len) + blockLen *= 2; int buildLen = blockLen; this.grailBuildBlocks(arr, pos + blockLen, len - blockLen, buildLen); // 2 * buildLen are built - while(len - blockLen > (buildLen *= 2)) { + while (len - blockLen > (buildLen *= 2)) { this.grailCombineBlocks(arr, pos + blockLen, len - blockLen, buildLen, blockLen); Highlights.clearMark(2); diff --git a/src/main/java/io/github/arrayv/sorts/templates/WikiSorting.java b/src/main/java/io/github/arrayv/sorts/templates/WikiSorting.java index 0cec6df4..feda122f 100644 --- a/src/main/java/io/github/arrayv/sorts/templates/WikiSorting.java +++ b/src/main/java/io/github/arrayv/sorts/templates/WikiSorting.java @@ -146,7 +146,8 @@ int length() { public final class WikiSorting { // use a small cache to speed up some of the operations // since the cache size is fixed, it's still O(1) memory! - // just keep in mind that making it too small ruins the point (nothing will fit into it), + // just keep in mind that making it too small ruins the point (nothing will fit + // into it), // and making it too large also ruins the point (so much for "low memory"!) private InsertionSort InsertSort; @@ -158,18 +159,24 @@ public final class WikiSorting { private static int cache_size = 0; private int[] cache; - // note that you can easily modify the above to allocate a dynamically sized cache + // note that you can easily modify the above to allocate a dynamically sized + // cache // good choices for the cache size are: - // (size + 1)/2 – turns into a full-speed standard merge sort since everything fits into the cache - // sqrt((size + 1)/2) + 1 – this will be the size of the A blocks at the largest level of merges, - // so a buffer of this size would allow it to skip using internal or in-place merges for anything + // (size + 1)/2 – turns into a full-speed standard merge sort since everything + // fits into the cache + // sqrt((size + 1)/2) + 1 – this will be the size of the A blocks at the largest + // level of merges, + // so a buffer of this size would allow it to skip using internal or in-place + // merges for anything - // Original static buffer = 512 – chosen from careful testing as a good balance between fixed-size memory use and run time - // ArrayVisualizer static buffer = 32, as the numbers of items we use for visual purposes is relatively small - - // 0 – if the system simply cannot allocate any extra memory whatsoever, no memory works just fine + // Original static buffer = 512 – chosen from careful testing as a good balance + // between fixed-size memory use and run time + // ArrayVisualizer static buffer = 32, as the numbers of items we use for visual + // purposes is relatively small + // 0 – if the system simply cannot allocate any extra memory whatsoever, no + // memory works just fine public WikiSorting(InsertionSort insertionSort, ArrayVisualizer arrayVisualizer, int cacheChoice) { this.InsertSort = insertionSort; @@ -181,50 +188,60 @@ public WikiSorting(InsertionSort insertionSort, ArrayVisualizer arrayVisualizer, cache_size = cacheChoice; - if(cache_size != 0) this.cache = Writes.createExternalArray(cache_size); - else this.cache = null; + if (cache_size != 0) + this.cache = Writes.createExternalArray(cache_size); + else + this.cache = null; } public static void sort(WikiSorting WikiSort, int[] array, int currentLen) { WikiSort.Sort(array, currentLen); - if (WikiSort.cache != null) WikiSort.Writes.deleteExternalArray(WikiSort.cache); + if (WikiSort.cache != null) + WikiSort.Writes.deleteExternalArray(WikiSort.cache); } // toolbox functions used by the sorter - // find the index of the first value within the range that is equal to array[index] + // find the index of the first value within the range that is equal to + // array[index] int BinaryFirst(int[] array, int value, Range range) { int start = range.start, end = range.end - 1; while (start < end) { - int mid = start + (end - start)/2; + int mid = start + (end - start) / 2; if (Reads.compareValues(array[mid], value) < 0) start = mid + 1; else end = mid; } - if (start == range.end - 1 && Reads.compareValues(array[start], value) < 0) start++; + if (start == range.end - 1 && Reads.compareValues(array[start], value) < 0) + start++; return start; } - // find the index of the last value within the range that is equal to array[index], plus 1 + // find the index of the last value within the range that is equal to + // array[index], plus 1 int BinaryLast(int[] array, int value, Range range) { int start = range.start, end = range.end - 1; while (start < end) { - int mid = start + (end - start)/2; + int mid = start + (end - start) / 2; if (Reads.compareValues(value, array[mid]) >= 0) start = mid + 1; else end = mid; } - if (start == range.end - 1 && Reads.compareValues(value, array[start]) >= 0) start++; + if (start == range.end - 1 && Reads.compareValues(value, array[start]) >= 0) + start++; return start; } - // combine a linear search with a binary search to reduce the number of comparisons in situations - // where have some idea as to how many unique values there are and where the next value might be + // combine a linear search with a binary search to reduce the number of + // comparisons in situations + // where have some idea as to how many unique values there are and where the + // next value might be int FindFirstForward(int[] array, int value, Range range, int unique) { - if (range.length() == 0) return range.start; - int index, skip = Math.max(range.length()/unique, 1); + if (range.length() == 0) + return range.start; + int index, skip = Math.max(range.length() / unique, 1); for (index = range.start + skip; Reads.compareValues(array[index - 1], value) < 0; index += skip) if (index >= range.end - skip) @@ -234,8 +251,9 @@ int FindFirstForward(int[] array, int value, Range range, int unique) { } int FindLastForward(int[] array, int value, Range range, int unique) { - if (range.length() == 0) return range.start; - int index, skip = Math.max(range.length()/unique, 1); + if (range.length() == 0) + return range.start; + int index, skip = Math.max(range.length() / unique, 1); for (index = range.start + skip; Reads.compareValues(value, array[index - 1]) >= 0; index += skip) if (index >= range.end - skip) @@ -245,10 +263,12 @@ int FindLastForward(int[] array, int value, Range range, int unique) { } int FindFirstBackward(int[] array, int value, Range range, int unique) { - if (range.length() == 0) return range.start; - int index, skip = Math.max(range.length()/unique, 1); + if (range.length() == 0) + return range.start; + int index, skip = Math.max(range.length() / unique, 1); - for (index = range.end - skip; index > range.start && Reads.compareValues(array[index - 1], value) >= 0; index -= skip) + for (index = range.end - skip; index > range.start + && Reads.compareValues(array[index - 1], value) >= 0; index -= skip) if (index < range.start + skip) return BinaryFirst(array, value, new Range(range.start, index)); @@ -256,10 +276,12 @@ int FindFirstBackward(int[] array, int value, Range range, int unique) { } int FindLastBackward(int[] array, int value, Range range, int unique) { - if (range.length() == 0) return range.start; - int index, skip = Math.max(range.length()/unique, 1); + if (range.length() == 0) + return range.start; + int index, skip = Math.max(range.length() / unique, 1); - for (index = range.end - skip; index > range.start && Reads.compareValues(value, array[index - 1]) < 0; index -= skip) + for (index = range.end - skip; index > range.start + && Reads.compareValues(value, array[index - 1]) < 0; index -= skip) if (index < range.start + skip) return BinaryLast(array, value, new Range(range.start, index)); @@ -286,7 +308,8 @@ void BlockSwap(int[] array, int start1, int start2, int block_size) { // rotate the values in an array ([0 1 2 3] becomes [1 2 3 0] if we rotate by 1) // this assumes that 0 <= amount <= range.length() void Rotate(int[] array, int amount, Range range, boolean use_cache) { - if (range.length() == 0) return; + if (range.length() == 0) + return; int split; if (amount >= 0) @@ -298,13 +321,15 @@ void Rotate(int[] array, int amount, Range range, boolean use_cache) { Range range2 = new Range(split, range.end); if (use_cache) { - // if the smaller of the two ranges fits into the cache, it's *slightly* faster copying it there and shifting the elements over + // if the smaller of the two ranges fits into the cache, it's *slightly* faster + // copying it there and shifting the elements over if (range1.length() <= range2.length()) { if (range1.length() <= cache_size) { if (cache != null) { Writes.arraycopy(array, range1.start, cache, 0, range1.length(), 1, true, true); Writes.arraycopy(array, range2.start, array, range1.start, range2.length(), 1, true, false); - Writes.arraycopy(cache, 0, array, range1.start + range2.length(), range1.length(), 1, true, false); + Writes.arraycopy(cache, 0, array, range1.start + range2.length(), range1.length(), 1, true, + false); } return; } @@ -312,7 +337,8 @@ void Rotate(int[] array, int amount, Range range, boolean use_cache) { if (range2.length() <= cache_size) { if (cache != null) { Writes.arraycopy(array, range2.start, cache, 0, range2.length(), 1, true, true); - Writes.arraycopy(array, range1.start, array, range2.end - range1.length(), range1.length(), 1, true, false); + Writes.arraycopy(array, range1.start, array, range2.end - range1.length(), range1.length(), 1, + true, false); Writes.arraycopy(cache, 0, array, range1.start, range2.length(), 1, true, false); } return; @@ -321,22 +347,22 @@ void Rotate(int[] array, int amount, Range range, boolean use_cache) { } /* - int lenA = range1.length(); - int lenB = range2.length(); - int pos = range.start; - - while(lenA != 0 && lenB != 0) { - if(lenA <= lenB) { - this.BlockSwap(array, pos, pos + lenA, lenA); - pos += lenA; - lenB -= lenA; - } - else { - this.BlockSwap(array, pos + (lenA - lenB), pos + lenA, lenB); - lenA -= lenB; - } - } - */ + * int lenA = range1.length(); + * int lenB = range2.length(); + * int pos = range.start; + * + * while(lenA != 0 && lenB != 0) { + * if(lenA <= lenB) { + * this.BlockSwap(array, pos, pos + lenA, lenA); + * pos += lenA; + * lenB -= lenA; + * } + * else { + * this.BlockSwap(array, pos + (lenA - lenB), pos + lenA, lenB); + * lenA -= lenB; + * } + * } + */ Reverse(array, range1); Reverse(array, range2); @@ -355,8 +381,10 @@ void MergeInto(int[] from, Range A, Range B, int[] into, int at_index, boolean t if (Reads.compareValues(from[B_index], from[A_index]) >= 0) { Writes.write(into, insert_index, from[A_index], 1, false, tempwrite); - if(tempwrite) Highlights.markArray(1, A_index); - else Highlights.markArray(1, insert_index); + if (tempwrite) + Highlights.markArray(1, A_index); + else + Highlights.markArray(1, insert_index); A_index++; insert_index++; @@ -368,8 +396,10 @@ void MergeInto(int[] from, Range A, Range B, int[] into, int at_index, boolean t } else { Writes.write(into, insert_index, from[B_index], 1, false, tempwrite); - if(tempwrite) Highlights.markArray(1, B_index); - else Highlights.markArray(1, insert_index); + if (tempwrite) + Highlights.markArray(1, B_index); + else + Highlights.markArray(1, insert_index); B_index++; insert_index++; @@ -399,12 +429,14 @@ void MergeExternal(int[] array, Range A, Range B) { Writes.write(array, insert_index, cache[A_index], 1, true, false); A_index++; insert_index++; - if (A_index == A_last) break; + if (A_index == A_last) + break; } else { Writes.write(array, insert_index, array[B_index], 1, true, false); B_index++; insert_index++; - if (B_index == B_last) break; + if (B_index == B_last) + break; } } } @@ -419,8 +451,10 @@ void MergeExternal(int[] array, Range A, Range B) { // merge operation using an internal buffer void MergeInternal(int[] array, Range A, Range B, Range buffer) { - // whenever we find a value to add to the final array, swap it with the value that's already in that spot - // when this algorithm is finished, 'buffer' will contain its original contents, but in a different order + // whenever we find a value to add to the final array, swap it with the value + // that's already in that spot + // when this algorithm is finished, 'buffer' will contain its original contents, + // but in a different order int A_count = 0, B_count = 0, insert = 0; if (B.length() > 0 && A.length() > 0) { @@ -431,14 +465,16 @@ void MergeInternal(int[] array, Range A, Range B, Range buffer) { Writes.swap(array, A.start + insert, buffer.start + A_count, 0, true, false); A_count++; insert++; - if (A_count >= A.length()) break; + if (A_count >= A.length()) + break; } else { Highlights.markArray(3, B.start + B_count); Delays.sleep(1); Writes.swap(array, A.start + insert, B.start + B_count, 0, true, false); B_count++; insert++; - if (B_count >= B.length()) break; + if (B_count >= B.length()) + break; } } } @@ -450,26 +486,31 @@ void MergeInternal(int[] array, Range A, Range B, Range buffer) { // merge operation without a buffer void MergeInPlace(int[] array, Range A, Range B) { - if (A.length() == 0 || B.length() == 0) return; + if (A.length() == 0 || B.length() == 0) + return; /* - this just repeatedly binary searches into B and rotates A into position. - the paper suggests using the 'rotation-based Hwang and Lin algorithm' here, - but I decided to stick with this because it had better situational performance - - (Hwang and Lin is designed for merging subarrays of very different sizes, - but WikiSort almost always uses subarrays that are roughly the same size) - - normally this is incredibly suboptimal, but this function is only called - when none of the A or B blocks in any subarray contained 2 sqrt(A) unique values, - which places a hard limit on the number of times this will ACTUALLY need - to binary search and rotate. - - according to my analysis the worst case is sqrt(A) rotations performed on sqrt(A) items - once the constant factors are removed, which ends up being O(n) - - again, this is NOT a general-purpose solution – it only works well in this case! - kind of like how the O(n^2) insertion sort is used in some places + * this just repeatedly binary searches into B and rotates A into position. + * the paper suggests using the 'rotation-based Hwang and Lin algorithm' here, + * but I decided to stick with this because it had better situational + * performance + * + * (Hwang and Lin is designed for merging subarrays of very different sizes, + * but WikiSort almost always uses subarrays that are roughly the same size) + * + * normally this is incredibly suboptimal, but this function is only called + * when none of the A or B blocks in any subarray contained 2 sqrt(A) unique + * values, + * which places a hard limit on the number of times this will ACTUALLY need + * to binary search and rotate. + * + * according to my analysis the worst case is sqrt(A) rotations performed on + * sqrt(A) items + * once the constant factors are removed, which ends up being O(n) + * + * again, this is NOT a general-purpose solution – it only works well in this + * case! + * kind of like how the O(n^2) insertion sort is used in some places */ A = new Range(A.start, A.end); @@ -482,13 +523,15 @@ kind of like how the O(n^2) insertion sort is used in some places // rotate A into place int amount = mid - A.end; Rotate(array, -amount, new Range(A.start, mid), true); - if (B.end == mid) break; + if (B.end == mid) + break; // calculate the new A and B ranges B.start = mid; A.set(A.start + amount, B.start); A.start = BinaryLast(array, array[A.start], A); - if (A.length() == 0) break; + if (A.length() == 0) + break; } } @@ -500,7 +543,8 @@ void NetSwap(int[] array, int[] order, Range range, int x, int y) { } } - // bottom-up merge sort combined with an in-place merge algorithm for O(1) memory use + // bottom-up merge sort combined with an in-place merge algorithm for O(1) + // memory use void Sort(int[] array, int len) { int size = len; @@ -535,49 +579,79 @@ void Sort(int[] array, int len) { Range range = iterator.nextRange(); if (range.length() == 8) { - NetSwap(array, order, range, 0, 1); NetSwap(array, order, range, 2, 3); - NetSwap(array, order, range, 4, 5); NetSwap(array, order, range, 6, 7); - NetSwap(array, order, range, 0, 2); NetSwap(array, order, range, 1, 3); - NetSwap(array, order, range, 4, 6); NetSwap(array, order, range, 5, 7); - NetSwap(array, order, range, 1, 2); NetSwap(array, order, range, 5, 6); - NetSwap(array, order, range, 0, 4); NetSwap(array, order, range, 3, 7); - NetSwap(array, order, range, 1, 5); NetSwap(array, order, range, 2, 6); - NetSwap(array, order, range, 1, 4); NetSwap(array, order, range, 3, 6); - NetSwap(array, order, range, 2, 4); NetSwap(array, order, range, 3, 5); + NetSwap(array, order, range, 0, 1); + NetSwap(array, order, range, 2, 3); + NetSwap(array, order, range, 4, 5); + NetSwap(array, order, range, 6, 7); + NetSwap(array, order, range, 0, 2); + NetSwap(array, order, range, 1, 3); + NetSwap(array, order, range, 4, 6); + NetSwap(array, order, range, 5, 7); + NetSwap(array, order, range, 1, 2); + NetSwap(array, order, range, 5, 6); + NetSwap(array, order, range, 0, 4); + NetSwap(array, order, range, 3, 7); + NetSwap(array, order, range, 1, 5); + NetSwap(array, order, range, 2, 6); + NetSwap(array, order, range, 1, 4); + NetSwap(array, order, range, 3, 6); + NetSwap(array, order, range, 2, 4); + NetSwap(array, order, range, 3, 5); NetSwap(array, order, range, 3, 4); } else if (range.length() == 7) { - NetSwap(array, order, range, 1, 2); NetSwap(array, order, range, 3, 4); NetSwap(array, order, range, 5, 6); - NetSwap(array, order, range, 0, 2); NetSwap(array, order, range, 3, 5); NetSwap(array, order, range, 4, 6); - NetSwap(array, order, range, 0, 1); NetSwap(array, order, range, 4, 5); NetSwap(array, order, range, 2, 6); - NetSwap(array, order, range, 0, 4); NetSwap(array, order, range, 1, 5); - NetSwap(array, order, range, 0, 3); NetSwap(array, order, range, 2, 5); - NetSwap(array, order, range, 1, 3); NetSwap(array, order, range, 2, 4); + NetSwap(array, order, range, 1, 2); + NetSwap(array, order, range, 3, 4); + NetSwap(array, order, range, 5, 6); + NetSwap(array, order, range, 0, 2); + NetSwap(array, order, range, 3, 5); + NetSwap(array, order, range, 4, 6); + NetSwap(array, order, range, 0, 1); + NetSwap(array, order, range, 4, 5); + NetSwap(array, order, range, 2, 6); + NetSwap(array, order, range, 0, 4); + NetSwap(array, order, range, 1, 5); + NetSwap(array, order, range, 0, 3); + NetSwap(array, order, range, 2, 5); + NetSwap(array, order, range, 1, 3); + NetSwap(array, order, range, 2, 4); NetSwap(array, order, range, 2, 3); } else if (range.length() == 6) { - NetSwap(array, order, range, 1, 2); NetSwap(array, order, range, 4, 5); - NetSwap(array, order, range, 0, 2); NetSwap(array, order, range, 3, 5); - NetSwap(array, order, range, 0, 1); NetSwap(array, order, range, 3, 4); NetSwap(array, order, range, 2, 5); - NetSwap(array, order, range, 0, 3); NetSwap(array, order, range, 1, 4); - NetSwap(array, order, range, 2, 4); NetSwap(array, order, range, 1, 3); + NetSwap(array, order, range, 1, 2); + NetSwap(array, order, range, 4, 5); + NetSwap(array, order, range, 0, 2); + NetSwap(array, order, range, 3, 5); + NetSwap(array, order, range, 0, 1); + NetSwap(array, order, range, 3, 4); + NetSwap(array, order, range, 2, 5); + NetSwap(array, order, range, 0, 3); + NetSwap(array, order, range, 1, 4); + NetSwap(array, order, range, 2, 4); + NetSwap(array, order, range, 1, 3); NetSwap(array, order, range, 2, 3); } else if (range.length() == 5) { - NetSwap(array, order, range, 0, 1); NetSwap(array, order, range, 3, 4); + NetSwap(array, order, range, 0, 1); + NetSwap(array, order, range, 3, 4); NetSwap(array, order, range, 2, 4); - NetSwap(array, order, range, 2, 3); NetSwap(array, order, range, 1, 4); + NetSwap(array, order, range, 2, 3); + NetSwap(array, order, range, 1, 4); NetSwap(array, order, range, 0, 3); - NetSwap(array, order, range, 0, 2); NetSwap(array, order, range, 1, 3); + NetSwap(array, order, range, 0, 2); + NetSwap(array, order, range, 1, 3); NetSwap(array, order, range, 1, 2); } else if (range.length() == 4) { - NetSwap(array, order, range, 0, 1); NetSwap(array, order, range, 2, 3); - NetSwap(array, order, range, 0, 2); NetSwap(array, order, range, 1, 3); + NetSwap(array, order, range, 0, 1); + NetSwap(array, order, range, 2, 3); + NetSwap(array, order, range, 0, 2); + NetSwap(array, order, range, 1, 3); NetSwap(array, order, range, 1, 2); } } - if (size < 8) return; + if (size < 8) + return; Highlights.clearMark(2); @@ -592,15 +666,20 @@ void Sort(int[] array, int len) { pull[0] = new Pull(); pull[1] = new Pull(); - // then merge sort the higher levels, which can be 8-15, 16-31, 32-63, 64-127, etc. + // then merge sort the higher levels, which can be 8-15, 16-31, 32-63, 64-127, + // etc. while (true) { - // if every A and B block will fit into the cache, use a special branch specifically for merging with the cache - // (we use < rather than <= since the block size might be one more than iterator.length()) + // if every A and B block will fit into the cache, use a special branch + // specifically for merging with the cache + // (we use < rather than <= since the block size might be one more than + // iterator.length()) if (iterator.length() < cache_size) { - // if four subarrays fit into the cache, it's faster to merge both pairs of subarrays into the cache, - // then merge the two merged subarrays from the cache back into the original array + // if four subarrays fit into the cache, it's faster to merge both pairs of + // subarrays into the cache, + // then merge the two merged subarrays from the cache back into the original + // array if ((iterator.length() + 1) * 4 <= cache_size && iterator.length() * 4 <= size) { iterator.begin(); while (!iterator.finished()) { @@ -611,7 +690,8 @@ void Sort(int[] array, int len) { Range B2 = iterator.nextRange(); if (Reads.compareValues(array[B1.end - 1], array[A1.start]) < 0) { - // the two ranges are in reverse order, so copy them in reverse order into the cache + // the two ranges are in reverse order, so copy them in reverse order into the + // cache Writes.arraycopy(array, A1.start, cache, B1.length(), A1.length(), 1, true, true); Writes.arraycopy(array, B1.start, cache, 0, B1.length(), 1, true, true); } else if (Reads.compareValues(array[B1.start], array[A1.end - 1]) < 0) { @@ -619,7 +699,9 @@ void Sort(int[] array, int len) { MergeInto(array, A1, B1, cache, 0, true); } else { // if A1, B1, A2, and B2 are all in order, skip doing anything else - if (Reads.compareValues(array[B2.start], array[A2.end - 1]) >= 0 && Reads.compareValues(array[A2.start], array[B1.end - 1]) >= 0) continue; + if (Reads.compareValues(array[B2.start], array[A2.end - 1]) >= 0 + && Reads.compareValues(array[A2.start], array[B1.end - 1]) >= 0) + continue; // copy A1 and B1 into the cache in the same order Writes.arraycopy(array, A1.start, cache, 0, A1.length(), 1, true, true); @@ -629,8 +711,10 @@ void Sort(int[] array, int len) { // merge A2 and B2 into the cache if (Reads.compareValues(array[B2.end - 1], array[A2.start]) < 0) { - // the two ranges are in reverse order, so copy them in reverse order into the cache - Writes.arraycopy(array, A2.start, cache, A1.length() + B2.length(), A2.length(), 1, true, true); + // the two ranges are in reverse order, so copy them in reverse order into the + // cache + Writes.arraycopy(array, A2.start, cache, A1.length() + B2.length(), A2.length(), 1, true, + true); Writes.arraycopy(array, B2.start, cache, A1.length(), B2.length(), 1, true, true); } else if (Reads.compareValues(array[B2.start], array[A2.end - 1]) < 0) { // these two ranges weren't already in order, so merge them into the cache @@ -638,7 +722,8 @@ void Sort(int[] array, int len) { } else { // copy A2 and B2 into the cache in the same order Writes.arraycopy(array, A2.start, cache, A1.length(), A2.length(), 1, true, true); - Writes.arraycopy(array, B2.start, cache, A1.length() + A2.length(), B2.length(), 1, true, true); + Writes.arraycopy(array, B2.start, cache, A1.length() + A2.length(), B2.length(), 1, true, + true); } A2.set(A2.start, B2.end); @@ -647,8 +732,10 @@ void Sort(int[] array, int len) { Range B3 = new Range(A1.length(), A1.length() + A2.length()); if (Reads.compareValues(cache[B3.end - 1], cache[A3.start]) < 0) { - // the two ranges are in reverse order, so copy them in reverse order into the cache - Writes.arraycopy(cache, A3.start, array, A1.start + A2.length(), A3.length(), 1, true, false); + // the two ranges are in reverse order, so copy them in reverse order into the + // cache + Writes.arraycopy(cache, A3.start, array, A1.start + A2.length(), A3.length(), 1, true, + false); Writes.arraycopy(cache, B3.start, array, A1.start, B3.length(), 1, true, false); } else if (Reads.compareValues(cache[B3.start], cache[A3.end - 1]) < 0) { // these two ranges weren't already in order, so merge them back into the array @@ -656,7 +743,8 @@ void Sort(int[] array, int len) { } else { // copy A3 and B3 into the array in the same order Writes.arraycopy(cache, A3.start, array, A1.start, A3.length(), 1, true, false); - Writes.arraycopy(cache, B3.start, array, A1.start + A1.length(), B3.length(), 1, true, false); + Writes.arraycopy(cache, B3.start, array, A1.start + A1.length(), B3.length(), 1, true, + false); } } @@ -683,20 +771,25 @@ void Sort(int[] array, int len) { } else { // this is where the in-place merge logic starts! // 1. pull out two internal buffers each containing sqrt(A) unique values - // 1a. adjust block_size and buffer_size if we couldn't find enough unique values + // 1a. adjust block_size and buffer_size if we couldn't find enough unique + // values // 2. loop over the A and B subarrays within this level of the merge sort - // 3. break A and B into blocks of size 'block_size' - // 4. "tag" each of the A blocks with values from the first internal buffer - // 5. roll the A blocks through the B blocks and drop/rotate them where they belong - // 6. merge each A block with any B values that follow, using the cache or the second internal buffer + // 3. break A and B into blocks of size 'block_size' + // 4. "tag" each of the A blocks with values from the first internal buffer + // 5. roll the A blocks through the B blocks and drop/rotate them where they + // belong + // 6. merge each A block with any B values that follow, using the cache or the + // second internal buffer // 7. sort the second internal buffer if it exists // 8. redistribute the two internal buffers back into the array - int block_size = (int)Math.sqrt(iterator.length()); - int buffer_size = iterator.length()/block_size + 1; + int block_size = (int) Math.sqrt(iterator.length()); + int buffer_size = iterator.length() / block_size + 1; - // as an optimization, we really only need to pull out the internal buffers once for each level of merges - // after that we can reuse the same buffers over and over, then redistribute it when we're finished with this level + // as an optimization, we really only need to pull out the internal buffers once + // for each level of merges + // after that we can reuse the same buffers over and over, then redistribute it + // when we're finished with this level int index, last, count, pull_index = 0; buffer1.set(0, 0); buffer2.set(0, 0); @@ -709,21 +802,28 @@ void Sort(int[] array, int len) { boolean find_separately = false; if (block_size <= cache_size) { - // if every A block fits into the cache then we won't need the second internal buffer, + // if every A block fits into the cache then we won't need the second internal + // buffer, // so we really only need to find 'buffer_size' unique values find = buffer_size; } else if (find > iterator.length()) { - // we can't fit both buffers into the same A or B subarray, so find two buffers separately + // we can't fit both buffers into the same A or B subarray, so find two buffers + // separately find = buffer_size; find_separately = true; } - // we need to find either a single contiguous space containing 2 sqrt(A) unique values (which will be split up into two buffers of size sqrt(A) each), - // or we need to find one buffer of < 2 sqrt(A) unique values, and a second buffer of sqrt(A) unique values, - // OR if we couldn't find that many unique values, we need the largest possible buffer we can get + // we need to find either a single contiguous space containing 2 sqrt(A) unique + // values (which will be split up into two buffers of size sqrt(A) each), + // or we need to find one buffer of < 2 sqrt(A) unique values, and a second + // buffer of sqrt(A) unique values, + // OR if we couldn't find that many unique values, we need the largest possible + // buffer we can get - // in the case where it couldn't find a single buffer of at least sqrt(A) unique values, - // all of the Merge steps must be replaced by a different merge algorithm (MergeInPlace) + // in the case where it couldn't find a single buffer of at least sqrt(A) unique + // values, + // all of the Merge steps must be replaced by a different merge algorithm + // (MergeInPlace) iterator.begin(); while (!iterator.finished()) { @@ -734,12 +834,14 @@ void Sort(int[] array, int len) { // these values will be pulled out to the start of A for (last = A.start, count = 1; count < find; last = index, count++) { index = FindLastForward(array, array[last], new Range(last + 1, A.end), find - count); - if (index == A.end) break; + if (index == A.end) + break; } index = last; if (count >= buffer_size) { - // keep track of the range within the array where we'll need to "pull out" these values to create the internal buffer + // keep track of the range within the array where we'll need to "pull out" these + // values to create the internal buffer pull[pull_index].range.set(A.start, B.end); pull[pull_index].count = count; pull[pull_index].from = index; @@ -747,14 +849,18 @@ void Sort(int[] array, int len) { pull_index = 1; if (count == buffer_size + buffer_size) { - // we were able to find a single contiguous section containing 2 sqrt(A) unique values, - // so this section can be used to contain both of the internal buffers we'll need + // we were able to find a single contiguous section containing 2 sqrt(A) unique + // values, + // so this section can be used to contain both of the internal buffers we'll + // need buffer1.set(A.start, A.start + buffer_size); buffer2.set(A.start + buffer_size, A.start + count); break; } else if (find == buffer_size + buffer_size) { - // we found a buffer that contains at least sqrt(A) unique values, but did not contain the full 2 sqrt(A) unique values, - // so we still need to find a second separate buffer of at least sqrt(A) unique values + // we found a buffer that contains at least sqrt(A) unique values, but did not + // contain the full 2 sqrt(A) unique values, + // so we still need to find a second separate buffer of at least sqrt(A) unique + // values buffer1.set(A.start, A.start + count); find = buffer_size; } else if (block_size <= cache_size) { @@ -766,7 +872,8 @@ void Sort(int[] array, int len) { buffer1 = new Range(A.start, A.start + count); find_separately = false; } else { - // we found a second buffer in an 'A' subarray containing sqrt(A) unique values, so we're done! + // we found a second buffer in an 'A' subarray containing sqrt(A) unique values, + // so we're done! buffer2.set(A.start, A.start + count); break; } @@ -784,12 +891,14 @@ void Sort(int[] array, int len) { // these values will be pulled out to the end of B for (last = B.end - 1, count = 1; count < find; last = index - 1, count++) { index = FindFirstBackward(array, array[last], new Range(B.start, last), find - count); - if (index == B.start) break; + if (index == B.start) + break; } index = last; if (count >= buffer_size) { - // keep track of the range within the array where we'll need to "pull out" these values to create the internal buffer + // keep track of the range within the array where we'll need to "pull out" these + // values to create the internal buffer pull[pull_index].range.set(A.start, B.end); pull[pull_index].count = count; pull[pull_index].from = index; @@ -797,14 +906,18 @@ void Sort(int[] array, int len) { pull_index = 1; if (count == buffer_size + buffer_size) { - // we were able to find a single contiguous section containing 2 sqrt(A) unique values, - // so this section can be used to contain both of the internal buffers we'll need + // we were able to find a single contiguous section containing 2 sqrt(A) unique + // values, + // so this section can be used to contain both of the internal buffers we'll + // need buffer1.set(B.end - count, B.end - buffer_size); buffer2.set(B.end - buffer_size, B.end); break; } else if (find == buffer_size + buffer_size) { - // we found a buffer that contains at least sqrt(A) unique values, but did not contain the full 2sqrt(A) unique values, - // so we still need to find a second separate buffer of at least sqrt(A) unique values + // we found a buffer that contains at least sqrt(A) unique values, but did not + // contain the full 2sqrt(A) unique values, + // so we still need to find a second separate buffer of at least sqrt(A) unique + // values buffer1.set(B.end - count, B.end); find = buffer_size; } else if (block_size <= cache_size) { @@ -816,11 +929,15 @@ void Sort(int[] array, int len) { buffer1 = new Range(B.end - count, B.end); find_separately = false; } else { - // buffer2 will be pulled out from a 'B' subarray, so if the first buffer was pulled out from the corresponding 'A' subarray, - // we need to adjust the end point for that A subarray so it knows to stop redistributing its values before reaching buffer2 - if (pull[0].range.start == A.start) pull[0].range.end -= pull[1].count; - - // we found a second buffer in an 'B' subarray containing sqrt(A) unique values, so we're done! + // buffer2 will be pulled out from a 'B' subarray, so if the first buffer was + // pulled out from the corresponding 'A' subarray, + // we need to adjust the end point for that A subarray so it knows to stop + // redistributing its values before reaching buffer2 + if (pull[0].range.start == A.start) + pull[0].range.end -= pull[1].count; + + // we found a second buffer in an 'B' subarray containing sqrt(A) unique values, + // so we're done! buffer2.set(B.end - count, B.end); break; } @@ -840,10 +957,13 @@ void Sort(int[] array, int len) { int length = pull[pull_index].count; if (pull[pull_index].to < pull[pull_index].from) { - // we're pulling the values out to the left, which means the start of an A subarray + // we're pulling the values out to the left, which means the start of an A + // subarray index = pull[pull_index].from; for (count = 1; count < length; count++) { - index = FindFirstBackward(array, array[index - 1], new Range(pull[pull_index].to, pull[pull_index].from - (count - 1)), length - count); + index = FindFirstBackward(array, array[index - 1], + new Range(pull[pull_index].to, pull[pull_index].from - (count - 1)), + length - count); Range range = new Range(index + 1, pull[pull_index].from + 1); Rotate(array, range.length() - count, range, true); pull[pull_index].from = index + count; @@ -852,7 +972,8 @@ void Sort(int[] array, int len) { // we're pulling values out to the right, which means the end of a B subarray index = pull[pull_index].from + 1; for (count = 1; count < length; count++) { - index = FindLastForward(array, array[index], new Range(index, pull[pull_index].to), length - count); + index = FindLastForward(array, array[index], new Range(index, pull[pull_index].to), + length - count); Range range = new Range(pull[pull_index].from, index - 1); Rotate(array, count, range, true); pull[pull_index].from = index - 1 - count; @@ -860,15 +981,19 @@ void Sort(int[] array, int len) { } } - // adjust block_size and buffer_size based on the values we were able to pull out + // adjust block_size and buffer_size based on the values we were able to pull + // out buffer_size = buffer1.length(); - block_size = iterator.length()/buffer_size + 1; + block_size = iterator.length() / buffer_size + 1; - // the first buffer NEEDS to be large enough to tag each of the evenly sized A blocks, + // the first buffer NEEDS to be large enough to tag each of the evenly sized A + // blocks, // so this was originally here to test the math for adjusting block_size above - //if ((iterator.length() + 1)/block_size > buffer_size) throw new RuntimeException(); + // if ((iterator.length() + 1)/block_size > buffer_size) throw new + // RuntimeException(); - // now that the two internal buffers have been created, it's time to merge each A+B combination at this level of the merge sort! + // now that the two internal buffers have been created, it's time to merge each + // A+B combination at this level of the merge sort! iterator.begin(); while (!iterator.finished()) { A = iterator.nextRange(); @@ -880,22 +1005,29 @@ void Sort(int[] array, int len) { if (pull[0].from > pull[0].to) { A.start += pull[0].count; - // if the internal buffer takes up the entire A or B subarray, then there's nothing to merge - // this only happens for very small subarrays, like sqrt(4) = 2, 2 * (2 internal buffers) = 4, - // which also only happens when cache_size is small or 0 since it'd otherwise use MergeExternal - if (A.length() == 0) continue; + // if the internal buffer takes up the entire A or B subarray, then there's + // nothing to merge + // this only happens for very small subarrays, like sqrt(4) = 2, 2 * (2 internal + // buffers) = 4, + // which also only happens when cache_size is small or 0 since it'd otherwise + // use MergeExternal + if (A.length() == 0) + continue; } else if (pull[0].from < pull[0].to) { B.end -= pull[0].count; - if (B.length() == 0) continue; + if (B.length() == 0) + continue; } } if (start == pull[1].range.start) { if (pull[1].from > pull[1].to) { A.start += pull[1].count; - if (A.length() == 0) continue; + if (A.length() == 0) + continue; } else if (pull[1].from < pull[1].to) { B.end -= pull[1].count; - if (B.length() == 0) continue; + if (B.length() == 0) + continue; } } @@ -905,38 +1037,45 @@ void Sort(int[] array, int len) { } else if (Reads.compareValues(array[A.end], array[A.end - 1]) < 0) { // these two ranges weren't already in order, so we'll need to merge them! - // break the remainder of A into blocks. firstA is the uneven-sized first A block + // break the remainder of A into blocks. firstA is the uneven-sized first A + // block blockA.set(A.start, A.end); firstA.set(A.start, A.start + blockA.length() % block_size); // swap the first value of each A block with the value in buffer1 int indexA = buffer1.start; - for (index = firstA.end; index < blockA.end; index += block_size) { + for (index = firstA.end; index < blockA.end; index += block_size) { Writes.swap(array, indexA, index, 10, true, false); indexA++; } // start rolling the A blocks through the B blocks! - // whenever we leave an A block behind, we'll need to merge the previous A block with any B blocks that follow it, so track that information as well + // whenever we leave an A block behind, we'll need to merge the previous A block + // with any B blocks that follow it, so track that information as well lastA.set(firstA.start, firstA.end); lastB.set(0, 0); blockB.set(B.start, B.start + Math.min(block_size, B.length())); blockA.start += firstA.length(); indexA = buffer1.start; - // if the first unevenly sized A block fits into the cache, copy it there for when we go to Merge it - // otherwise, if the second buffer is available, block swap the contents into that + // if the first unevenly sized A block fits into the cache, copy it there for + // when we go to Merge it + // otherwise, if the second buffer is available, block swap the contents into + // that if (lastA.length() <= cache_size && cache != null) { Writes.arraycopy(array, lastA.start, cache, 0, lastA.length(), 1, true, true); - } - else if (buffer2.length() > 0) + } else if (buffer2.length() > 0) BlockSwap(array, lastA.start, buffer2.start, lastA.length()); if (blockA.length() > 0) { while (true) { - // if there's a previous B block and the first value of the minimum A block is <= the last value of the previous B block, - // then drop that minimum A block behind. or if there are no B blocks left then keep dropping the remaining A blocks. - if ((lastB.length() > 0 && Reads.compareValues(array[lastB.end - 1], array[indexA]) >= 0) || blockB.length() == 0) { + // if there's a previous B block and the first value of the minimum A block is + // <= the last value of the previous B block, + // then drop that minimum A block behind. or if there are no B blocks left then + // keep dropping the remaining A blocks. + if ((lastB.length() > 0 + && Reads.compareValues(array[lastB.end - 1], array[indexA]) >= 0) + || blockB.length() == 0) { // figure out where to split the previous B block, and rotate it at the split int B_split = BinaryFirst(array, array[indexA], lastB); int B_remaining = lastB.end - B_split; @@ -948,7 +1087,8 @@ else if (buffer2.length() > 0) minA = findA; BlockSwap(array, blockA.start, minA, block_size); - // swap the first item of the previous A block back with its original value, which is stored in buffer1 + // swap the first item of the previous A block back with its original value, + // which is stored in buffer1 Writes.swap(array, blockA.start, indexA, 1, true, false); indexA++; @@ -964,23 +1104,28 @@ else if (buffer2.length() > 0) MergeInPlace(array, lastA, new Range(lastA.end, B_split)); if (buffer2.length() > 0 || block_size <= cache_size) { - // copy the previous A block into the cache or buffer2, since that's where we need it to be when we go to merge it anyway + // copy the previous A block into the cache or buffer2, since that's where we + // need it to be when we go to merge it anyway if (block_size <= cache_size) { Writes.arraycopy(array, blockA.start, cache, 0, block_size, 1, true, true); - } - else + } else BlockSwap(array, blockA.start, buffer2.start, block_size); // this is equivalent to rotating, but faster - // the area normally taken up by the A block is either the contents of buffer2, or data we don't need anymore since we memcopied it - // either way, we don't need to retain the order of those items, so instead of rotating we can just block swap B to where it belongs + // the area normally taken up by the A block is either the contents of buffer2, + // or data we don't need anymore since we memcopied it + // either way, we don't need to retain the order of those items, so instead of + // rotating we can just block swap B to where it belongs BlockSwap(array, B_split, blockA.start + block_size - B_remaining, B_remaining); } else { - // we are unable to use the 'buffer2' trick to speed up the rotation operation since buffer2 doesn't exist, so perform a normal rotation - Rotate(array, blockA.start - B_split, new Range(B_split, blockA.start + block_size), true); + // we are unable to use the 'buffer2' trick to speed up the rotation operation + // since buffer2 doesn't exist, so perform a normal rotation + Rotate(array, blockA.start - B_split, + new Range(B_split, blockA.start + block_size), true); } - // update the range for the remaining A blocks, and the range remaining from the B block after it was split + // update the range for the remaining A blocks, and the range remaining from the + // B block after it was split lastA.set(blockA.start - B_remaining, blockA.start - B_remaining + block_size); lastB.set(lastA.end, lastA.end + B_remaining); @@ -990,8 +1135,10 @@ else if (buffer2.length() > 0) break; } else if (blockB.length() < block_size) { - // move the last B block, which is unevenly sized, to before the remaining A blocks, by using a rotation - // the cache is disabled here since it might contain the contents of the previous A block + // move the last B block, which is unevenly sized, to before the remaining A + // blocks, by using a rotation + // the cache is disabled here since it might contain the contents of the + // previous A block Rotate(array, -blockB.length(), new Range(blockA.start, blockB.end), false); lastB.set(blockA.start, blockA.start + blockB.length()); @@ -1026,20 +1173,27 @@ else if (buffer2.length() > 0) Highlights.clearMark(2); - // when we're finished with this merge step we should have the one or two internal buffers left over, where the second buffer is all jumbled up - // insertion sort the second buffer, then redistribute the buffers back into the array using the opposite process used for creating the buffer + // when we're finished with this merge step we should have the one or two + // internal buffers left over, where the second buffer is all jumbled up + // insertion sort the second buffer, then redistribute the buffers back into the + // array using the opposite process used for creating the buffer - // while an unstable sort like quick sort could be applied here, in benchmarks it was consistently slightly slower than a simple insertion sort, - // even for tens of millions of items. this may be because insertion sort is quite fast when the data is already somewhat sorted, like it is here + // while an unstable sort like quick sort could be applied here, in benchmarks + // it was consistently slightly slower than a simple insertion sort, + // even for tens of millions of items. this may be because insertion sort is + // quite fast when the data is already somewhat sorted, like it is here InsertionSort(array, buffer2); for (pull_index = 0; pull_index < 2; pull_index++) { int unique = pull[pull_index].count * 2; if (pull[pull_index].from > pull[pull_index].to) { - // the values were pulled out to the left, so redistribute them back to the right - Range buffer = new Range(pull[pull_index].range.start, pull[pull_index].range.start + pull[pull_index].count); + // the values were pulled out to the left, so redistribute them back to the + // right + Range buffer = new Range(pull[pull_index].range.start, + pull[pull_index].range.start + pull[pull_index].count); while (buffer.length() > 0) { - index = FindFirstForward(array, array[buffer.start], new Range(buffer.end, pull[pull_index].range.end), unique); + index = FindFirstForward(array, array[buffer.start], + new Range(buffer.end, pull[pull_index].range.end), unique); int amount = index - buffer.end; Rotate(array, buffer.length(), new Range(buffer.start, index), true); buffer.start += (amount + 1); @@ -1047,10 +1201,13 @@ else if (buffer2.length() > 0) unique -= 2; } } else if (pull[pull_index].from < pull[pull_index].to) { - // the values were pulled out to the right, so redistribute them back to the left - Range buffer = new Range(pull[pull_index].range.end - pull[pull_index].count, pull[pull_index].range.end); + // the values were pulled out to the right, so redistribute them back to the + // left + Range buffer = new Range(pull[pull_index].range.end - pull[pull_index].count, + pull[pull_index].range.end); while (buffer.length() > 0) { - index = FindLastBackward(array, array[buffer.end - 1], new Range(pull[pull_index].range.start, buffer.start), unique); + index = FindLastBackward(array, array[buffer.end - 1], + new Range(pull[pull_index].range.start, buffer.start), unique); int amount = buffer.start - index; Rotate(array, amount, new Range(index, buffer.end), true); buffer.start -= amount; @@ -1061,8 +1218,10 @@ else if (buffer2.length() > 0) } } - // double the size of each A and B subarray that will be merged in the next level - if (!iterator.nextLevel()) break; + // double the size of each A and B subarray that will be merged in the next + // level + if (!iterator.nextLevel()) + break; } } } diff --git a/src/main/java/io/github/arrayv/sorts/tests/RotationTest.java b/src/main/java/io/github/arrayv/sorts/tests/RotationTest.java index 7054a634..0a4062f6 100644 --- a/src/main/java/io/github/arrayv/sorts/tests/RotationTest.java +++ b/src/main/java/io/github/arrayv/sorts/tests/RotationTest.java @@ -30,11 +30,7 @@ this software and associated documentation files (the "Software"), to deal in * */ -@SortMeta( - listName = "Rotations", - showcaseName = "Rotation Test", - runName = "Rotation Test" -) +@SortMeta(listName = "Rotations", runName = "Rotation Test") public final class RotationTest extends Sort { final double BLOCK_DIV = 6.98; @@ -44,7 +40,7 @@ public RotationTest(ArrayVisualizer arrayVisualizer) { @Override public void runSort(int[] array, int length, int bucketCount) { - int blockSize = (int)(length / BLOCK_DIV); + int blockSize = (int) (length / BLOCK_DIV); for (int i = 0; i < blockSize; i++) { Writes.write(array, i, i + length - blockSize, 0.05, false, false); diff --git a/src/main/java/io/github/arrayv/sorts/tests/package-info.java b/src/main/java/io/github/arrayv/sorts/tests/package-info.java index 0f359ee4..4863c704 100644 --- a/src/main/java/io/github/arrayv/sorts/tests/package-info.java +++ b/src/main/java/io/github/arrayv/sorts/tests/package-info.java @@ -1,4 +1,2 @@ -@io.github.arrayv.sortdata.SortPackageMeta( - category = "Tests" -) +@io.github.arrayv.sortdata.SortPackageMeta(category = "Tests") package io.github.arrayv.sorts.tests; diff --git a/src/main/resources/scripts/categories/impractical.groovy b/src/main/resources/scripts/categories/impractical.groovy index 9b101bd9..fc385945 100644 --- a/src/main/resources/scripts/categories/impractical.groovy +++ b/src/main/resources/scripts/categories/impractical.groovy @@ -4,9 +4,9 @@ SortPrompt.setSortThreadForCategory('Impractical Sorts', 32) { run BadSort go 64.numbers, 0.0075.speed run StoogeSort go 64.numbers, 0.005.speed run QuadStoogeSort go 64.numbers, 0.005.speed - run SillySort go 64.numbers, 0.5.speed - run SlowSort go 64.numbers, 0.5.speed - run SnuffleSort go 64.numbers, 0.25.speed + run SillySort go 32.numbers, 0.5.speed + run SlowSort go 32.numbers, 0.5.speed + run SnuffleSort go 32.numbers, 1.speed run HanoiSort go 8.numbers, 0.025.speed // Bogosorts