From 05e30dfe954398ab31e7df808ca77dae091fd007 Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Tue, 13 Jul 2021 18:06:34 -0500 Subject: [PATCH 1/5] Add ArrayVList beta --- src/main/ArrayVisualizer.java | 8 + src/sorts/exchange/StableQuickSort.java | 17 +- src/utils/ArrayVList.java | 363 ++++++++++++++++++++++++ src/utils/Sounds.java | 12 +- src/utils/Writes.java | 22 +- 5 files changed, 401 insertions(+), 21 deletions(-) create mode 100644 src/utils/ArrayVList.java diff --git a/src/main/ArrayVisualizer.java b/src/main/ArrayVisualizer.java index fcad3640..f47b3d37 100644 --- a/src/main/ArrayVisualizer.java +++ b/src/main/ArrayVisualizer.java @@ -86,6 +86,8 @@ of this software and associated documentation files (the "Software"), to deal */ final public class ArrayVisualizer { + static ArrayVisualizer instance; + final JFrame window; final private int MIN_ARRAY_VAL; @@ -185,6 +187,8 @@ final public class ArrayVisualizer { private volatile boolean frameSkipped; public ArrayVisualizer() { + ArrayVisualizer.instance = this; + this.window = new JFrame(); this.window.addKeyListener(new KeyListener() { @Override @@ -494,6 +498,10 @@ public void run() { this.drawWindows(); } + public static ArrayVisualizer getInstance() { + return ArrayVisualizer.instance; + } + public void refreshSorts() { this.ComparisonSorts = this.SortAnalyzer.getComparisonSorts(); this.DistributionSorts = this.SortAnalyzer.getDistributionSorts(); diff --git a/src/sorts/exchange/StableQuickSort.java b/src/sorts/exchange/StableQuickSort.java index 374aa8bd..b12eb97c 100644 --- a/src/sorts/exchange/StableQuickSort.java +++ b/src/sorts/exchange/StableQuickSort.java @@ -4,6 +4,7 @@ import main.ArrayVisualizer; import sorts.templates.Sort; +import utils.ArrayVList; /* * @@ -50,7 +51,7 @@ public StableQuickSort(ArrayVisualizer arrayVisualizer) { // Author: Rodney Shaghoulian // Github: github.com/RodneyShag - private void copy(ArrayList 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); @@ -62,19 +63,21 @@ private int stablePartition(int[] array, int start, int end) { int pivotValue = array[start]; //poor pivot choice Highlights.markArray(3, start); - ArrayList leftList = new ArrayList<>(); - ArrayList rightList = new ArrayList<>(); + ArrayVList leftList = new ArrayVList(); + ArrayVList rightList = new ArrayVList(); 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]); + // Writes.mockWrite(end - start, leftList.size(), array[i], 0.25); + // Writes.arrayListAdd(leftList, array[i]); + leftList.add(array[i], 0.25, false); } else { - Writes.mockWrite(end - start, rightList.size(), array[i], 0.25); - Writes.arrayListAdd(rightList, array[i]); + // Writes.mockWrite(end - start, rightList.size(), array[i], 0.25); + // Writes.arrayListAdd(rightList, array[i]); + rightList.add(array[i], 0.25, false); } } diff --git a/src/utils/ArrayVList.java b/src/utils/ArrayVList.java new file mode 100644 index 00000000..c25328e9 --- /dev/null +++ b/src/utils/ArrayVList.java @@ -0,0 +1,363 @@ +package utils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.function.Consumer; + +import main.ArrayVisualizer; + +public class ArrayVList implements List { + final static int DEFAULT_CAPACITY = 128; + final static double DEFAULT_GROW_FACTOR = 2; + + static ArrayVisualizer arrayVisualizer; + static Reads Reads; + static Writes Writes; + + int[] internal; + double growFactor; + int count, capacity; + + public ArrayVList() { + this(DEFAULT_CAPACITY, DEFAULT_GROW_FACTOR); + } + + public ArrayVList(int capacity) { + this(capacity, DEFAULT_GROW_FACTOR); + } + + public ArrayVList(int capacity, double growFactor) { + if (arrayVisualizer == null) { + arrayVisualizer = ArrayVisualizer.getInstance(); + Reads = arrayVisualizer.getReads(); + Writes = arrayVisualizer.getWrites(); + } + this.internal = new int[capacity]; + arrayVisualizer.getArrays().add(internal); + this.count = 0; + this.capacity = capacity; + this.growFactor = growFactor; + } + + public void delete() { + Writes.changeAllocAmount(-count); + arrayVisualizer.getArrays().remove(internal); + this.internal = null; + this.count = 0; + this.capacity = 0; + } + + @Override + public int size() { + return count; + } + + @Override + public boolean isEmpty() { + return count == 0; + } + + @Override + public boolean contains(Object o) { + return indexOf(o) > -1; + } + + @Override + public Object[] toArray() { + Integer[] result = new Integer[count]; + for (int i = 0; i < count; i++) { + result[i] = internal[i]; + } + return result; + } + + @Override + @SuppressWarnings("unchecked") + public T[] toArray(T[] a) { + if (a.length < count) { + for (int i = 0; i < count; i++) { + a[i] = (T)Integer.valueOf(internal[i]); + } + return a; + } + return (T[])toArray(); + } + + protected void grow() { + int newCapacity = (int)Math.ceil(capacity * growFactor); + int[] newInternal = new int[newCapacity]; + System.arraycopy(internal, 0, newInternal, 0, count); + ArrayList arrays = arrayVisualizer.getArrays(); + arrays.set(arrays.indexOf(internal), newInternal); + this.capacity = newCapacity; + this.internal = newInternal; + } + + public boolean add(int e, double sleep, boolean mark) { + if (count == capacity) { + grow(); + } + Writes.write(internal, count++, e, sleep, mark, true); + Writes.changeAllocAmount(1); + return true; + } + + @Override + public boolean add(Integer e) { + return add(e, 0, false); + } + + private void fastRemove(int index) { + int numMoved = count - index - 1; + if (numMoved > 0) + Writes.arraycopy(internal, index + 1, internal, index, numMoved, 0, false, true); + count--; + Writes.changeAllocAmount(-1); + } + + @Override + public boolean remove(Object o) { + if (o == null) { + return false; + } else { + for (int i = 0; i < count; i++) { + if (o.equals(internal[i])) { + fastRemove(i); + return true; + } + } + } + return false; + } + + @Override + public boolean containsAll(Collection c) { + return false; + } + + @Override + public boolean addAll(Collection c) { + return false; + } + + @Override + public boolean addAll(int index, Collection c) { + return false; + } + + @Override + public boolean removeAll(Collection c) { + return false; + } + + @Override + public boolean retainAll(Collection c) { + return false; + } + + @Override + public void clear() { + count = 0; + } + + @Override + public Integer get(int index) { + return internal[index]; + } + + public Integer set(int index, int element, double sleep, boolean mark) { + rangeCheck(index); + int old = internal[index]; + Writes.write(internal, index, element, sleep, mark, true); + return old; + } + + @Override + public Integer set(int index, Integer element) { + return set(index, element, 0, false); + } + + private String outOfBoundsMsg(int index) { + return "Index: " + index + ", Size: " + this.count; + } + + private void rangeCheck(int index) { + if (index >= count) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + @Override + public void add(int index, Integer element) { + + } + + @Override + public Integer remove(int index) { + rangeCheck(index); + int old = internal[index]; + fastRemove(index); + return old; + } + + @Override + public int indexOf(Object o) { + if (o == null) { + return -1; + } + if (!(o instanceof Integer)) { + return -1; + } + int value = (Integer)o; + for (int i = 0; i < count; i++) { + if (Reads.compareValues(internal[i], value) == 0) { + return i; + } + } + return -1; + } + + @Override + public int lastIndexOf(Object o) { + if (o == null) { + return -1; + } + if (!(o instanceof Integer)) { + return -1; + } + int value = (Integer)o; + for (int i = count - 1; i >= 0; i--) { + if (Reads.compareValues(internal[i], value) == 0) { + return i; + } + } + return -1; + } + + @Override + public Iterator iterator() { + return new Itr(); + } + + @Override + public ListIterator listIterator() { + return new ListItr(0); + } + + @Override + public ListIterator listIterator(int index) { + return new ListItr(index); + } + + private class Itr implements Iterator { + int cursor; // index of next element to return + int lastRet = -1; // index of last element returned; -1 if no such + + public boolean hasNext() { + return cursor != count; + } + + public Integer next() { + int i = cursor; + if (i >= count) + throw new NoSuchElementException(); + cursor = i + 1; + return ArrayVList.this.internal[lastRet = i]; + } + + public void remove() { + if (lastRet < 0) + throw new IllegalStateException(); + + try { + ArrayVList.this.remove(lastRet); + cursor = lastRet; + lastRet = -1; + } catch (IndexOutOfBoundsException ex) { + throw new ConcurrentModificationException(); + } + } + + @Override + public void forEachRemaining(Consumer consumer) { + Objects.requireNonNull(consumer); + final int size = ArrayVList.this.capacity; + int i = cursor; + if (i >= size) { + return; + } + final int[] internal = ArrayVList.this.internal; + if (i >= internal.length) { + throw new ConcurrentModificationException(); + } + while (i != size) { + consumer.accept(internal[i++]); + } + // update once at end of iteration to reduce heap write traffic + cursor = i; + lastRet = i - 1; + } + } + + private class ListItr extends Itr implements ListIterator { + ListItr(int index) { + super(); + cursor = index; + } + + public boolean hasPrevious() { + return cursor != 0; + } + + public int nextIndex() { + return cursor; + } + + public int previousIndex() { + return cursor - 1; + } + + public Integer previous() { + int i = cursor - 1; + if (i < 0) + throw new NoSuchElementException(); + int[] internal = ArrayVList.this.internal; + if (i >= internal.length) + throw new ConcurrentModificationException(); + cursor = i; + return internal[lastRet = i]; + } + + public void set(Integer e) { + if (lastRet < 0) + throw new IllegalStateException(); + + try { + ArrayVList.this.set(lastRet, e); + } catch (IndexOutOfBoundsException ex) { + throw new ConcurrentModificationException(); + } + } + + public void add(Integer e) { + try { + int i = cursor; + ArrayVList.this.add(i, e); + cursor = i + 1; + lastRet = -1; + } catch (IndexOutOfBoundsException ex) { + throw new ConcurrentModificationException(); + } + } + } + + @Override + public List subList(int fromIndex, int toIndex) { + return null; + } +} diff --git a/src/utils/Sounds.java b/src/utils/Sounds.java index 1cd9c2f5..8525300a 100644 --- a/src/utils/Sounds.java +++ b/src/utils/Sounds.java @@ -4,6 +4,8 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; +import java.util.Map; import javax.sound.midi.Instrument; import javax.sound.midi.InvalidMidiDataException; @@ -105,7 +107,7 @@ public Sounds(int[] array, ArrayVisualizer arrayVisualizer) { try { MidiSystem.getSequencer(false); this.synth = MidiSystem.getSynthesizer(); - this.synth.open(); + synth.open(); } catch (MidiUnavailableException e) { JErrorPane.invokeCustomErrorMessage("The default MIDI device is unavailable, possibly because it is already being used by another application."); @@ -181,10 +183,10 @@ public void run() { }; } - public boolean isEnabled() { - return this.soundEnabled; - } - + public boolean isEnabled() { + return this.soundEnabled; + } + public int getInstrumentChoice() { return this.instrumentChoice; } diff --git a/src/utils/Writes.java b/src/utils/Writes.java index 3ff2b304..16aa6984 100644 --- a/src/utils/Writes.java +++ b/src/utils/Writes.java @@ -1,7 +1,7 @@ package utils; import java.util.Arrays; - +import java.util.List; import java.text.DecimalFormat; import java.util.ArrayList; @@ -406,12 +406,12 @@ public void deleteExternalArray(int[] array) { ArrayVisualizer.updateNow(); } - public void arrayListAdd(ArrayList aList, int value) { + public void arrayListAdd(List aList, int value) { allocAmount++; aList.add(value); } - public void arrayListAdd(ArrayList aList, int value, boolean mockWrite, double sleep) { + public void arrayListAdd(List aList, int value, boolean mockWrite, double sleep) { allocAmount++; aList.add(value); if (mockWrite) { @@ -422,22 +422,26 @@ public void arrayListAdd(ArrayList aList, int value, boolean mockWrite, } } - public void arrayListRemoveAt(ArrayList aList, int index) { + public void arrayListRemoveAt(List aList, int index) { allocAmount--; aList.remove(index); } - public void arrayListClear(ArrayList aList) { + public void arrayListClear(List aList) { allocAmount -= aList.size(); aList.clear(); } - public void deleteArrayList(ArrayList aList) { - allocAmount -= aList.size(); + public void deleteArrayList(List aList) { + if (aList instanceof ArrayVList) { + ((ArrayVList)aList).delete(); + } else { + allocAmount -= aList.size(); + } } - public void deleteExternalArray(ArrayList[] array) { - for (ArrayList aList : array) { + public void deleteExternalArray(List[] array) { + for (List aList : array) { deleteArrayList(aList); } } From 8007651a4ef5657e35399111bf54309db66a437e Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Tue, 13 Jul 2021 20:08:24 -0500 Subject: [PATCH 2/5] Improve stuff --- src/sorts/exchange/StableQuickSort.java | 7 +- src/sorts/hybrid/DropMergeSort.java | 7 +- src/utils/ArrayVList.java | 107 +++++++++++++++++++++++- src/utils/Writes.java | 7 +- 4 files changed, 120 insertions(+), 8 deletions(-) diff --git a/src/sorts/exchange/StableQuickSort.java b/src/sorts/exchange/StableQuickSort.java index b12eb97c..e5db690f 100644 --- a/src/sorts/exchange/StableQuickSort.java +++ b/src/sorts/exchange/StableQuickSort.java @@ -33,6 +33,8 @@ of this software and associated documentation files (the "Software"), to deal */ final public class StableQuickSort extends Sort { + int length; + public StableQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); @@ -63,8 +65,8 @@ private int stablePartition(int[] array, int start, int end) { int pivotValue = array[start]; //poor pivot choice Highlights.markArray(3, start); - ArrayVList leftList = new ArrayVList(); - ArrayVList rightList = new ArrayVList(); + ArrayVList leftList = new ArrayVList(this.length); + ArrayVList rightList = new ArrayVList(this.length); for (int i = start + 1 ; i <= end; i++) { Highlights.markArray(1, i); @@ -107,6 +109,7 @@ private void stableQuickSort(int [] array, int start, int end) { @Override public void runSort(int[] array, int length, int bucketCount) { + this.length = length; this.stableQuickSort(array, 0, length - 1); } } \ No newline at end of file diff --git a/src/sorts/hybrid/DropMergeSort.java b/src/sorts/hybrid/DropMergeSort.java index 6cd243f0..3187cfd7 100644 --- a/src/sorts/hybrid/DropMergeSort.java +++ b/src/sorts/hybrid/DropMergeSort.java @@ -1,11 +1,13 @@ package sorts.hybrid; import sorts.templates.Sort; +import utils.ArrayVList; import main.ArrayVisualizer; import sorts.hybrid.PDQBranchedSort; import java.util.ArrayList; +import java.util.List; /* * @@ -49,10 +51,9 @@ public DropMergeSort(ArrayVisualizer arrayVisualizer) { private final int EARLY_OUT_TEST_AT = 4; private final double EARLY_OUT_DISORDER_FRACTION = 0.6; - private void truncateArrayList(ArrayList arrayList, int len) { + private void truncateArrayList(List arrayList, int len) { int size = arrayList.size(); arrayList.subList(len, size).clear(); - Writes.changeAllocAmount(len - size); } @Override @@ -60,7 +61,7 @@ public void runSort(int[] array, int length, int bucketCount) { if (length < 2) return; PDQBranchedSort pdqSort = new PDQBranchedSort(arrayVisualizer); - ArrayList dropped = new ArrayList<>(length); + List dropped = new ArrayVList(length); int num_dropped_in_a_row = 0; int read = 0; diff --git a/src/utils/ArrayVList.java b/src/utils/ArrayVList.java index c25328e9..bb7a644e 100644 --- a/src/utils/ArrayVList.java +++ b/src/utils/ArrayVList.java @@ -1,5 +1,6 @@ package utils; +import java.util.AbstractList; import java.util.ArrayList; import java.util.Collection; import java.util.ConcurrentModificationException; @@ -8,11 +9,13 @@ import java.util.ListIterator; import java.util.NoSuchElementException; import java.util.Objects; +import java.util.RandomAccess; +import java.util.Spliterator; import java.util.function.Consumer; import main.ArrayVisualizer; -public class ArrayVList implements List { +public class ArrayVList extends AbstractList implements RandomAccess, Cloneable, java.io.Serializable { final static int DEFAULT_CAPACITY = 128; final static double DEFAULT_GROW_FACTOR = 2; @@ -187,6 +190,14 @@ private String outOfBoundsMsg(int index) { return "Index: " + index + ", Size: " + this.count; } + protected void removeRange(int fromIndex, int toIndex) { + int numMoved = count - toIndex; + System.arraycopy(internal, toIndex, internal, fromIndex, + numMoved); + int newSize = count - (toIndex-fromIndex); + count = newSize; + } + private void rangeCheck(int index) { if (index >= count) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); @@ -358,6 +369,98 @@ public void add(Integer e) { @Override public List subList(int fromIndex, int toIndex) { - return null; + return new SubList(this, 0, fromIndex, toIndex); + } + + private class SubList extends AbstractList implements RandomAccess { + private final ArrayVList parent; + private final int parentOffset; + private final int offset; + int size; + + SubList(ArrayVList parent, + int offset, int fromIndex, int toIndex) { + this.parent = parent; + this.parentOffset = fromIndex; + this.offset = offset + fromIndex; + this.size = toIndex - fromIndex; + } + + public Integer set(int index, int e) { + rangeCheck(index); + int oldValue = ArrayVList.this.internal[offset + index]; + ArrayVList.this.internal[offset + index] = e; + return oldValue; + } + + public Integer get(int index) { + rangeCheck(index); + return ArrayVList.this.internal[offset + index]; + } + + public int size() { + return this.size; + } + + public void add(int index, int e) { + rangeCheckForAdd(index); + parent.add(parentOffset + index, e); + size++; + } + + public Integer remove(int index) { + rangeCheck(index); + int result = parent.remove(parentOffset + index); + this.size--; + return result; + } + + protected void removeRange(int fromIndex, int toIndex) { + parent.removeRange(parentOffset + fromIndex, + parentOffset + toIndex); + this.size -= toIndex - fromIndex; + } + + public Iterator iterator() { + return listIterator(); + } + + public ListIterator listIterator(final int index) { + return null; + } + + public List subList(int fromIndex, int toIndex) { + return null; + // subListRangeCheck(fromIndex, toIndex, size); + // return new SubList(this, offset, fromIndex, toIndex); + } + + private void rangeCheck(int index) { + if (index < 0 || index >= this.size) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + private void rangeCheckForAdd(int index) { + if (index < 0 || index > this.size) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + private String outOfBoundsMsg(int index) { + return "Index: "+index+", Size: "+this.size; + } + + public Spliterator spliterator() { + return null; + } + } + + static void subListRangeCheck(int fromIndex, int toIndex, int size) { + if (fromIndex < 0) + throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); + if (toIndex > size) + throw new IndexOutOfBoundsException("toIndex = " + toIndex); + if (fromIndex > toIndex) + throw new IllegalArgumentException("fromIndex(" + fromIndex + + ") > toIndex(" + toIndex + ")"); } } diff --git a/src/utils/Writes.java b/src/utils/Writes.java index 16aa6984..226da0bd 100644 --- a/src/utils/Writes.java +++ b/src/utils/Writes.java @@ -412,6 +412,10 @@ public void arrayListAdd(List aList, int value) { } public void arrayListAdd(List aList, int value, boolean mockWrite, double sleep) { + if (aList instanceof ArrayVList) { + ((ArrayVList)aList).add(value, sleep, false); + return; + } allocAmount++; aList.add(value); if (mockWrite) { @@ -428,7 +432,8 @@ public void arrayListRemoveAt(List aList, int index) { } public void arrayListClear(List aList) { - allocAmount -= aList.size(); + if (!(aList instanceof ArrayVList)) + allocAmount -= aList.size(); aList.clear(); } From 47ca069ef0c400440436915ab8781c83f4f597aa Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Thu, 15 Jul 2021 18:11:19 -0500 Subject: [PATCH 3/5] Set removed values to 0 to indicate their absence --- src/sorts/hybrid/DropMergeSort.java | 1 + src/utils/ArrayVList.java | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/sorts/hybrid/DropMergeSort.java b/src/sorts/hybrid/DropMergeSort.java index 3187cfd7..71fcdde3 100644 --- a/src/sorts/hybrid/DropMergeSort.java +++ b/src/sorts/hybrid/DropMergeSort.java @@ -83,6 +83,7 @@ public void runSort(int[] array, int length, int bucketCount) { } Writes.arrayListClear(dropped); pdqSort.customSort(array, 0, length); + Writes.deleteArrayList(dropped); return; } diff --git a/src/utils/ArrayVList.java b/src/utils/ArrayVList.java index bb7a644e..69eaffbe 100644 --- a/src/utils/ArrayVList.java +++ b/src/utils/ArrayVList.java @@ -2,6 +2,7 @@ import java.util.AbstractList; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.Iterator; @@ -120,7 +121,7 @@ private void fastRemove(int index) { int numMoved = count - index - 1; if (numMoved > 0) Writes.arraycopy(internal, index + 1, internal, index, numMoved, 0, false, true); - count--; + internal[--count] = 0; Writes.changeAllocAmount(-1); } @@ -166,6 +167,8 @@ public boolean retainAll(Collection c) { @Override public void clear() { + Arrays.fill(internal, 0, count, 0); + Writes.changeAllocAmount(-count); count = 0; } @@ -194,8 +197,12 @@ protected void removeRange(int fromIndex, int toIndex) { int numMoved = count - toIndex; System.arraycopy(internal, toIndex, internal, fromIndex, numMoved); - int newSize = count - (toIndex-fromIndex); + + int sizeOffset = toIndex - fromIndex; + int newSize = count - sizeOffset; + Arrays.fill(internal, newSize, count, 0); count = newSize; + Writes.changeAllocAmount(-sizeOffset); } private void rangeCheck(int index) { From ed2c4044e19a3315827d6ce4659edb849e6474fc Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Tue, 28 Dec 2021 14:03:07 -0600 Subject: [PATCH 4/5] Add Writes.createArrayList --- src/sorts/exchange/StableQuickSort.java | 24 +++--- src/sorts/hybrid/DropMergeSort.java | 42 +++++----- src/utils/Writes.java | 100 +++++++++++++----------- 3 files changed, 87 insertions(+), 79 deletions(-) diff --git a/src/sorts/exchange/StableQuickSort.java b/src/sorts/exchange/StableQuickSort.java index e5db690f..33142959 100644 --- a/src/sorts/exchange/StableQuickSort.java +++ b/src/sorts/exchange/StableQuickSort.java @@ -7,7 +7,7 @@ import utils.ArrayVList; /* - * + * MIT License Copyright (c) 2017 Rodney Shaghoulian @@ -37,7 +37,7 @@ final public class StableQuickSort extends Sort { public StableQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Stable Quick"); this.setRunAllSortsName("Stable Quick Sort"); this.setRunSortName("Stable Quicksort"); @@ -59,23 +59,23 @@ private void copy(ArrayVList list, int [] array, int startIndex) { Highlights.markArray(1, 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 Highlights.markArray(3, start); - - ArrayVList leftList = new ArrayVList(this.length); - ArrayVList rightList = new ArrayVList(this.length); + + ArrayVList leftList = Writes.createArrayList(this.length); + ArrayVList rightList = Writes.createArrayList(this.length); 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 { // Writes.mockWrite(end - start, rightList.size(), array[i], 0.25); // Writes.arrayListAdd(rightList, array[i]); @@ -85,12 +85,12 @@ private int stablePartition(int[] array, int start, int end) { /* Recreate array */ this.copy(leftList, array, start); - + int newPivotIndex = start + leftList.size(); - + Writes.write(array, newPivotIndex, pivotValue, 0.25, false, false); Highlights.markArray(1, newPivotIndex); - + this.copy(rightList, array, newPivotIndex + 1); Writes.deleteArrayList(leftList); @@ -106,7 +106,7 @@ private void stableQuickSort(int [] array, int start, int end) { this.stableQuickSort(array, pivotIndex + 1, end); } } - + @Override public void runSort(int[] array, int length, int bucketCount) { this.length = length; diff --git a/src/sorts/hybrid/DropMergeSort.java b/src/sorts/hybrid/DropMergeSort.java index 71fcdde3..69d77051 100644 --- a/src/sorts/hybrid/DropMergeSort.java +++ b/src/sorts/hybrid/DropMergeSort.java @@ -10,7 +10,7 @@ import java.util.List; /* - * + * MIT License Copyright (c) 2020 fungamer2 and Emil Ernerfeldt Permission is hereby granted, free of charge, to any person obtaining a copy @@ -34,7 +34,7 @@ of this software and associated documentation files (the "Software"), to deal final public class DropMergeSort extends Sort { public DropMergeSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Drop Merge"); this.setRunAllSortsName("Drop Merge Sort"); this.setRunSortName("Drop Mergesort"); @@ -46,30 +46,30 @@ public DropMergeSort(ArrayVisualizer arrayVisualizer) { this.setUnreasonableLimit(0); this.setBogoSort(false); } - + private final int RECENCY = 8; private final int EARLY_OUT_TEST_AT = 4; 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(); } - + @Override public void runSort(int[] array, int length, int bucketCount) { if (length < 2) return; - + PDQBranchedSort pdqSort = new PDQBranchedSort(arrayVisualizer); - List dropped = new ArrayVList(length); - + List dropped = Writes.createArrayList(length); + int num_dropped_in_a_row = 0; int read = 0; int write = 0; - + int iteration = 0; int early_out_stop = length / EARLY_OUT_TEST_AT; - + while (read < length) { Highlights.markArray(2, read); iteration += 1; @@ -77,7 +77,7 @@ public void runSort(int[] array, int length, int bucketCount) { // We have seen a lot of the elements and dropped a lot of them. // This doesn't look good. Abort. Highlights.clearMark(2); - + for (int i = 0; i < dropped.size(); i++) { Writes.write(array, write++, dropped.get(i), 1, true, false); } @@ -86,7 +86,7 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.deleteArrayList(dropped); return; } - + if (write == 0 || Reads.compareIndices(array, read, write - 1, 0, false) >= 0) { // The element is order - keep it: Writes.write(array, write++, array[read++], 1, true, false); @@ -138,24 +138,24 @@ public void runSort(int[] array, int length, int bucketCount) { } } } - + Highlights.clearMark(2); - + for (int i = 0; i < dropped.size(); i++) { Writes.write(array, write + i, dropped.get(i), 1, true, false); } - + pdqSort.customSort(array, write, length); - - + + int[] buffer = Writes.createExternalArray(dropped.size()); - + Writes.arraycopy(array, write, buffer, 0, dropped.size(), 1, true, true); - + int i = buffer.length - 1; int j = write - 1; int k = length - 1; - + while (i >= 0) { if (j < 0 || Reads.compareValues(buffer[i], array[j]) == 1) { Writes.write(array, k--, buffer[i--], 1, true, false); @@ -164,7 +164,7 @@ public void runSort(int[] array, int length, int bucketCount) { Writes.write(array, k--, array[j--], 1, true, false); } } - + Writes.deleteArrayList(dropped); Writes.deleteExternalArray(buffer); } diff --git a/src/utils/Writes.java b/src/utils/Writes.java index 226da0bd..e80b6560 100644 --- a/src/utils/Writes.java +++ b/src/utils/Writes.java @@ -8,7 +8,7 @@ import main.ArrayVisualizer; /* - * + * MIT License Copyright (c) 2019 w0rthy @@ -43,29 +43,29 @@ final public class Writes { private volatile long auxWrites; private volatile long writes; private volatile long allocAmount; - + private DecimalFormat formatter; - + private ArrayVisualizer ArrayVisualizer; private Delays Delays; private Highlights Highlights; private Timer Timer; - + public Writes(ArrayVisualizer ArrayVisualizer) { this.reversals = 0; this.swaps = 0; this.auxWrites = 0; this.writes = 0; this.allocAmount = 0; - + this.ArrayVisualizer = ArrayVisualizer; this.Delays = ArrayVisualizer.getDelays(); this.Highlights = ArrayVisualizer.getHighlights(); this.Timer = ArrayVisualizer.getTimer(); - + this.formatter = ArrayVisualizer.getNumberFormat(); } - + public void resetStatistics() { this.reversals = 0; this.swaps = 0; @@ -73,7 +73,7 @@ public void resetStatistics() { this.writes = 0; this.allocAmount = 0; } - + public String getReversals() { if(this.reversals < 0) { this.reversals = Long.MIN_VALUE; @@ -84,7 +84,7 @@ public String getReversals() { else return this.formatter.format(this.reversals) + " Reversals"; } } - + public String getSwaps() { if(this.swaps < 0) { this.swaps = Long.MIN_VALUE; @@ -95,7 +95,7 @@ public String getSwaps() { else return this.formatter.format(this.swaps) + " Swaps"; } } - + public String getAuxWrites() { if(this.auxWrites < 0) { this.auxWrites = Long.MIN_VALUE; @@ -106,7 +106,7 @@ public String getAuxWrites() { else return this.formatter.format(this.auxWrites) + " Writes to Auxiliary Array(s)"; } } - + public String getMainWrites() { if(this.writes < 0) { this.writes = Long.MIN_VALUE; @@ -128,11 +128,11 @@ public String getAllocAmount() { else return this.formatter.format(this.allocAmount) + " Items in External Arrays"; } } - + public void changeAuxWrites(int value) { this.auxWrites += value; } - + public void changeWrites(int value) { this.writes += value; } @@ -144,11 +144,11 @@ public void changeAllocAmount(int value) { public void clearAllocAmount() { this.allocAmount = 0; } - + public void changeReversals(int value) { this.reversals += value; } - + private void updateSwap(boolean auxwrite) { this.swaps++; if(auxwrite) this.auxWrites += 2; @@ -198,10 +198,10 @@ public void multiSwap(int[] array, int pos, int to, double sleep, boolean mark, } } } - + public void reversal(int[] array, int start, int length, double sleep, boolean mark, boolean auxwrite) { this.reversals++; - + for(int i = start; i < start + ((length - start + 1) / 2); i++) { this.swap(array, i, start + length - i, sleep, mark, auxwrite); } @@ -214,16 +214,16 @@ public void write(int[] array, int at, int equals, double pause, boolean mark, b } if(mark) Highlights.markArray(1, at); - + if(auxwrite) auxWrites++; else writes++; - + Timer.startLap("Write"); - + array[at] = equals; Timer.stopLap(); - + ArrayVisualizer.updateNow(); Delays.sleep(pause); } @@ -231,15 +231,15 @@ public void write(int[] array, int at, int equals, double pause, boolean mark, b public void write(T[] array, int at, T equals, double pause, boolean mark) { if (ArrayVisualizer.sortCanceled()) throw new StopSort(); if(mark) Highlights.markArray(1, at); - + auxWrites++; - + Timer.startLap("Write"); - + array[at] = equals; Timer.stopLap(); - + ArrayVisualizer.updateNow(); Delays.sleep(pause); } @@ -247,16 +247,16 @@ public void write(T[] array, int at, T equals, double pause, boolean mark) { public void multiDimWrite(int[][] array, int x, int y, int equals, double pause, boolean mark, boolean auxwrite) { if (ArrayVisualizer.sortCanceled()) throw new StopSort(); if(mark) Highlights.markArray(1, x); - + if(auxwrite) auxWrites++; else writes++; Timer.startLap(); - + array[x][y] = equals; Timer.stopLap(); - + ArrayVisualizer.updateNow(); Delays.sleep(pause); } @@ -264,15 +264,15 @@ public void multiDimWrite(int[][] array, int x, int y, int equals, double pause, public void multiDimWrite(T[][] array, int x, int y, T equals, double pause, boolean mark) { if (ArrayVisualizer.sortCanceled()) throw new StopSort(); if(mark) Highlights.markArray(1, x); - + auxWrites++; Timer.startLap(); - + array[x][y] = equals; Timer.stopLap(); - + ArrayVisualizer.updateNow(); Delays.sleep(pause); } @@ -281,15 +281,15 @@ public void multiDimWrite(T[][] array, int x, int y, T equals, double pause, public void mockWrite(int length, int pos, int val, double pause) { if (ArrayVisualizer.sortCanceled()) throw new StopSort(); int[] mockArray = new int[length]; - + this.auxWrites++; Timer.startLap(); - + mockArray[pos] = val; Timer.stopLap(); - + Delays.sleep(pause); } @@ -312,7 +312,7 @@ public void transcribeMSD(int[] array, ArrayList[] registers, int start for(ArrayList list : registers) { total += list.size(); } - + for(int index = registers.length - 1; index >= 0; index--) { for(int i = registers[index].size() - 1; i >= 0; i--) { this.write(array, total + min - temp++ - 1, registers[index].get(i), 0, mark, auxwrite); @@ -332,12 +332,12 @@ public void fancyTranscribe(int[] array, int length, ArrayList[] regist for(int i = 0; i < length; i++) { int register = i % radix; int pos = (register * (length / radix)) + (i / radix); - + if(!tempWrite[pos]) { this.write(array, pos, tempArray[pos], 0, false, false); tempWrite[pos] = true; } - + Highlights.markArray(register, pos); if(register == 0) Delays.sleep(sleep); } @@ -346,12 +346,12 @@ public void fancyTranscribe(int[] array, int length, ArrayList[] regist this.write(array, i, tempArray[i], 0, false, false); } } - + Highlights.clearAllMarks(); this.deleteExternalArray(tempArray); } - + //Methods mocking System.arraycopy (reversearraycopy is for TimSort's MergeHi and BinaryInsert, and WikiSort's Rotate) public void arraycopy(int[] src, int srcPos, int[] dest, int destPos, int length, double sleep, boolean mark, boolean aux) { for(int i = 0; i < length; i++) { @@ -359,7 +359,7 @@ public void arraycopy(int[] src, int srcPos, int[] dest, int destPos, int length if(aux) Highlights.markArray(1, srcPos + i); else Highlights.markArray(1, destPos + i); } - + //TODO: Handle order of Delays in write method better this.write(dest, destPos + i, src[srcPos + i], sleep, false, aux); } @@ -380,18 +380,26 @@ public int[] copyOfRangeArray(int[] original, int from, int to) { ArrayVisualizer.updateNow(); return result; } - + public void reversearraycopy(int[] src, int srcPos, int[] dest, int destPos, int length, double sleep, boolean mark, boolean aux) { for(int i = length - 1; i >= 0; i--) { if(mark) { if(aux) Highlights.markArray(1, srcPos + i); else Highlights.markArray(1, destPos + i); } - + this.write(dest, destPos + i, src[srcPos + i], sleep, false, aux); } } + public ArrayVList createArrayList() { + return new ArrayVList(); + } + + public ArrayVList createArrayList(int defaultCapacity) { + return new ArrayVList(defaultCapacity); + } + public int[] createExternalArray(int length) { this.allocAmount += length; int[] result = new int[length]; @@ -450,20 +458,20 @@ public void deleteExternalArray(List[] array) { deleteArrayList(aList); } } - + //TODO: These methods should be solely controlled by Timer class public void addTime(long milliseconds) { if(Timer.timerEnabled()) Timer.manualAddTime(milliseconds); } - + public void setTime(long milliseconds) { if(Timer.timerEnabled()) Timer.manualSetTime(milliseconds); } - + public void startLap() { if(Timer.timerEnabled()) Timer.startLap(); } - + public void stopLap() { if(Timer.timerEnabled()) Timer.stopLap(); } From 8e0378ffc506a009b94a4e44f74160d6857c97ec Mon Sep 17 00:00:00 2001 From: "Josiah (Gaming32) Glosson" Date: Tue, 28 Dec 2021 14:15:32 -0600 Subject: [PATCH 5/5] Implement for more sorts --- src/sorts/exchange/StableQuickSort.java | 4 +- .../exchange/StableQuickSortMiddlePivot.java | 38 +++++++++---------- src/sorts/select/AnarchySort.java | 14 +++---- src/utils/ArrayVList.java | 4 +- 4 files changed, 29 insertions(+), 31 deletions(-) diff --git a/src/sorts/exchange/StableQuickSort.java b/src/sorts/exchange/StableQuickSort.java index 33142959..32d8af80 100644 --- a/src/sorts/exchange/StableQuickSort.java +++ b/src/sorts/exchange/StableQuickSort.java @@ -1,7 +1,5 @@ package sorts.exchange; -import java.util.ArrayList; - import main.ArrayVisualizer; import sorts.templates.Sort; import utils.ArrayVList; @@ -33,7 +31,7 @@ of this software and associated documentation files (the "Software"), to deal */ final public class StableQuickSort extends Sort { - int length; + private int length; public StableQuickSort(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); diff --git a/src/sorts/exchange/StableQuickSortMiddlePivot.java b/src/sorts/exchange/StableQuickSortMiddlePivot.java index 84688372..aafad1d0 100644 --- a/src/sorts/exchange/StableQuickSortMiddlePivot.java +++ b/src/sorts/exchange/StableQuickSortMiddlePivot.java @@ -1,12 +1,11 @@ package sorts.exchange; -import java.util.ArrayList; - import main.ArrayVisualizer; import sorts.templates.Sort; +import utils.ArrayVList; /* - * + * MIT License Copyright (c) 2017 Rodney Shaghoulian @@ -33,9 +32,11 @@ of this software and associated documentation files (the "Software"), to deal */ final public class StableQuickSortMiddlePivot extends Sort { + private int length; + public StableQuickSortMiddlePivot(ArrayVisualizer arrayVisualizer) { super(arrayVisualizer); - + this.setSortListName("Stable Quick (Middle Pivot)"); this.setRunAllSortsName("Stable Quick Sort (Middle Pivot)"); this.setRunSortName("Stable Quicksort (Middle Pivot)"); @@ -54,45 +55,43 @@ public StableQuickSortMiddlePivot(ArrayVisualizer arrayVisualizer) { // Author: Josiah Glosson // Github: github.com/gaming32 - private void copy(ArrayList 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); } } - + /* Partition/Quicksort "Stable Sort" version using O(n) space */ private int stablePartition(int[] array, int start, int end) { int pivot = start + (end - start) / 2; int pivotValue = array[pivot]; Highlights.markArray(3, start); Highlights.markArray(4, pivot); - - ArrayList leftList = new ArrayList<>(); - ArrayList rightList = new ArrayList<>(); + + ArrayVList leftList = Writes.createArrayList(this.length); + ArrayVList rightList = Writes.createArrayList(this.length); for (int i = start ; i <= end; i++) { Highlights.markArray(1, i); if (i == pivot) continue; - + if (Reads.compareValues(array[i], pivotValue) == -1) { - Writes.mockWrite(end - start, leftList.size(), array[i], 0.25); - Writes.arrayListAdd(leftList, array[i]); - } + Writes.arrayListAdd(leftList, array[i], true, 0.25); + } else { - Writes.mockWrite(end - start, rightList.size(), array[i], 0.25); - Writes.arrayListAdd(rightList, array[i]); + Writes.arrayListAdd(rightList, array[i], true, 0.25); } } /* Recreate array */ this.copy(leftList, array, start); - + int newPivotIndex = start + leftList.size(); - + Writes.write(array, newPivotIndex, pivotValue, 0.25, false, false); Highlights.markArray(1, newPivotIndex); - + this.copy(rightList, array, newPivotIndex + 1); Writes.deleteArrayList(leftList); @@ -108,9 +107,10 @@ private void stableQuickSort(int [] array, int start, int end) { this.stableQuickSort(array, pivotIndex + 1, end); } } - + @Override public void runSort(int[] array, int length, int bucketCount) { + this.length = length; this.stableQuickSort(array, 0, length - 1); } } \ No newline at end of file diff --git a/src/sorts/select/AnarchySort.java b/src/sorts/select/AnarchySort.java index 4fc5c804..9d3114dc 100644 --- a/src/sorts/select/AnarchySort.java +++ b/src/sorts/select/AnarchySort.java @@ -1,9 +1,8 @@ package sorts.select; -import java.util.ArrayList; - import main.ArrayVisualizer; import sorts.templates.Sort; +import utils.ArrayVList; public final class AnarchySort extends Sort { @@ -22,13 +21,13 @@ public AnarchySort(ArrayVisualizer arrayVisualizer) { } - private boolean containsValue(ArrayList list, int value) { + private boolean containsValue(ArrayVList list, int value) { for (int at = 0; at < list.size(); at++) { this.Delays.sleep(0.001D); this.Highlights.markArray(1, at); this.Writes.startLap(); - boolean comp = (((Integer) list.get(at)).intValue() == value); + boolean comp = list.get(at) == value; this.Writes.stopLap(); if (comp) @@ -59,7 +58,7 @@ private void convert(int[] array, int[] aux, int length) { this.Writes.write(aux, init, array[init], 0.001D, true, true); } - ArrayList t2 = new ArrayList<>(); + ArrayVList t2 = Writes.createArrayList(length); int m = 0; while (m < length) { @@ -71,14 +70,15 @@ private void convert(int[] array, int[] aux, int length) { } i++; } - this.Writes.changeAuxWrites(1); - t2.add(Integer.valueOf(j)); + t2.add(j); this.Highlights.markArray(1, j); this.Delays.sleep(1.0D); this.Writes.write(array, j, m, 1.0D, true, false); m++; } + + Writes.deleteArrayList(t2); } private void sortMainAndAux(int[] array, int[] aux, int length) { diff --git a/src/utils/ArrayVList.java b/src/utils/ArrayVList.java index 69eaffbe..e3380093 100644 --- a/src/utils/ArrayVList.java +++ b/src/utils/ArrayVList.java @@ -197,7 +197,7 @@ protected void removeRange(int fromIndex, int toIndex) { int numMoved = count - toIndex; System.arraycopy(internal, toIndex, internal, fromIndex, numMoved); - + int sizeOffset = toIndex - fromIndex; int newSize = count - sizeOffset; Arrays.fill(internal, newSize, count, 0); @@ -212,7 +212,7 @@ private void rangeCheck(int index) { @Override public void add(int index, Integer element) { - + } @Override