From 7d39318bdbf34d41153a2cefeb187e180e74dd6f Mon Sep 17 00:00:00 2001 From: aphitorite Date: Sun, 14 Jun 2020 12:27:12 -0600 Subject: [PATCH 1/2] update heap sorts --- src/sorts/FlippedMinHeapSort.java | 7 +++-- src/sorts/TernaryHeapSort.java | 45 ++++++++++++++++--------------- src/templates/HeapSorting.java | 12 ++++----- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/src/sorts/FlippedMinHeapSort.java b/src/sorts/FlippedMinHeapSort.java index 6313c2b5..dbdad3e8 100644 --- a/src/sorts/FlippedMinHeapSort.java +++ b/src/sorts/FlippedMinHeapSort.java @@ -40,6 +40,7 @@ public FlippedMinHeapSort(Delays delayOps, Highlights markOps, Reads readOps, Wr this.isBogoSort(false); } private void siftDown(int[] array, int length, int root, int dist) { + int temp = array[length - root]; while (root <= dist / 2) { int leaf = 2 * root; if (leaf < dist && Reads.compare(array[length - leaf], array[length - leaf - 1]) == 1) { @@ -48,11 +49,13 @@ private void siftDown(int[] array, int length, int root, int dist) { Highlights.markArray(1, length - root); Highlights.markArray(2, length - leaf); Delays.sleep(1); - if (Reads.compare(array[length - root], array[length - leaf]) == 1) { - Writes.swap(array, length - root, length - leaf, 0, true, false); + if (Reads.compare(temp, array[length - leaf]) == 1) { + Writes.write(array, length - root, array[length - leaf], 0, true, false); root = leaf; } else break; } + + Writes.write(array, length - root, temp, 0, true, false); } @Override public void runSort(int[] array, int length, int bucketCount) { diff --git a/src/sorts/TernaryHeapSort.java b/src/sorts/TernaryHeapSort.java index c80f0204..8e58cce1 100644 --- a/src/sorts/TernaryHeapSort.java +++ b/src/sorts/TernaryHeapSort.java @@ -40,32 +40,33 @@ private static int rightBranch(int i) { } private void maxHeapify(int[] array, int i) { + int temp = array[i], root = i; + while(this.leftBranch(root) <= this.heapSize) { + int leftChild = TernaryHeapSort.leftBranch(root); + int rightChild = TernaryHeapSort.rightBranch(root); + int middleChild = TernaryHeapSort.middleBranch(root); + int largest = leftChild; - int leftChild = TernaryHeapSort.leftBranch(i); - int rightChild = TernaryHeapSort.rightBranch(i); - int middleChild = TernaryHeapSort.middleBranch(i); - int largest; + if(rightChild <= heapSize && Reads.compare(array[rightChild], array[largest]) > 0) { + largest = rightChild; + } - largest = leftChild <= heapSize && Reads.compare(array[leftChild], array[i]) > 0 ? leftChild : i; + if(middleChild <= heapSize && Reads.compare(array[middleChild], array[largest]) > 0) { + largest = middleChild; + } - if(rightChild <= heapSize && Reads.compare(array[rightChild], array[largest]) > 0) { - largest = rightChild; - } - - if(middleChild <= heapSize && Reads.compare(array[middleChild], array[largest]) > 0) { - largest = middleChild; - } - - - if(largest != i) { - Writes.swap(array, i, largest, 1, true, false); - this.maxHeapify(array, largest); - } + if(Reads.compare(array[largest], temp) > 0) { + Writes.write(array, root, array[largest], 1, true, false); + root = largest; + } else break; + } + + Writes.write(array, root, temp, 1, true, false); } private void buildMaxTernaryHeap(int[] array, int length) { - heapSize = length - 1; - for(int i = length - 1 / 3; i >= 0; i--) + this.heapSize = length - 1; + for(int i = this.heapSize / 3; i >= 0; i--) this.maxHeapify(array, i); } @@ -73,10 +74,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--){ + 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 + this.heapSize--; //shrink heap by 1 this.maxHeapify(array, 0); } } diff --git a/src/templates/HeapSorting.java b/src/templates/HeapSorting.java index c0f2dfa5..a111244b 100644 --- a/src/templates/HeapSorting.java +++ b/src/templates/HeapSorting.java @@ -23,11 +23,9 @@ protected HeapSorting(Delays delayOps, Highlights markOps, Reads readOps, Writes } 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; + int compareVal = isMax ? -1 : 1; + int temp = array[start + root - 1]; while (root <= dist / 2) { int leaf = 2 * root; if (leaf < dist && Reads.compare(array[start + leaf - 1], array[start + leaf]) == compareVal) { @@ -36,12 +34,14 @@ private void siftDown(int[] array, int root, int dist, int start, double sleep, Highlights.markArray(1, start + root - 1); Highlights.markArray(2, start + leaf - 1); Delays.sleep(sleep); - if (Reads.compare(array[start + root - 1], array[start + leaf - 1]) == compareVal) { - Writes.swap(array, start + root - 1, start + leaf - 1, 0, true, false); + if (Reads.compare(temp, array[start + leaf - 1]) == compareVal) { + Writes.write(array, start + root - 1, array[start + leaf - 1], 0, true, false); root = leaf; } else break; } + + Writes.write(array, start + root - 1, temp, 0, true, false); } private void heapify(int[] arr, int low, int high, double sleep, boolean isMax) { From 0347bacb81b43827d13dc053a63a2c46903f28f9 Mon Sep 17 00:00:00 2001 From: Lucy Phipps Date: Tue, 21 Jul 2020 21:38:18 +0100 Subject: [PATCH 2/2] use optimized heapsorts as separate algorithms --- src/sorts/FlippedMinHeapSort.java | 7 +- src/sorts/OptimizedFlippedMinHeapSort.java | 70 ++++++++++++++++++ src/sorts/OptimizedMaxHeapSort.java | 45 ++++++++++++ src/sorts/OptimizedMinHeapSort.java | 41 +++++++++++ src/sorts/OptimizedTernaryHeapSort.java | 84 ++++++++++++++++++++++ src/sorts/TernaryHeapSort.java | 45 ++++++------ src/templates/HeapSorting.java | 12 ++-- src/templates/OptimizedHeapSorting.java | 68 ++++++++++++++++++ 8 files changed, 338 insertions(+), 34 deletions(-) create mode 100644 src/sorts/OptimizedFlippedMinHeapSort.java create mode 100644 src/sorts/OptimizedMaxHeapSort.java create mode 100644 src/sorts/OptimizedMinHeapSort.java create mode 100644 src/sorts/OptimizedTernaryHeapSort.java create mode 100644 src/templates/OptimizedHeapSorting.java diff --git a/src/sorts/FlippedMinHeapSort.java b/src/sorts/FlippedMinHeapSort.java index dbdad3e8..6313c2b5 100644 --- a/src/sorts/FlippedMinHeapSort.java +++ b/src/sorts/FlippedMinHeapSort.java @@ -40,7 +40,6 @@ public FlippedMinHeapSort(Delays delayOps, Highlights markOps, Reads readOps, Wr this.isBogoSort(false); } private void siftDown(int[] array, int length, int root, int dist) { - int temp = array[length - root]; while (root <= dist / 2) { int leaf = 2 * root; if (leaf < dist && Reads.compare(array[length - leaf], array[length - leaf - 1]) == 1) { @@ -49,13 +48,11 @@ private void siftDown(int[] array, int length, int root, int dist) { Highlights.markArray(1, length - root); Highlights.markArray(2, length - leaf); Delays.sleep(1); - if (Reads.compare(temp, array[length - leaf]) == 1) { - Writes.write(array, length - root, array[length - leaf], 0, true, false); + if (Reads.compare(array[length - root], array[length - leaf]) == 1) { + Writes.swap(array, length - root, length - leaf, 0, true, false); root = leaf; } else break; } - - Writes.write(array, length - root, temp, 0, true, false); } @Override public void runSort(int[] array, int length, int bucketCount) { diff --git a/src/sorts/OptimizedFlippedMinHeapSort.java b/src/sorts/OptimizedFlippedMinHeapSort.java new file mode 100644 index 00000000..d39a65da --- /dev/null +++ b/src/sorts/OptimizedFlippedMinHeapSort.java @@ -0,0 +1,70 @@ +package sorts; + +import templates.Sort; +import utils.Delays; +import utils.Highlights; +import utils.Reads; +import utils.Writes; + +/* + * +Copyright (c) rosettacode.org. +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.2 +or any later version published by the Free Software Foundation; +with no Invariant Sections, no Front-Cover Texts, and no Back-Cover +Texts. A copy of the license is included in the section entitled "GNU +Free Documentation License". + * + */ + +/* +modified by Lucy Phipps from ../templates/OptimizedHeapSorting.java and OptimizedMinHeapSort.java +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 +*/ + +final public class OptimizedFlippedMinHeapSort extends Sort { + public OptimizedFlippedMinHeapSort(Delays delayOps, Highlights markOps, Reads readOps, Writes writeOps) { + super(delayOps, markOps, readOps, writeOps); + this.setSortPromptID("Optimized Flipped Min Heap"); + this.setRunAllID("Optimized Flipped Min Heap Sort"); + this.setReportSortID("Optimized Flipped Reverse Heapsort"); + this.setCategory("Selection Sorts"); + this.isComparisonBased(true); + this.isBucketSort(false); + this.isRadixSort(false); + this.isUnreasonablySlow(false); + this.setUnreasonableLimit(0); + this.isBogoSort(false); + } + private void siftDown(int[] array, int length, int root, int dist) { + int temp = array[length - root]; + while (root <= dist / 2) { + int leaf = 2 * root; + if (leaf < dist && Reads.compare(array[length - leaf], array[length - leaf - 1]) == 1) { + leaf++; + } + Highlights.markArray(1, length - root); + Highlights.markArray(2, length - leaf); + Delays.sleep(1); + if (Reads.compare(temp, array[length - leaf]) == 1) { + Writes.write(array, length - root, array[length - leaf], 0, true, false); + root = leaf; + } else break; + } + + Writes.write(array, length - root, temp, 0, true, false); + } + @Override + public void runSort(int[] array, int length, int bucketCount) { + for (int i = length / 2; i >= 1; i--) { + siftDown(array, length, i, length); + } + for (int i = length; i > 1; i--) { + Writes.swap(array, length - 1, length - i, 1, true, false); + siftDown(array, length, 1, i - 1); + } + } +} \ No newline at end of file diff --git a/src/sorts/OptimizedMaxHeapSort.java b/src/sorts/OptimizedMaxHeapSort.java new file mode 100644 index 00000000..ba8e56d2 --- /dev/null +++ b/src/sorts/OptimizedMaxHeapSort.java @@ -0,0 +1,45 @@ +package sorts; + +import templates.OptimizedHeapSorting; +import utils.Delays; +import utils.Highlights; +import utils.Reads; +import utils.Writes; + +/* + * +Copyright (c) rosettacode.org. +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.2 +or any later version published by the Free Software Foundation; +with no Invariant Sections, no Front-Cover Texts, and no Back-Cover +Texts. A copy of the license is included in the section entitled "GNU +Free Documentation License". + * + */ + +final public class OptimizedMaxHeapSort extends OptimizedHeapSorting { + public OptimizedMaxHeapSort(Delays delayOps, Highlights markOps, Reads readOps, Writes writeOps) { + super(delayOps, markOps, readOps, writeOps); + + this.setSortPromptID("Optimized Max Heap"); + this.setRunAllID("Optimized Max Heap Sort"); + this.setReportSortID("Optimized Heapsort"); + this.setCategory("Selection Sorts"); + this.isComparisonBased(true); + this.isBucketSort(false); + this.isRadixSort(false); + this.isUnreasonablySlow(false); + this.setUnreasonableLimit(0); + this.isBogoSort(false); + } + + public void customHeapSort(int[] array, int start, int length, double sleep) { + this.heapSort(array, start, length, sleep, true); + } + + @Override + public void runSort(int[] array, int length, int bucketCount) { + this.heapSort(array, 0, length, 1, true); + } +} \ No newline at end of file diff --git a/src/sorts/OptimizedMinHeapSort.java b/src/sorts/OptimizedMinHeapSort.java new file mode 100644 index 00000000..b50a2cbf --- /dev/null +++ b/src/sorts/OptimizedMinHeapSort.java @@ -0,0 +1,41 @@ +package sorts; + +import templates.OptimizedHeapSorting; +import utils.Delays; +import utils.Highlights; +import utils.Reads; +import utils.Writes; + +/* + * +Copyright (c) rosettacode.org. +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.2 +or any later version published by the Free Software Foundation; +with no Invariant Sections, no Front-Cover Texts, and no Back-Cover +Texts. A copy of the license is included in the section entitled "GNU +Free Documentation License". + * + */ + +final public class OptimizedMinHeapSort extends OptimizedHeapSorting { + public OptimizedMinHeapSort(Delays delayOps, Highlights markOps, Reads readOps, Writes writeOps) { + super(delayOps, markOps, readOps, writeOps); + + this.setSortPromptID("Optimized Min Heap"); + this.setRunAllID("Optimized Min Heap Sort"); + this.setReportSortID("Optimized Reverse Heapsort"); + this.setCategory("Selection Sorts"); + this.isComparisonBased(true); + this.isBucketSort(false); + this.isRadixSort(false); + this.isUnreasonablySlow(false); + this.setUnreasonableLimit(0); + this.isBogoSort(false); + } + + @Override + public void runSort(int[] array, int length, int bucketCount) { + this.heapSort(array, 0, length, 1, false); + } +} \ No newline at end of file diff --git a/src/sorts/OptimizedTernaryHeapSort.java b/src/sorts/OptimizedTernaryHeapSort.java new file mode 100644 index 00000000..87b465bc --- /dev/null +++ b/src/sorts/OptimizedTernaryHeapSort.java @@ -0,0 +1,84 @@ +package sorts; + +import templates.Sort; +import utils.Delays; +import utils.Highlights; +import utils.Reads; +import utils.Writes; + +final public class OptimizedTernaryHeapSort extends Sort { + public OptimizedTernaryHeapSort(Delays delayOps, Highlights markOps, Reads readOps, Writes writeOps) { + super(delayOps, markOps, readOps, writeOps); + + this.setSortPromptID("Optimized Ternary Heap"); + this.setRunAllID("Optimized Ternary Heap Sort"); + this.setReportSortID("Optimized Ternary Heapsort"); + this.setCategory("Selection Sorts"); + this.isComparisonBased(true); + this.isBucketSort(false); + this.isRadixSort(false); + this.isUnreasonablySlow(false); + this.setUnreasonableLimit(0); + this.isBogoSort(false); + } + + // TERNARY HEAP SORT - written by qbit + // https://codereview.stackexchange.com/questions/63384/binary-heapsort-and-ternary-heapsort-implementation + + private int heapSize; + + private static int leftBranch(int i) { + return 3 * i + 1; + } + + private static int middleBranch(int i) { + return 3 * i + 2; + } + + private static int rightBranch(int i) { + return 3 * i + 3; + } + + private void maxHeapify(int[] array, int i) { + int temp = array[i], root = i; + while(this.leftBranch(root) <= this.heapSize) { + int leftChild = OptimizedTernaryHeapSort.leftBranch(root); + int rightChild = OptimizedTernaryHeapSort.rightBranch(root); + int middleChild = OptimizedTernaryHeapSort.middleBranch(root); + int largest = leftChild; + + if(rightChild <= heapSize && Reads.compare(array[rightChild], array[largest]) > 0) { + largest = rightChild; + } + + if(middleChild <= heapSize && Reads.compare(array[middleChild], array[largest]) > 0) { + largest = middleChild; + } + + if(Reads.compare(array[largest], temp) > 0) { + Writes.write(array, root, array[largest], 1, true, false); + root = largest; + } else break; + } + + Writes.write(array, root, temp, 1, true, false); + } + + private void buildMaxTernaryHeap(int[] array, int length) { + this.heapSize = length - 1; + for(int i = this.heapSize / 3; i >= 0; i--) + this.maxHeapify(array, i); + } + + @Override + 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 + + this.heapSize--; //shrink heap by 1 + this.maxHeapify(array, 0); + } + } +} \ No newline at end of file diff --git a/src/sorts/TernaryHeapSort.java b/src/sorts/TernaryHeapSort.java index 8e58cce1..c80f0204 100644 --- a/src/sorts/TernaryHeapSort.java +++ b/src/sorts/TernaryHeapSort.java @@ -40,33 +40,32 @@ private static int rightBranch(int i) { } private void maxHeapify(int[] array, int i) { - int temp = array[i], root = i; - while(this.leftBranch(root) <= this.heapSize) { - int leftChild = TernaryHeapSort.leftBranch(root); - int rightChild = TernaryHeapSort.rightBranch(root); - int middleChild = TernaryHeapSort.middleBranch(root); - int largest = leftChild; - if(rightChild <= heapSize && Reads.compare(array[rightChild], array[largest]) > 0) { - largest = rightChild; - } + int leftChild = TernaryHeapSort.leftBranch(i); + int rightChild = TernaryHeapSort.rightBranch(i); + int middleChild = TernaryHeapSort.middleBranch(i); + int largest; - if(middleChild <= heapSize && Reads.compare(array[middleChild], array[largest]) > 0) { - largest = middleChild; - } + largest = leftChild <= heapSize && Reads.compare(array[leftChild], array[i]) > 0 ? leftChild : i; - if(Reads.compare(array[largest], temp) > 0) { - Writes.write(array, root, array[largest], 1, true, false); - root = largest; - } else break; - } - - Writes.write(array, root, temp, 1, true, false); + if(rightChild <= heapSize && Reads.compare(array[rightChild], array[largest]) > 0) { + largest = rightChild; + } + + if(middleChild <= heapSize && Reads.compare(array[middleChild], array[largest]) > 0) { + largest = middleChild; + } + + + if(largest != i) { + Writes.swap(array, i, largest, 1, true, false); + this.maxHeapify(array, largest); + } } private void buildMaxTernaryHeap(int[] array, int length) { - this.heapSize = length - 1; - for(int i = this.heapSize / 3; i >= 0; i--) + heapSize = length - 1; + for(int i = length - 1 / 3; i >= 0; i--) this.maxHeapify(array, i); } @@ -74,10 +73,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--){ + 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 - this.heapSize--; //shrink heap by 1 + heapSize = heapSize - 1; //shrink heap by 1 this.maxHeapify(array, 0); } } diff --git a/src/templates/HeapSorting.java b/src/templates/HeapSorting.java index a111244b..c0f2dfa5 100644 --- a/src/templates/HeapSorting.java +++ b/src/templates/HeapSorting.java @@ -23,9 +23,11 @@ protected HeapSorting(Delays delayOps, Highlights markOps, Reads readOps, Writes } private void siftDown(int[] array, int root, int dist, int start, double sleep, boolean isMax) { - int compareVal = isMax ? -1 : 1; + int compareVal = 0; + + if(isMax) compareVal = -1; + else compareVal = 1; - int temp = array[start + root - 1]; while (root <= dist / 2) { int leaf = 2 * root; if (leaf < dist && Reads.compare(array[start + leaf - 1], array[start + leaf]) == compareVal) { @@ -34,14 +36,12 @@ private void siftDown(int[] array, int root, int dist, int start, double sleep, Highlights.markArray(1, start + root - 1); Highlights.markArray(2, start + leaf - 1); Delays.sleep(sleep); - if (Reads.compare(temp, array[start + leaf - 1]) == compareVal) { - Writes.write(array, start + root - 1, array[start + leaf - 1], 0, true, false); + if (Reads.compare(array[start + root - 1], array[start + leaf - 1]) == compareVal) { + Writes.swap(array, start + root - 1, start + leaf - 1, 0, true, false); root = leaf; } else break; } - - Writes.write(array, start + root - 1, temp, 0, true, false); } private void heapify(int[] arr, int low, int high, double sleep, boolean isMax) { diff --git a/src/templates/OptimizedHeapSorting.java b/src/templates/OptimizedHeapSorting.java new file mode 100644 index 00000000..2162a3b6 --- /dev/null +++ b/src/templates/OptimizedHeapSorting.java @@ -0,0 +1,68 @@ +package templates; + +import utils.Delays; +import utils.Highlights; +import utils.Reads; +import utils.Writes; + +/* + * +Copyright (c) rosettacode.org. +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.2 +or any later version published by the Free Software Foundation; +with no Invariant Sections, no Front-Cover Texts, and no Back-Cover +Texts. A copy of the license is included in the section entitled "GNU +Free Documentation License". + * + */ + +public abstract class OptimizedHeapSorting extends Sort { + protected OptimizedHeapSorting(Delays delayOps, Highlights markOps, Reads readOps, Writes writeOps) { + super(delayOps, markOps, readOps, writeOps); + } + + private void siftDown(int[] array, int root, int dist, int start, double sleep, boolean isMax) { + int compareVal = isMax ? -1 : 1; + + int temp = array[start + root - 1]; + while (root <= dist / 2) { + int leaf = 2 * root; + if (leaf < dist && Reads.compare(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.compare(temp, array[start + leaf - 1]) == compareVal) { + Writes.write(array, start + root - 1, array[start + leaf - 1], 0, true, false); + root = leaf; + } + else break; + } + + Writes.write(array, start + root - 1, temp, 0, true, false); + } + + private void heapify(int[] arr, int low, int high, double sleep, boolean isMax) { + int length = high - low; + for (int i = length / 2; i >= 1; i--) { + siftDown(arr, i, length, low, sleep, isMax); + } + } + + // This version of heap sort works for max and min variants, alongside sorting + // partial ranges of an array. + protected void heapSort(int[] arr, int start, int length, double sleep, boolean isMax) { + heapify(arr, start, length, sleep, isMax); + + for (int i = length - start; i > 1; i--) { + Writes.swap(arr, start, start + i - 1, sleep, true, false); + siftDown(arr, 1, i - 1, start, sleep, isMax); + } + + if(!isMax) { + Writes.reversal(arr, start, start + length - 1, 1, true, false); + } + } +} \ No newline at end of file