From c996c306a2b55c89f923d293c4332e605299302d Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Mon, 12 Feb 2024 14:39:16 -0800 Subject: [PATCH 01/33] build tests, implement arraylist --- src/ArrayList.java | 247 ++++++++++++++++++++++++++++++++++++++++ test/ArrayListTest.java | 177 ++++++++++++++++++++++++++++ 2 files changed, 424 insertions(+) create mode 100644 src/ArrayList.java create mode 100644 test/ArrayListTest.java diff --git a/src/ArrayList.java b/src/ArrayList.java new file mode 100644 index 0000000..9154dc8 --- /dev/null +++ b/src/ArrayList.java @@ -0,0 +1,247 @@ +import java.util.Iterator; + +public class ArrayList implements List { + + private static final double MAX_CAPACITY = 0.85; + private static final double MIN_CAPACITY = 0.5; + private static final int DEFAULT_BUFFER = 10; + + private E[] arrayData; + int arraySize; + + /** + * Generate an arraylist of the default buffer size + */ + public ArrayList() { + this(DEFAULT_BUFFER); + } + + /** + * Generate an array list of a specified buffer size + * @param bufsize + */ + public ArrayList(int bufsize) { + arrayData = (E[])new Object[bufsize]; + arraySize = 0; + } + + // performs resizing if too large or too small of a buffer size. + private void autoResize() { + double capacity = this.size() / arraySize; + + // grow when we reach max capacity + if (capacity > MAX_CAPACITY) grow(); + // shrink if we're below the min capacity, but the default buffer must have a size. + else if (capacity < MIN_CAPACITY && arraySize > DEFAULT_BUFFER) shrink(); + } + + // general index checker + private void checkIfInRange(int i) { + if (i < 0 || i >= arraySize) throw new IndexOutOfBoundsException(String.format("%d is not a valid index.", i)); + } + + private void grow() { + // hold old data + E[] buf = arrayData; + + // create new array of a larger size + arrayData = (E[]) new Object[buf.length + DEFAULT_BUFFER]; + + this.copy(buf, arrayData); + } + + private void shrink() { + // hold old data + E[] buf = arrayData; + + // create new array of a smaller size + arrayData = (E[]) new Object[buf.length - DEFAULT_BUFFER]; + + this.copy(buf, arrayData); + } + + private void copy(E[] from, E[] to) { + // copy old data to new array + for (int i = 0; i < from.length; i++) { + to[i] = from[i]; + } + } + + /** + * Add item to the front. + * + * @param item the item to be added + */ + @Override + public void addFront(E item) { + add(0, item); + } + + /** + * Add item to the back. + * + * @param item the item to be added + */ + @Override + public void addBack(E item) { + add(this.size(), item); + } + + /** + * Add an item at specified index (position). + * + * @param i the index where the item should be added + * @param item the item to be added + */ + @Override + public void add(int i, E item) { + // special range check, add will be able to perform addBack + if (i < 0 || i > this.size()) throw new IndexOutOfBoundsException(String.format("%d is not a valid index.", i)); + + autoResize(); + + // move all from rhs of index right by one + for (int idx = this.size(); idx > i; idx--) { + arrayData[idx] = arrayData[idx-1]; + } + + // set new value and array size + arrayData[i] = item; + arraySize++; + } + + /** + * Get the item at a specified index. + * + * @param i the index where the item should be retrieved + * @return the item located at that index + */ + @Override + public E get(int i) { + checkIfInRange(i); + return arrayData[i]; + } + + /** + * Set (save) an item at a specified index. Previous + * item at that index is overwritten. + * + * @param i the index where the item should be saved + * @param item the item to be saved + */ + @Override + public void set(int i, E item) { + checkIfInRange(i); + arrayData[i] = item; + } + + /** + * Remove item at the front of the list. + * + * @return the item that was removed + */ + @Override + public E removeFront() { + return remove(0); + } + + /** + * Remove item at the back of the list + * + * @return the item that was removed + */ + @Override + public E removeBack() { + return remove(this.size()-1); + } + + /** + * Remove item from the list + * + * @param item the item to be removed + */ + @Override + public void remove(E item) { + for (int i = 0; i < this.size(); i++) { + if (arrayData[i].equals(item)) remove(i); // call the integer type remove, since it will do the same thing once we find the index + } + } + + /** + * Remove item at a specified index. + * + * @param i the index where the item should be removed + * @return the item that was removed + */ + @Override + public E remove(int i) { + checkIfInRange(i); + + autoResize(); + + E data = arrayData[i]; + + // shift all from rhs left to shrink, adjust array size + for (int idx = i; idx < this.size(); i++) { + arrayData[idx] = arrayData[idx+1]; + } + arraySize--; + + return data; + } + + /** + * Checks if an item is in the list. + * + * @param item the item to search for + * @return true if the item is in the list, false otherwise + */ + @Override + public boolean contains(E item) { + for (int i = 0; i < arraySize; i++) + if (arrayData[i].equals(item)) return true; + return false; + } + + /** + * Checks if the list is empty. + * + * @return true if the list is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return this.size() == 0; + } + + /** + * Provides a count of the number of items in the list. + * + * @return number of items in the list + */ + @Override + public int size() { + return arraySize; + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @Override + public Iterator iterator() { + return new Iterator() { + int index = 0; + + @Override + public boolean hasNext() { + return index < arraySize; + } + + @Override + public E next() { + return arrayData[index++]; + } + }; + } +} diff --git a/test/ArrayListTest.java b/test/ArrayListTest.java new file mode 100644 index 0000000..0277db8 --- /dev/null +++ b/test/ArrayListTest.java @@ -0,0 +1,177 @@ +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class ArrayListTest { + + @Test + void add() { + ArrayList t = new ArrayList<>(); + + assertTrue(t.isEmpty()); + + // test add back functionality + t.add(0 , "test"); + assertEquals(t.size(),1); + assertEquals(t.get(0), "test"); + + // test add front functionality + t.add(0, "test2"); + assertEquals(t.size(), 2); + assertEquals(t.get(0), "test2"); + + // test add center functionality + t.add(1, "test3"); + assertEquals(t.size(), 3); + assertEquals(t.get(1), "test3"); + } + + @Test + void addFront() { + ArrayList t = new ArrayList<>(); + + t.addFront("test"); + assertEquals(t.size(), 1); + + t.addFront("test2"); + assertEquals(t.size(), 2); + assertEquals(t.get(0), "test2"); + + + } + + @Test + void addBack() { + ArrayList t = new ArrayList<>(); + t.addBack("test"); + t.addBack("test2"); + t.addBack("test3"); + + assertEquals(t.get(0), "test"); + assertEquals(t.get(2), "test3"); + + } + + @Test + void get() { + ArrayList t = new ArrayList<>(); + + t.addBack("1"); + t.addBack("2"); + t.addBack("3"); + t.addBack("4"); + + // inside array + assertEquals("3", t.get(2)); + + // case: beginning of array + assertEquals("1", t.get(0)); + + // case: end of array + assertEquals("4", t.get(3)); + + } + + @Test + void set() { + ArrayList t = new ArrayList<>(); + + t.addBack("test"); + t.addBack("test"); + t.addBack("test"); + t.addBack("test"); + + t.set(1, "set"); + + assertEquals("set", t.get(1)); + } + + @Test + void removeFront() { + ArrayList t = new ArrayList<>(); + + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + + var retval = t.removeFront(); + assertEquals(retval, "test1"); + + retval = t.removeFront(); + assertEquals(retval, "test1"); + } + + @Test + void removeBack() { + ArrayList t = new ArrayList<>(); + + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + + } + + @Test + void remove() { + ArrayList t = new ArrayList<>(); + + // + + } + + @Test + void testRemove() { + ArrayList t = new ArrayList<>(); + } + + @Test + void contains() { + ArrayList t = new ArrayList<>(); + + t.addBack(""); + t.addBack("test"); + t.addBack("toast"); + + assertTrue(t.contains("test")); + + assertFalse(t.contains("test2")); + + } + + @Test + void isEmpty() { + ArrayList t = new ArrayList<>(); + + assertTrue(t.isEmpty()); + + t.addBack(""); + + assertFalse(t.isEmpty()); + + t.removeBack(); + + assertTrue(t.isEmpty()); + + } + + @Test + void size() { + ArrayList t = new ArrayList<>(); + + assertTrue(t.isEmpty()); + + t.addBack("test"); + + assertTrue(t.size() == 1); + + t.removeBack(); + + assertTrue(t.isEmpty()); + + } + +} \ No newline at end of file From 65fc179882e5da5d67075a73fa92d39ea71c04a2 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Mon, 12 Feb 2024 14:47:30 -0800 Subject: [PATCH 02/33] fix remove, implement more arraylist tests --- src/ArrayList.java | 6 +++++- test/ArrayListTest.java | 40 +++++++++++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/ArrayList.java b/src/ArrayList.java index 9154dc8..e174fda 100644 --- a/src/ArrayList.java +++ b/src/ArrayList.java @@ -163,7 +163,11 @@ public E removeBack() { @Override public void remove(E item) { for (int i = 0; i < this.size(); i++) { - if (arrayData[i].equals(item)) remove(i); // call the integer type remove, since it will do the same thing once we find the index + if (arrayData[i].equals(item)) { + remove(i); // call the integer type remove, since it will do the same thing once we find the index + return; // we probably only want to remove one item at a time + } + } } diff --git a/test/ArrayListTest.java b/test/ArrayListTest.java index 0277db8..6d4cb32 100644 --- a/test/ArrayListTest.java +++ b/test/ArrayListTest.java @@ -112,20 +112,52 @@ void removeBack() { t.addBack("test3"); t.addBack("test4"); + var retval = t.removeBack(); + assertEquals(retval, "test4"); + retval = t.removeBack(); + assertEquals(retval, "test3"); } @Test - void remove() { + void removeByIndex() { ArrayList t = new ArrayList<>(); - // + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + // test remove inner index + var retval = t.remove(1); + assertEquals(retval, "test2"); + // test remove final index + retval = t.remove(t.size()-1); + assertEquals(retval, "test4"); + + // test remove beginning index + retval = t.remove(0); + assertEquals(retval, "test1"); } @Test - void testRemove() { + void removeByElement() { ArrayList t = new ArrayList<>(); + + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + // test removing element that does not exist + t.remove("test5"); + assertEquals(t.size(), 4); + + // test removing element that exists + t.remove("test2"); + assertEquals(t.size(), 3); + } @Test @@ -165,11 +197,9 @@ void size() { assertTrue(t.isEmpty()); t.addBack("test"); - assertTrue(t.size() == 1); t.removeBack(); - assertTrue(t.isEmpty()); } From e3d542316f4f367944029b80fab38dcbe8a9885d Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Mon, 12 Feb 2024 14:59:35 -0800 Subject: [PATCH 03/33] fix infinite loop, implement iterator tests --- src/ArrayList.java | 4 ++-- test/ArrayListTest.java | 29 ++++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/ArrayList.java b/src/ArrayList.java index e174fda..b641be9 100644 --- a/src/ArrayList.java +++ b/src/ArrayList.java @@ -27,7 +27,7 @@ public ArrayList(int bufsize) { // performs resizing if too large or too small of a buffer size. private void autoResize() { - double capacity = this.size() / arraySize; + double capacity = this.size() / arrayData.length; // grow when we reach max capacity if (capacity > MAX_CAPACITY) grow(); @@ -186,7 +186,7 @@ public E remove(int i) { E data = arrayData[i]; // shift all from rhs left to shrink, adjust array size - for (int idx = i; idx < this.size(); i++) { + for (int idx = i; idx < this.size(); idx++) { arrayData[idx] = arrayData[idx+1]; } arraySize--; diff --git a/test/ArrayListTest.java b/test/ArrayListTest.java index 6d4cb32..2e77011 100644 --- a/test/ArrayListTest.java +++ b/test/ArrayListTest.java @@ -80,10 +80,18 @@ void set() { t.addBack("test"); t.addBack("test"); t.addBack("test"); - + + // case: inner array t.set(1, "set"); - assertEquals("set", t.get(1)); + + // case: beginning of array + t.set(0, "set2"); + assertEquals("set2", t.get(0)); + + // case: end of array + t.set(3, "set3"); + assertEquals("set3", t.get(3)); } @Test @@ -100,7 +108,7 @@ void removeFront() { assertEquals(retval, "test1"); retval = t.removeFront(); - assertEquals(retval, "test1"); + assertEquals(retval, "test2"); } @Test @@ -181,11 +189,9 @@ void isEmpty() { assertTrue(t.isEmpty()); t.addBack(""); - assertFalse(t.isEmpty()); t.removeBack(); - assertTrue(t.isEmpty()); } @@ -203,5 +209,18 @@ void size() { assertTrue(t.isEmpty()); } + + @Test + void iterator() { + ArrayList t = new ArrayList<>(); + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + for (var i : t) { + assertTrue(t.contains(i)); + } + } } \ No newline at end of file From 037d4ac132bb2a42ba21063ea7792f582e226fd8 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Mon, 12 Feb 2024 16:45:33 -0800 Subject: [PATCH 04/33] fix resize method, fix tests --- src/ArrayList.java | 26 +++++++++++++++++++------- test/ArrayListTest.java | 23 ++++++++++++++++++++++- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/ArrayList.java b/src/ArrayList.java index b641be9..16514d3 100644 --- a/src/ArrayList.java +++ b/src/ArrayList.java @@ -2,7 +2,7 @@ public class ArrayList implements List { - private static final double MAX_CAPACITY = 0.85; + private static final double MAX_CAPACITY = 0.75; private static final double MIN_CAPACITY = 0.5; private static final int DEFAULT_BUFFER = 10; @@ -27,12 +27,12 @@ public ArrayList(int bufsize) { // performs resizing if too large or too small of a buffer size. private void autoResize() { - double capacity = this.size() / arrayData.length; + double capacity = this.size() / (double)arrayData.length; // grow when we reach max capacity if (capacity > MAX_CAPACITY) grow(); // shrink if we're below the min capacity, but the default buffer must have a size. - else if (capacity < MIN_CAPACITY && arraySize > DEFAULT_BUFFER) shrink(); + else if (capacity < MIN_CAPACITY && arrayData.length > DEFAULT_BUFFER) shrink(); } // general index checker @@ -43,9 +43,10 @@ private void checkIfInRange(int i) { private void grow() { // hold old data E[] buf = arrayData; + int newLength = arrayData.length + DEFAULT_BUFFER; // create new array of a larger size - arrayData = (E[]) new Object[buf.length + DEFAULT_BUFFER]; + arrayData = (E[]) new Object[newLength]; this.copy(buf, arrayData); } @@ -53,16 +54,21 @@ private void grow() { private void shrink() { // hold old data E[] buf = arrayData; + int newLength = arrayData.length - DEFAULT_BUFFER; + + // don't try if the new length is too small + if (newLength < DEFAULT_BUFFER) return; // create new array of a smaller size - arrayData = (E[]) new Object[buf.length - DEFAULT_BUFFER]; + arrayData = (E[]) new Object[newLength]; this.copy(buf, arrayData); } private void copy(E[] from, E[] to) { // copy old data to new array - for (int i = 0; i < from.length; i++) { + int shortest = (to.length < from.length) ? to.length : from.length; + for (int i = 0; i < shortest; i++) { to[i] = from[i]; } } @@ -239,13 +245,19 @@ public Iterator iterator() { @Override public boolean hasNext() { - return index < arraySize; + return index < size(); } @Override public E next() { + if (index >= size()) throw new IndexOutOfBoundsException(); return arrayData[index++]; } }; } + + // for use in testing + protected int getArraySize() { + return arrayData.length; + } } diff --git a/test/ArrayListTest.java b/test/ArrayListTest.java index 2e77011..c84f63b 100644 --- a/test/ArrayListTest.java +++ b/test/ArrayListTest.java @@ -1,9 +1,31 @@ import org.junit.jupiter.api.Test; +import java.util.Iterator; + import static org.junit.jupiter.api.Assertions.*; class ArrayListTest { + @Test + void autoResize() { + ArrayList t = new ArrayList<>(); + + for (int i = 0; i < 100; i++) { + t.addBack(String.format("test%d", i)); + } + + // should be 110ish? + assertTrue(t.getArraySize() > 100); + + var iter = t.iterator(); + while (iter.hasNext()) { + t.removeBack(); + } + + // the array should have shrunk + assertTrue(t.getArraySize() < 100); + } + @Test void add() { ArrayList t = new ArrayList<>(); @@ -36,7 +58,6 @@ void addFront() { t.addFront("test2"); assertEquals(t.size(), 2); assertEquals(t.get(0), "test2"); - } From da9c7176373f759234300cc1c4a5731bee34ae62 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Mon, 12 Feb 2024 17:00:58 -0800 Subject: [PATCH 05/33] fix iterator --- src/ArrayList.java | 10 +++++++--- test/ArrayListTest.java | 16 ++++++++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/ArrayList.java b/src/ArrayList.java index 16514d3..e70c28e 100644 --- a/src/ArrayList.java +++ b/src/ArrayList.java @@ -241,17 +241,21 @@ public int size() { @Override public Iterator iterator() { return new Iterator() { + E[] readOnly = arrayData.clone(); + int size = size(); int index = 0; @Override public boolean hasNext() { - return index < size(); + return index < size; } @Override public E next() { - if (index >= size()) throw new IndexOutOfBoundsException(); - return arrayData[index++]; + if (index >= size) throw new IndexOutOfBoundsException(); + E value = readOnly[index]; + index++; + return value; } }; } diff --git a/test/ArrayListTest.java b/test/ArrayListTest.java index c84f63b..9679e20 100644 --- a/test/ArrayListTest.java +++ b/test/ArrayListTest.java @@ -17,11 +17,19 @@ void autoResize() { // should be 110ish? assertTrue(t.getArraySize() > 100); - var iter = t.iterator(); - while (iter.hasNext()) { - t.removeBack(); - } +// var iter = t.iterator(); +// while (iter.hasNext()) { +// t.removeBack(); +// } + + for (var i: t) + t.removeFront(); + + var arraySize = t.getArraySize(); + var actual = t.size(); + + System.out.println(arraySize + " " + actual); // the array should have shrunk assertTrue(t.getArraySize() < 100); } From 45b50b1572c1c63c3a88b139b7391af51014a03f Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Mon, 12 Feb 2024 17:09:02 -0800 Subject: [PATCH 06/33] finalize arraylist --- src/ArrayList.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ArrayList.java b/src/ArrayList.java index e70c28e..102e079 100644 --- a/src/ArrayList.java +++ b/src/ArrayList.java @@ -240,10 +240,12 @@ public int size() { */ @Override public Iterator iterator() { + + E[] readOnly = arrayData.clone(); + return new Iterator() { - E[] readOnly = arrayData.clone(); - int size = size(); int index = 0; + int size = size(); @Override public boolean hasNext() { @@ -252,7 +254,7 @@ public boolean hasNext() { @Override public E next() { - if (index >= size) throw new IndexOutOfBoundsException(); + if (!hasNext()) throw new IndexOutOfBoundsException(); E value = readOnly[index]; index++; return value; From 165e4f9a49728945822bb1a4d6119d50a30f6b8c Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Mon, 12 Feb 2024 17:10:45 -0800 Subject: [PATCH 07/33] start linkedlist --- src/LinkedList.java | 142 ++++++++++++++++++++++++++++++++++++++++ test/ArrayListTest.java | 7 -- 2 files changed, 142 insertions(+), 7 deletions(-) create mode 100644 src/LinkedList.java diff --git a/src/LinkedList.java b/src/LinkedList.java new file mode 100644 index 0000000..fc558d3 --- /dev/null +++ b/src/LinkedList.java @@ -0,0 +1,142 @@ +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; + +public class LinkedList implements List { + /** + * Add item to the front. + * + * @param item the item to be added + */ + @Override + public void addFront(E item) { + + } + + /** + * Add item to the back. + * + * @param item the item to be added + */ + @Override + public void addBack(E item) { + + } + + /** + * Add an item at specified index (position). + * + * @param i the index where the item should be added + * @param item the item to be added + */ + @Override + public void add(int i, E item) { + + } + + /** + * Get the item at a specified index. + * + * @param i the index where the item should be retrieved + * @return the item located at that index + */ + @Override + public E get(int i) { + return null; + } + + /** + * Set (save) an item at a specified index. Previous + * item at that index is overwritten. + * + * @param i the index where the item should be saved + * @param item the item to be saved + */ + @Override + public void set(int i, E item) { + + } + + /** + * Remove item at the front of the list. + * + * @return the item that was removed + */ + @Override + public E removeFront() { + return null; + } + + /** + * Remove item at the back of the list + * + * @return the item that was removed + */ + @Override + public E removeBack() { + return null; + } + + /** + * Remove item from the list + * + * @param item the item to be removed + */ + @Override + public void remove(E item) { + + } + + /** + * Remove item at a specified index. + * + * @param i the index where the item should be removed + * @return the item that was removed + */ + @Override + public E remove(int i) { + return null; + } + + /** + * Checks if an item is in the list. + * + * @param item the item to search for + * @return true if the item is in the list, false otherwise + */ + @Override + public boolean contains(E item) { + return false; + } + + /** + * Checks if the list is empty. + * + * @return true if the list is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return false; + } + + /** + * Provides a count of the number of items in the list. + * + * @return number of items in the list + */ + @Override + public int size() { + return 0; + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @NotNull + @Override + public Iterator iterator() { + return null; + } +} diff --git a/test/ArrayListTest.java b/test/ArrayListTest.java index 9679e20..1250017 100644 --- a/test/ArrayListTest.java +++ b/test/ArrayListTest.java @@ -17,19 +17,12 @@ void autoResize() { // should be 110ish? assertTrue(t.getArraySize() > 100); -// var iter = t.iterator(); -// while (iter.hasNext()) { -// t.removeBack(); -// } - for (var i: t) t.removeFront(); var arraySize = t.getArraySize(); var actual = t.size(); - - System.out.println(arraySize + " " + actual); // the array should have shrunk assertTrue(t.getArraySize() < 100); } From c641e4975422eb119cb4edc7c883e4bbb19240b3 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Mon, 12 Feb 2024 20:48:28 -0800 Subject: [PATCH 08/33] convert arraylist test to linklist tests --- test/LinkedListTest.java | 224 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 test/LinkedListTest.java diff --git a/test/LinkedListTest.java b/test/LinkedListTest.java new file mode 100644 index 0000000..c23cdd2 --- /dev/null +++ b/test/LinkedListTest.java @@ -0,0 +1,224 @@ +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class LinkedListTest { + @Test + void add() { + LinkedList t = new LinkedList<>(); + + assertTrue(t.isEmpty()); + + // test add back functionality + t.add(0 , "test"); + assertEquals(t.size(),1); + assertEquals(t.get(0), "test"); + + // test add front functionality + t.add(0, "test2"); + assertEquals(t.size(), 2); + assertEquals(t.get(0), "test2"); + + // test add center functionality + t.add(1, "test3"); + assertEquals(t.size(), 3); + assertEquals(t.get(1), "test3"); + } + + @Test + void addFront() { + LinkedList t = new LinkedList<>(); + + t.addFront("test"); + assertEquals(t.size(), 1); + + t.addFront("test2"); + assertEquals(t.size(), 2); + assertEquals(t.get(0), "test2"); + + } + + @Test + void addBack() { + LinkedList t = new LinkedList<>(); + t.addBack("test"); + t.addBack("test2"); + t.addBack("test3"); + + assertEquals(t.get(0), "test"); + assertEquals(t.get(2), "test3"); + + } + + @Test + void get() { + LinkedList t = new LinkedList<>(); + + t.addBack("1"); + t.addBack("2"); + t.addBack("3"); + t.addBack("4"); + + // inside array + assertEquals("3", t.get(2)); + + // case: beginning of array + assertEquals("1", t.get(0)); + + // case: end of array + assertEquals("4", t.get(3)); + + } + + @Test + void set() { + LinkedList t = new LinkedList<>(); + + t.addBack("test"); + t.addBack("test"); + t.addBack("test"); + t.addBack("test"); + + // case: inner array + t.set(1, "set"); + assertEquals("set", t.get(1)); + + // case: beginning of array + t.set(0, "set2"); + assertEquals("set2", t.get(0)); + + // case: end of array + t.set(3, "set3"); + assertEquals("set3", t.get(3)); + } + + @Test + void removeFront() { + LinkedList t = new LinkedList<>(); + + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + + var retval = t.removeFront(); + assertEquals(retval, "test1"); + + retval = t.removeFront(); + assertEquals(retval, "test2"); + } + + @Test + void removeBack() { + LinkedList t = new LinkedList<>(); + + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + var retval = t.removeBack(); + assertEquals(retval, "test4"); + + retval = t.removeBack(); + assertEquals(retval, "test3"); + } + + @Test + void removeByIndex() { + LinkedList t = new LinkedList<>(); + + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + // test remove inner index + var retval = t.remove(1); + assertEquals(retval, "test2"); + + // test remove final index + retval = t.remove(t.size()-1); + assertEquals(retval, "test4"); + + // test remove beginning index + retval = t.remove(0); + assertEquals(retval, "test1"); + } + + @Test + void removeByElement() { + LinkedList t = new LinkedList<>(); + + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + // test removing element that does not exist + t.remove("test5"); + assertEquals(t.size(), 4); + + // test removing element that exists + t.remove("test2"); + assertEquals(t.size(), 3); + + } + + @Test + void contains() { + LinkedList t = new LinkedList<>(); + + t.addBack(""); + t.addBack("test"); + t.addBack("toast"); + + assertTrue(t.contains("test")); + + assertFalse(t.contains("test2")); + + } + + @Test + void isEmpty() { + LinkedList t = new LinkedList<>(); + + assertTrue(t.isEmpty()); + + t.addBack(""); + assertFalse(t.isEmpty()); + + t.removeBack(); + assertTrue(t.isEmpty()); + + } + + @Test + void size() { + LinkedList t = new LinkedList<>(); + + assertTrue(t.isEmpty()); + + t.addBack("test"); + assertTrue(t.size() == 1); + + t.removeBack(); + assertTrue(t.isEmpty()); + + } + + @Test + void iterator() { + LinkedList t = new LinkedList<>(); + t.addBack("test1"); + t.addBack("test2"); + t.addBack("test3"); + t.addBack("test4"); + + for (var i : t) { + assertTrue(t.contains(i)); + } + } + +} \ No newline at end of file From 42bf8f1c9307e1daa4210c90809ac54a52caf6b0 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Mon, 12 Feb 2024 20:49:30 -0800 Subject: [PATCH 09/33] implement some linkedlist methods --- src/LinkedList.java | 83 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 5 deletions(-) diff --git a/src/LinkedList.java b/src/LinkedList.java index fc558d3..5cd5585 100644 --- a/src/LinkedList.java +++ b/src/LinkedList.java @@ -3,6 +3,29 @@ import java.util.Iterator; public class LinkedList implements List { + + Node head; + int size; + + protected class Node { + Node next; + E data; + + public Node() { + this(null,null); + } + + public Node(E data) { + this(data, null); + } + + public Node(E data, Node next) { + this.data = data; + this.next = next; + } + } + + /** * Add item to the front. * @@ -10,7 +33,14 @@ public class LinkedList implements List { */ @Override public void addFront(E item) { - + // check if there is a head element + if (head == null) { + head = new Node(item); + return; + } + + // add element to front + head = new Node(item, head); } /** @@ -20,6 +50,18 @@ public void addFront(E item) { */ @Override public void addBack(E item) { + // check if there are any elements, if not, just add to front + if (head == null) { + addFront(item); + return; + } + + // wind to last element + Node cur = head; + while (cur.next != null) cur = cur.next; + + // insert new element + cur.next = new Node(item); } @@ -31,6 +73,17 @@ public void addBack(E item) { */ @Override public void add(int i, E item) { + // check if in range + if (i > size()) throw new IndexOutOfBoundsException(String.format("%d out of range", i)); + + // wind to the place we want to add. + Node cur = head; + for (int j = 0; j < i; j++) { + cur = cur.next; + } + + // insert an item after this point + cur.next = new Node(item, cur.next); } @@ -42,7 +95,13 @@ public void add(int i, E item) { */ @Override public E get(int i) { - return null; + Node cur = head; + + // wind to index + for (int j = 0; j < i; j++) + cur = cur.next; + + return cur.data; } /** @@ -116,7 +175,7 @@ public boolean contains(E item) { */ @Override public boolean isEmpty() { - return false; + return size == 0; } /** @@ -126,7 +185,7 @@ public boolean isEmpty() { */ @Override public int size() { - return 0; + return size; } /** @@ -137,6 +196,20 @@ public int size() { @NotNull @Override public Iterator iterator() { - return null; + return new Iterator() { + Node cur = head; + + @Override + public boolean hasNext() { + return cur != null; + } + + @Override + public E next() { + E data = cur.data; + cur = cur.next; + return data; + } + }; } } From 993f1bef81010ecc7d7a0bbbe04cef1ae8edb428 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Mon, 12 Feb 2024 20:59:20 -0800 Subject: [PATCH 10/33] passing linked list tests for add/get --- src/LinkedList.java | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/src/LinkedList.java b/src/LinkedList.java index 5cd5585..5d63f76 100644 --- a/src/LinkedList.java +++ b/src/LinkedList.java @@ -33,14 +33,7 @@ public Node(E data, Node next) { */ @Override public void addFront(E item) { - // check if there is a head element - if (head == null) { - head = new Node(item); - return; - } - - // add element to front - head = new Node(item, head); + add(0, item); } /** @@ -50,19 +43,7 @@ public void addFront(E item) { */ @Override public void addBack(E item) { - // check if there are any elements, if not, just add to front - if (head == null) { - addFront(item); - return; - } - - // wind to last element - Node cur = head; - while (cur.next != null) cur = cur.next; - - // insert new element - cur.next = new Node(item); - + add(size(), item); } /** @@ -74,15 +55,30 @@ public void addBack(E item) { @Override public void add(int i, E item) { // check if in range - if (i > size()) throw new IndexOutOfBoundsException(String.format("%d out of range", i)); + if (i < 0 || i > size() ) throw new IndexOutOfBoundsException(String.format("%d out of range.", i)); + + size++; + + // case: size is 0/no head + if (head == null) { + head = new Node(item); + return; + } + + // case: index 0, need to reassign head + if (i == 0) { + head = new Node(item, head); + return; + } + // case: valid index // wind to the place we want to add. Node cur = head; - for (int j = 0; j < i; j++) { + for (int j = 0; j < i - 1; j++) { cur = cur.next; } - // insert an item after this point + // insert an item at this point cur.next = new Node(item, cur.next); } From 235b02be75e837bac53d7f6664d1fc3304921eb5 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Mon, 12 Feb 2024 21:13:51 -0800 Subject: [PATCH 11/33] implement remove methods, all tests pass. --- src/LinkedList.java | 58 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/src/LinkedList.java b/src/LinkedList.java index 5d63f76..894ed3b 100644 --- a/src/LinkedList.java +++ b/src/LinkedList.java @@ -91,9 +91,12 @@ public void add(int i, E item) { */ @Override public E get(int i) { + // check if valid range + if (i < 0 || i > size() - 1) throw new IndexOutOfBoundsException(String.format("%d out of range.", i)); + Node cur = head; - // wind to index + // wind to index and return that data for (int j = 0; j < i; j++) cur = cur.next; @@ -109,6 +112,15 @@ public E get(int i) { */ @Override public void set(int i, E item) { + // check if valid range + if (i < 0 || i > size() - 1) throw new IndexOutOfBoundsException(String.format("%d out of range.", i)); + + // wind to index, set that item. + Node cur = head; + for (int j = 0; j < i; j++) + cur = cur.next; + + cur.data = item; } @@ -119,7 +131,7 @@ public void set(int i, E item) { */ @Override public E removeFront() { - return null; + return remove(0); } /** @@ -129,7 +141,7 @@ public E removeFront() { */ @Override public E removeBack() { - return null; + return remove(size()-1); } /** @@ -139,7 +151,14 @@ public E removeBack() { */ @Override public void remove(E item) { - + Node cur = head; + for (int i = 0; i < size(); i++) { + if (cur.data.equals(item)) { + remove(i); + return; + } + cur = cur.next; + } } /** @@ -150,7 +169,31 @@ public void remove(E item) { */ @Override public E remove(int i) { - return null; + // check if valid range + if (i < 0 || i > size() - 1) throw new IndexOutOfBoundsException(String.format("%d out of range.", i)); + + size--; + + // case: index is at position 0, need to reassign head + if (i == 0) { + E data = head.data; + head = head.next; + return data; + } + + // case: any other index + Node cur = head, prev = cur; + for (int j = 0; j < i; j++) { + prev = cur; + cur = cur.next; + } + + E data = cur.data; + + // remove reference to current node + prev.next = cur.next; + + return data; } /** @@ -161,6 +204,11 @@ public E remove(int i) { */ @Override public boolean contains(E item) { + Node cur = head; + for (int i = 0; i < size(); i++) { + if (cur.data.equals(item)) return true; + cur = cur.next; + } return false; } From b273ac06f05041da2e8620a456543a0098939af6 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Tue, 13 Feb 2024 16:05:33 -0800 Subject: [PATCH 12/33] add runtime analysis in JavaDocs. --- src/ArrayList.java | 19 ++++++++++++++++++- src/LinkedList.java | 15 +++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/ArrayList.java b/src/ArrayList.java index 102e079..fba4245 100644 --- a/src/ArrayList.java +++ b/src/ArrayList.java @@ -18,7 +18,7 @@ public ArrayList() { /** * Generate an array list of a specified buffer size - * @param bufsize + * @param bufsize size of the initial underlying buffer. */ public ArrayList(int bufsize) { arrayData = (E[])new Object[bufsize]; @@ -26,6 +26,9 @@ public ArrayList(int bufsize) { } // performs resizing if too large or too small of a buffer size. + // worst case: O(n), linear progression each time we need to make new spaces. + // grow/shrink are included in this + private void autoResize() { double capacity = this.size() / (double)arrayData.length; @@ -65,6 +68,7 @@ private void shrink() { this.copy(buf, arrayData); } + // O(n), linear copy. private void copy(E[] from, E[] to) { // copy old data to new array int shortest = (to.length < from.length) ? to.length : from.length; @@ -75,6 +79,7 @@ private void copy(E[] from, E[] to) { /** * Add item to the front. + * O(n) - adding a new item to the beginning means you need to look at every element * * @param item the item to be added */ @@ -85,6 +90,7 @@ public void addFront(E item) { /** * Add item to the back. + * O(n) - would be O(1) if arrays could be expanded without copying, but no luck there. * * @param item the item to be added */ @@ -95,6 +101,8 @@ public void addBack(E item) { /** * Add an item at specified index (position). + * O(n) - item added to the beginning would move the whole array. + * additionally, changes in array capacity would result in a second pass. * * @param i the index where the item should be added * @param item the item to be added @@ -118,6 +126,7 @@ public void add(int i, E item) { /** * Get the item at a specified index. + * O(1) - Access is constant in an array * * @param i the index where the item should be retrieved * @return the item located at that index @@ -131,6 +140,7 @@ public E get(int i) { /** * Set (save) an item at a specified index. Previous * item at that index is overwritten. + * O(1) - access/setting is constant * * @param i the index where the item should be saved * @param item the item to be saved @@ -153,6 +163,7 @@ public E removeFront() { /** * Remove item at the back of the list + * O(n) - changes in array capacity will result in copying all data * * @return the item that was removed */ @@ -163,6 +174,7 @@ public E removeBack() { /** * Remove item from the list + * O(n) - changes in array capacity will result in copying all data * * @param item the item to be removed */ @@ -179,6 +191,7 @@ public void remove(E item) { /** * Remove item at a specified index. + * O(n) - changes in array capacity will result in copying all data * * @param i the index where the item should be removed * @return the item that was removed @@ -202,6 +215,7 @@ public E remove(int i) { /** * Checks if an item is in the list. + * O(n) - item not present will go over whole array * * @param item the item to search for * @return true if the item is in the list, false otherwise @@ -215,6 +229,7 @@ public boolean contains(E item) { /** * Checks if the list is empty. + * O(1) - instant access to size * * @return true if the list is empty, false otherwise */ @@ -225,6 +240,7 @@ public boolean isEmpty() { /** * Provides a count of the number of items in the list. + * O(1) - instant access to size * * @return number of items in the list */ @@ -235,6 +251,7 @@ public int size() { /** * Returns an iterator over elements of type {@code T}. + * O(n) - by its nature * * @return an Iterator. */ diff --git a/src/LinkedList.java b/src/LinkedList.java index 894ed3b..6233f1c 100644 --- a/src/LinkedList.java +++ b/src/LinkedList.java @@ -28,6 +28,7 @@ public Node(E data, Node next) { /** * Add item to the front. + * O(1) - access to the front nodes are instant * * @param item the item to be added */ @@ -38,6 +39,8 @@ public void addFront(E item) { /** * Add item to the back. + * O(n) - need to scroll to the end node since we don't keep track of it. + * although we could and it would result in O(1) as well. * * @param item the item to be added */ @@ -48,6 +51,7 @@ public void addBack(E item) { /** * Add an item at specified index (position). + * O(n) - if adding to the very back, you will need to scroll the whole list. * * @param i the index where the item should be added * @param item the item to be added @@ -85,6 +89,7 @@ public void add(int i, E item) { /** * Get the item at a specified index. + * O(n) - if scrolling to the very back, will need to traverse whole list * * @param i the index where the item should be retrieved * @return the item located at that index @@ -106,6 +111,8 @@ public E get(int i) { /** * Set (save) an item at a specified index. Previous * item at that index is overwritten. + * O(n) - will need to scroll to position to set it. + * * * @param i the index where the item should be saved * @param item the item to be saved @@ -126,6 +133,7 @@ public void set(int i, E item) { /** * Remove item at the front of the list. + * O(1) - head is readily accessible. * * @return the item that was removed */ @@ -136,6 +144,7 @@ public E removeFront() { /** * Remove item at the back of the list + * O(n) - back needs to be scrolled to before removing it * * @return the item that was removed */ @@ -146,6 +155,7 @@ public E removeBack() { /** * Remove item from the list + * O(n) - item may not be present, resulting in traversing the whole list. * * @param item the item to be removed */ @@ -163,6 +173,7 @@ public void remove(E item) { /** * Remove item at a specified index. + * O(n) - need to scroll to index to find it, which may be at the end. * * @param i the index where the item should be removed * @return the item that was removed @@ -198,6 +209,7 @@ public E remove(int i) { /** * Checks if an item is in the list. + * O(n) - may not find an item, resulting in traversing the whole list. * * @param item the item to search for * @return true if the item is in the list, false otherwise @@ -214,6 +226,7 @@ public boolean contains(E item) { /** * Checks if the list is empty. + * O(1), size access is instant * * @return true if the list is empty, false otherwise */ @@ -224,6 +237,7 @@ public boolean isEmpty() { /** * Provides a count of the number of items in the list. + * O(1) - size access is instant. * * @return number of items in the list */ @@ -234,6 +248,7 @@ public int size() { /** * Returns an iterator over elements of type {@code T}. + * O(n) - traverses entire list. * * @return an Iterator. */ From e2b35f25c6f7ffe55654ecdcdb375cef4180289a Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Tue, 13 Feb 2024 16:10:07 -0800 Subject: [PATCH 13/33] format runtime analysis in JavaDocs. --- src/ArrayList.java | 18 +++++++++++++++++- src/LinkedList.java | 13 +++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/ArrayList.java b/src/ArrayList.java index fba4245..f7edc54 100644 --- a/src/ArrayList.java +++ b/src/ArrayList.java @@ -26,7 +26,9 @@ public ArrayList(int bufsize) { } // performs resizing if too large or too small of a buffer size. - // worst case: O(n), linear progression each time we need to make new spaces. + // + // O(n), linear progression each time we need to make new spaces. + // // grow/shrink are included in this private void autoResize() { @@ -79,6 +81,7 @@ private void copy(E[] from, E[] to) { /** * Add item to the front. + * * O(n) - adding a new item to the beginning means you need to look at every element * * @param item the item to be added @@ -90,6 +93,7 @@ public void addFront(E item) { /** * Add item to the back. + * * O(n) - would be O(1) if arrays could be expanded without copying, but no luck there. * * @param item the item to be added @@ -101,6 +105,7 @@ public void addBack(E item) { /** * Add an item at specified index (position). + * * O(n) - item added to the beginning would move the whole array. * additionally, changes in array capacity would result in a second pass. * @@ -126,6 +131,7 @@ public void add(int i, E item) { /** * Get the item at a specified index. + * * O(1) - Access is constant in an array * * @param i the index where the item should be retrieved @@ -140,6 +146,7 @@ public E get(int i) { /** * Set (save) an item at a specified index. Previous * item at that index is overwritten. + * * O(1) - access/setting is constant * * @param i the index where the item should be saved @@ -154,6 +161,8 @@ public void set(int i, E item) { /** * Remove item at the front of the list. * + * O(n) - removing an element from the front results in moving the whole array + * * @return the item that was removed */ @Override @@ -163,6 +172,7 @@ public E removeFront() { /** * Remove item at the back of the list + * * O(n) - changes in array capacity will result in copying all data * * @return the item that was removed @@ -174,6 +184,7 @@ public E removeBack() { /** * Remove item from the list + * * O(n) - changes in array capacity will result in copying all data * * @param item the item to be removed @@ -191,6 +202,7 @@ public void remove(E item) { /** * Remove item at a specified index. + * * O(n) - changes in array capacity will result in copying all data * * @param i the index where the item should be removed @@ -215,6 +227,7 @@ public E remove(int i) { /** * Checks if an item is in the list. + * * O(n) - item not present will go over whole array * * @param item the item to search for @@ -229,6 +242,7 @@ public boolean contains(E item) { /** * Checks if the list is empty. + * * O(1) - instant access to size * * @return true if the list is empty, false otherwise @@ -240,6 +254,7 @@ public boolean isEmpty() { /** * Provides a count of the number of items in the list. + * * O(1) - instant access to size * * @return number of items in the list @@ -251,6 +266,7 @@ public int size() { /** * Returns an iterator over elements of type {@code T}. + * * O(n) - by its nature * * @return an Iterator. diff --git a/src/LinkedList.java b/src/LinkedList.java index 6233f1c..0f8844c 100644 --- a/src/LinkedList.java +++ b/src/LinkedList.java @@ -28,6 +28,7 @@ public Node(E data, Node next) { /** * Add item to the front. + * * O(1) - access to the front nodes are instant * * @param item the item to be added @@ -39,6 +40,7 @@ public void addFront(E item) { /** * Add item to the back. + * * O(n) - need to scroll to the end node since we don't keep track of it. * although we could and it would result in O(1) as well. * @@ -51,6 +53,7 @@ public void addBack(E item) { /** * Add an item at specified index (position). + * * O(n) - if adding to the very back, you will need to scroll the whole list. * * @param i the index where the item should be added @@ -89,6 +92,7 @@ public void add(int i, E item) { /** * Get the item at a specified index. + * * O(n) - if scrolling to the very back, will need to traverse whole list * * @param i the index where the item should be retrieved @@ -111,6 +115,7 @@ public E get(int i) { /** * Set (save) an item at a specified index. Previous * item at that index is overwritten. + * * O(n) - will need to scroll to position to set it. * * @@ -133,6 +138,7 @@ public void set(int i, E item) { /** * Remove item at the front of the list. + * * O(1) - head is readily accessible. * * @return the item that was removed @@ -144,6 +150,7 @@ public E removeFront() { /** * Remove item at the back of the list + * * O(n) - back needs to be scrolled to before removing it * * @return the item that was removed @@ -155,6 +162,7 @@ public E removeBack() { /** * Remove item from the list + * * O(n) - item may not be present, resulting in traversing the whole list. * * @param item the item to be removed @@ -173,6 +181,7 @@ public void remove(E item) { /** * Remove item at a specified index. + * * O(n) - need to scroll to index to find it, which may be at the end. * * @param i the index where the item should be removed @@ -209,6 +218,7 @@ public E remove(int i) { /** * Checks if an item is in the list. + * * O(n) - may not find an item, resulting in traversing the whole list. * * @param item the item to search for @@ -226,6 +236,7 @@ public boolean contains(E item) { /** * Checks if the list is empty. + * * O(1), size access is instant * * @return true if the list is empty, false otherwise @@ -237,6 +248,7 @@ public boolean isEmpty() { /** * Provides a count of the number of items in the list. + * * O(1) - size access is instant. * * @return number of items in the list @@ -248,6 +260,7 @@ public int size() { /** * Returns an iterator over elements of type {@code T}. + * * O(n) - traverses entire list. * * @return an Iterator. From 1062e4aaabef7ce950889949243bd0b13e1b50bb Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Tue, 13 Feb 2024 16:27:30 -0800 Subject: [PATCH 14/33] clarification on BigO --- src/LinkedList.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/LinkedList.java b/src/LinkedList.java index 0f8844c..60c6567 100644 --- a/src/LinkedList.java +++ b/src/LinkedList.java @@ -163,7 +163,9 @@ public E removeBack() { /** * Remove item from the list * - * O(n) - item may not be present, resulting in traversing the whole list. + * O(n) - this implementation calls remove twice, + * but is guaranteed to pass no more than twice. + * thus is it 2n, not BigO Squared. * * @param item the item to be removed */ From b77a8bb1d82b0eaef6d2d2e3d873744b36b24867 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Wed, 14 Feb 2024 02:13:50 -0800 Subject: [PATCH 15/33] Implement Dequeue. not yet tested. --- src/DequeImpl.java | 212 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 src/DequeImpl.java diff --git a/src/DequeImpl.java b/src/DequeImpl.java new file mode 100644 index 0000000..c6f85c2 --- /dev/null +++ b/src/DequeImpl.java @@ -0,0 +1,212 @@ +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class DequeImpl implements Deque { + + int size; + Node head, tail; + + private class Node { + E data; + Node prev, next; + + public Node(E data) { + this(data, null, null); + } + + public Node(E data, Node prev, Node next) { + this.data = data; + this.prev = prev; + this.next = next; + } + } + + /** + * Checks if the deque is empty. + * + * O(1), size access is recorded during node creation/deletion + * + * @return true if the deque is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Returns the number of items in the deque. + * + * O(1), size access is constant + * + * @return number of items in the deque + */ + @Override + public int size() { + return size; + } + + /** + * Add an item to the left end of the deque. + * + * @param item item to be added + */ + @Override + public void pushLeft(E item) { + // case: size is 0, need to assign new head and tail + if (size == 0) { + head = tail = new Node(item); + size++; + return; + } + + // case: size is 1, we need to decouple head and tail and make them point to each other + else if (size == 1) { + head = new Node(item, null, tail); + tail.prev = head; + size++; + return; + } + + // case: any other size + else { + head = head.next = new Node(item, null, head); + } + + size++; + } + + /** + * Add an item to the right end of the deque. + * O(1), adding right is instant + * @param item + */ + @Override + public void pushRight(E item) { + // case: size is 0, need to assign new head and tail + if (size == 0) { + head = tail = new Node(item); + size++; + } + + // case: size is 1, we need to decouple head and tail and make them point to each other + else if (size == 1) { + tail = new Node(item, null, head); + head.next = tail; + } + + // case: any other size + else { + + tail = tail.next = new Node(item, tail, null); + } + size++; + } + + /** + * Remove an item from the left end of the deque. + * + * O(1), left access is instant + * + * @return + */ + @Override + public E popLeft() { + if (head == null) throw new NoSuchElementException("No elements left in queue."); + + E data = head.data; + + size--; + + // case: size is 0, the resulting dequeue will be null; + if (size == 0) { + head = tail = null; + } + + // case: size is 1, head will point to tail. + else if (size == 1) { + head = tail; + + // erase references to prev/next + head.next = head.prev = null; + } + + // case: any other size + else { + // move head up one node + head = head.next; + //and null its reference to the previous node + head.prev = null; + } + + return data; + } + + /** + * Remove an item from the right end of the deque. + * + * O(1), contrast to something like a linked list, we can instantly access the right end of a dequeue + * + * @return + */ + @Override + public E popRight() { + if (tail == null) throw new NoSuchElementException("No elements left in queue."); + + E data = tail.data; + + size--; + + // case: size is 0, the resulting dequeue will be null; + if (size == 0) { + head = tail = null; + } + + // case: size is 1, tail will point to head. + else if (size == 1) { + tail = head; + + // erase references to prev/next + // dont really need to change anything here. head and tail are the same now + head.next = head.prev = null; + } + + // case: any other size + else { + // move head back one node + tail = tail.prev; + // and null its reference to the next node + tail.next = null; + } + + return data; + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * O(n), as usual, an iterator will always pass a list once and once only unless break occurs. + * + * @return an Iterator. + */ + @NotNull + @Override + public Iterator iterator() { + return new Iterator() { + Node cur = head; + + @Override + public boolean hasNext() { + return cur != null; + } + + @Override + public E next() { + E data = cur.data; + cur = cur.next; + return data; + } + }; + } +} From 4cdca56c9eb7601cdf2f949fc6564fcc661a63e0 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 13:42:05 -0800 Subject: [PATCH 16/33] implement stack, queue. --- src/QueueImpl.java | 103 +++++++++++++++++++++++++++++++++++++++++++ src/StackImpl.java | 107 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 210 insertions(+) create mode 100644 src/QueueImpl.java create mode 100644 src/StackImpl.java diff --git a/src/QueueImpl.java b/src/QueueImpl.java new file mode 100644 index 0000000..f5efa7b --- /dev/null +++ b/src/QueueImpl.java @@ -0,0 +1,103 @@ +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class QueueImpl implements Queue { + + int size; + Node head; + + private class Node { + E data; + + Node next; + + public Node(E data) { + this(data, null); + } + + public Node(E data, Node next) { + this.data = data; + this.next = next; + } + } + /** + * Add an item to the queue. + * + * @param item the item to be added + */ + @Override + public void enqueue(E item) { + size++; + head = new Node(item, head); + } + + /** + * Remove an item from the queue. + * + * @return the item that was removed + */ + @Override + public E dequeue() { + + if (size == 0) throw new NoSuchElementException(); + + size--; + + E data = head.data; + head = head.next; + + return data; + } + + /** + * Checks to see if the queue is empty. + * + * @return true if the queue is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Returns a count of the number of items in the queue. + * + * @return the number of items in the queue + */ + @Override + public int size() { + return size; + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * Most implementations of queues I find have no iterator... so should this move forward or backward? + * should it pop elements or simply read them? + * + * @return an Iterator. + */ + @NotNull + @Override + public Iterator iterator() { + return new Iterator() { + Node cur = head; + + @Override + public boolean hasNext() { + return !isEmpty(); + } + + @Override + public E next() { + if (!hasNext()) throw new NoSuchElementException(); + + E data = cur.data; + cur = cur.next; + return data; + } + }; + } +} diff --git a/src/StackImpl.java b/src/StackImpl.java new file mode 100644 index 0000000..b49035c --- /dev/null +++ b/src/StackImpl.java @@ -0,0 +1,107 @@ +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class StackImpl implements Stack { + + int size; + Node tail; + + private class Node { + E data; + + Node prev; + + public Node(E data) { + this(data, null); + } + + public Node(E data, Node prev) { + this.data = data; + this.prev = prev; + } + } + + /** + * Add an item to the stack. + * + * @param item the item to be added + */ + @Override + public void push(E item) { + tail = new Node(item, tail); + } + + /** + * Removes the most recently added item from the stack. + * + * @return the item that was removed + */ + @Override + public E pop() { + if (tail == null) throw new NoSuchElementException(); + size--; + E data = tail.data; + tail = tail.prev; + return data; + } + + /** + * Returns the item at the top of the stack. + * Does not modify the stack or the item at the top. + * + * @return item at the top of the stack. + */ + @Override + public E peek() { + if (tail == null) throw new NoSuchElementException(); + return tail.data; + } + + /** + * Checks to see if the stack is empty. + * + * @return true if the stack is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Returns a count of the number of items in the stack. + * + * @return the number of items in the stack + */ + @Override + public int size() { + return size; + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @NotNull + @Override + public Iterator iterator() { + return new Iterator() { + Node cur = tail; + @Override + public boolean hasNext() { + return cur != null; + } + + @Override + public E next() { + if (!hasNext()) throw new NoSuchElementException(); + + E data = cur.data; + cur = cur.prev; + return data; + } + }; + } +} From deb6d2dd5633f226033841dd0f611a693f66b84b Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 14:07:10 -0800 Subject: [PATCH 17/33] generate tests --- src/QueueImpl.java | 25 +++++++++++++++++++++---- test/DequeImplTest.java | 34 ++++++++++++++++++++++++++++++++++ test/QueueImplTest.java | 26 ++++++++++++++++++++++++++ test/StackImplTest.java | 30 ++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 test/DequeImplTest.java create mode 100644 test/QueueImplTest.java create mode 100644 test/StackImplTest.java diff --git a/src/QueueImpl.java b/src/QueueImpl.java index f5efa7b..3496470 100644 --- a/src/QueueImpl.java +++ b/src/QueueImpl.java @@ -6,7 +6,7 @@ public class QueueImpl implements Queue { int size; - Node head; + Node head, tail; private class Node { E data; @@ -25,17 +25,29 @@ public Node(E data, Node next) { /** * Add an item to the queue. * + * O(1), adding to a queue is instant if we keep track of the head and tail. + * * @param item the item to be added */ @Override public void enqueue(E item) { + // case: size is 0, create head and tail + if (size == 0) { + head = tail = new Node(item); + } + // case: any other size, add to back + else { + tail = tail.next = new Node(item, tail); + } + size++; - head = new Node(item, head); } /** * Remove an item from the queue. * + * O(1), dequeuing is instant and involves no loops. + * * @return the item that was removed */ @Override @@ -45,6 +57,7 @@ public E dequeue() { size--; + // dequeuing should be generally safe unless trying to access something that isn't there. E data = head.data; head = head.next; @@ -54,6 +67,8 @@ public E dequeue() { /** * Checks to see if the queue is empty. * + * O(1), size access is instant + * * @return true if the queue is empty, false otherwise */ @Override @@ -64,6 +79,8 @@ public boolean isEmpty() { /** * Returns a count of the number of items in the queue. * + * O(1), size access is instant + * * @return the number of items in the queue */ @Override @@ -74,8 +91,8 @@ public int size() { /** * Returns an iterator over elements of type {@code T}. * - * Most implementations of queues I find have no iterator... so should this move forward or backward? - * should it pop elements or simply read them? + * Most implementations of queues I find have no iterator. + * O(n) - guaranteed to be O(n) if you iterate through the list once * * @return an Iterator. */ diff --git a/test/DequeImplTest.java b/test/DequeImplTest.java new file mode 100644 index 0000000..15ca9a3 --- /dev/null +++ b/test/DequeImplTest.java @@ -0,0 +1,34 @@ +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class DequeImplTest { + + @Test + void isEmpty() { + } + + @Test + void size() { + } + + @Test + void pushLeft() { + } + + @Test + void pushRight() { + } + + @Test + void popLeft() { + } + + @Test + void popRight() { + } + + @Test + void iterator() { + } +} \ No newline at end of file diff --git a/test/QueueImplTest.java b/test/QueueImplTest.java new file mode 100644 index 0000000..c1fd0ba --- /dev/null +++ b/test/QueueImplTest.java @@ -0,0 +1,26 @@ +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class QueueImplTest { + + @Test + void enqueue() { + } + + @Test + void dequeue() { + } + + @Test + void isEmpty() { + } + + @Test + void size() { + } + + @Test + void iterator() { + } +} \ No newline at end of file diff --git a/test/StackImplTest.java b/test/StackImplTest.java new file mode 100644 index 0000000..93138d1 --- /dev/null +++ b/test/StackImplTest.java @@ -0,0 +1,30 @@ +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class StackImplTest { + + @Test + void push() { + } + + @Test + void pop() { + } + + @Test + void peek() { + } + + @Test + void isEmpty() { + } + + @Test + void size() { + } + + @Test + void iterator() { + } +} \ No newline at end of file From e0feb433e4838ed8c6b55fdb8e3808f4fa3ac302 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 14:49:48 -0800 Subject: [PATCH 18/33] create and generate tests for mathset --- src/MathSetImpl.java | 150 ++++++++++++++++++++++++++++++++++++++ test/MathSetImplTest.java | 58 +++++++++++++++ 2 files changed, 208 insertions(+) create mode 100644 src/MathSetImpl.java create mode 100644 test/MathSetImplTest.java diff --git a/src/MathSetImpl.java b/src/MathSetImpl.java new file mode 100644 index 0000000..93ff8fc --- /dev/null +++ b/src/MathSetImpl.java @@ -0,0 +1,150 @@ +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; + +public class MathSetImpl> implements MathSet { + /** + * Adds a key (item) to the set. Duplicate items + * are not added. + * + * @param key the key (item) to be added + */ + @Override + public void add(E key) { + + } + + /** + * Removes a key (item) from the set. + * + * @param key the key (item) to be removed + */ + @Override + public void remove(E key) { + + } + + /** + * Checks if a key (item) is an element in the set. + * + * @param key the key (item) to check + * @return true if the key is in the set, false otherise + */ + @Override + public boolean contains(E key) { + return false; + } + + /** + * Checks if this set is equal to another set. + * + * @param other the set to compare this set against + * @return true if this set is equal to the other set + */ + @Override + public boolean equals(MathSet other) { + return false; + } + + /** + * Checks if this set is a subset of another set. + * + * @param other the set to compare this set against + * @return true if this set is a subset of the other set + */ + @Override + public boolean isSubsetOf(MathSet other) { + return false; + } + + /** + * Checks if this set is a proper subset of another set. + * + * @param other the set to compare this set against + * @return true if this set is a proper subset of the other set + */ + @Override + public boolean isProperSubsetOf(MathSet other) { + return false; + } + + /** + * Computes the union of this set and another specified set. + * Does not change the contents of this set. + * + * @param other the second set for the operation + * @return new MathSet that contains the union + */ + @Override + public MathSet union(MathSet other) { + return null; + } + + /** + * Computes the intersection of this set and another specified set. + * Does not change the contents of this set. + * + * @param other the second set for the operation + * @return new MathSet that contains the intersection + */ + @Override + public MathSet intersection(MathSet other) { + return null; + } + + /** + * Computes the difference of this set and another specified set. + * Does not change the contents of this set. + * + * @param other the second set for the operation + * @return new MathSet that contains the difference + */ + @Override + public MathSet difference(MathSet other) { + return null; + } + + /** + * Computes the symmetric difference of this set and another specified set. + * Does not change the contents of this set. + * + * @param other the second set for the operation + * @return new MathSet that contains the symmetric difference + */ + @Override + public MathSet symmetricDifference(MathSet other) { + return null; + } + + /** + * Checks if this set is empty. + * + * @return true if this set is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return false; + } + + /** + * Returns a count of the number of keys (elements) in this set + * also known as the cardinality of the set. + * + * @return number of keys (elements) in this set. + */ + @Override + public int size() { + return 0; + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @NotNull + @Override + public Iterator iterator() { + return null; + } +} diff --git a/test/MathSetImplTest.java b/test/MathSetImplTest.java new file mode 100644 index 0000000..35461aa --- /dev/null +++ b/test/MathSetImplTest.java @@ -0,0 +1,58 @@ +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class MathSetImplTest { + + @Test + void add() { + } + + @Test + void remove() { + } + + @Test + void contains() { + } + + @Test + void testEquals() { + } + + @Test + void isSubsetOf() { + } + + @Test + void isProperSubsetOf() { + } + + @Test + void union() { + } + + @Test + void intersection() { + } + + @Test + void difference() { + } + + @Test + void symmetricDifference() { + } + + @Test + void isEmpty() { + } + + @Test + void size() { + } + + @Test + void iterator() { + } +} \ No newline at end of file From 4c3299010d79ef87444a4bf11ca55cc11542cc2b Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 15:25:24 -0800 Subject: [PATCH 19/33] fix deque --- src/DequeImpl.java | 38 ++++++------ test/DequeImplTest.java | 126 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 21 deletions(-) diff --git a/src/DequeImpl.java b/src/DequeImpl.java index c6f85c2..719c5cf 100644 --- a/src/DequeImpl.java +++ b/src/DequeImpl.java @@ -5,8 +5,8 @@ public class DequeImpl implements Deque { - int size; - Node head, tail; + private int size; + private Node head, tail; private class Node { E data; @@ -57,24 +57,20 @@ public void pushLeft(E item) { // case: size is 0, need to assign new head and tail if (size == 0) { head = tail = new Node(item); - size++; - return; } // case: size is 1, we need to decouple head and tail and make them point to each other else if (size == 1) { - head = new Node(item, null, tail); - tail.prev = head; - size++; - return; + tail.prev = head = new Node(item, null, tail); } // case: any other size else { - head = head.next = new Node(item, null, head); + head = head.prev = new Node(item, null, head); } size++; + } /** @@ -87,20 +83,20 @@ public void pushRight(E item) { // case: size is 0, need to assign new head and tail if (size == 0) { head = tail = new Node(item); - size++; } - // case: size is 1, we need to decouple head and tail and make them point to each other + // case: size is 1, adding one we need to decouple head and tail and make them point to each other else if (size == 1) { - tail = new Node(item, null, head); - head.next = tail; + head.next = tail = new Node(item, head, null); } // case: any other size else { - tail = tail.next = new Node(item, tail, null); + + } + size++; } @@ -134,9 +130,9 @@ else if (size == 1) { // case: any other size else { - // move head up one node + // move right one node head = head.next; - //and null its reference to the previous node + // and null its reference to the previous node head.prev = null; } @@ -165,18 +161,17 @@ public E popRight() { // case: size is 1, tail will point to head. else if (size == 1) { - tail = head; + tail=head; - // erase references to prev/next - // dont really need to change anything here. head and tail are the same now - head.next = head.prev = null; + // erase references to next + tail.next = tail.prev = null; } // case: any other size else { // move head back one node tail = tail.prev; - // and null its reference to the next node + tail.next = null; } @@ -203,6 +198,7 @@ public boolean hasNext() { @Override public E next() { + if (!hasNext()) throw new NoSuchElementException(); E data = cur.data; cur = cur.next; return data; diff --git a/test/DequeImplTest.java b/test/DequeImplTest.java index 15ca9a3..8025c6f 100644 --- a/test/DequeImplTest.java +++ b/test/DequeImplTest.java @@ -1,34 +1,160 @@ import org.junit.jupiter.api.Test; +import java.util.Deque; +import java.util.Iterator; +import java.util.NoSuchElementException; + import static org.junit.jupiter.api.Assertions.*; class DequeImplTest { @Test void isEmpty() { + DequeImpl deque = new DequeImpl<>(); + + assertTrue(deque.isEmpty()); + + deque.pushLeft(""); + assertFalse(deque.isEmpty()); + + deque.popLeft(); + assertTrue(deque.isEmpty()); + } @Test void size() { + DequeImpl deque = new DequeImpl<>(); + + assertEquals(deque.size(), 0); + + deque.pushLeft(""); + assertEquals(deque.size(), 1); + + deque.popLeft(); + assertEquals(deque.size(), 0); + } @Test void pushLeft() { + DequeImpl deque = new DequeImpl<>(); + + // from a 0 sized deque + deque.pushLeft("1"); + assertEquals(deque.size(), 1); + + // from a 1 sized deque + deque.pushLeft("2"); + assertEquals(deque.size(), 2); + + // from a n>1 sized deque + deque.pushLeft("3"); + assertEquals(deque.size(), 3); + } @Test void pushRight() { + DequeImpl deque = new DequeImpl<>(); + + // from a 0 sized deque + deque.pushRight("1"); + assertEquals(deque.size(), 1); + + // from a 1 sized deque + deque.pushRight("2"); + assertEquals(deque.size(), 2); + + // from a n>1 sized deque + deque.pushRight("3"); + assertEquals(deque.size(), 3); } @Test void popLeft() { + DequeImpl deque = new DequeImpl<>(); + + deque.pushLeft("1"); + // 1 + + deque.pushLeft("2"); + // 2 1 + + deque.pushLeft("3"); + // 3 2 1 + + deque.pushRight("2"); + // 3 2 1 2 + + deque.pushRight("1"); + // 3 2 1 2 1 + + + // n>1 sized deque + var n = deque.popLeft(); + assertEquals("3", n); + n = deque.popLeft(); + assertEquals("2", n); + n = deque.popLeft(); + assertEquals("1", n); + + // 2 elements left, resulting in a 1 sized data structure + n = deque.popLeft(); + assertEquals("2", n); + assertEquals(1, deque.size()); + + // 1 element left + n = deque.popLeft(); + assertEquals("1", n); + + assertTrue(deque.isEmpty()); + + + } @Test void popRight() { + DequeImpl deque = new DequeImpl<>(); + + deque.pushRight("1"); + // 1 + deque.pushRight("2"); + // 1 2 + deque.pushRight("3"); + // 1 2 3 + deque.pushLeft("2"); + // 2 1 2 3 + deque.pushLeft("1"); + // 1 2 1 2 3 + + // n>1 sized deque + var n = deque.popRight(); + assertEquals("3", n); + n = deque.popRight(); + assertEquals("2", n); + n = deque.popRight(); + assertEquals("1", n); + + // 2 elements left, resulting in a 1 sized data structure + n = deque.popRight(); + assertEquals("2", n); + assertEquals(1, deque.size()); + + // 1 element left + n = deque.popRight(); + assertEquals("1", n); + + assertTrue(deque.isEmpty()); } @Test void iterator() { + assertThrows( NoSuchElementException.class, () -> { + DequeImpl deque = new DequeImpl<>(); + var it = deque.iterator(); + it.next(); + }); } } \ No newline at end of file From ea6fd47c5912e8b2e125f11b4b513335348d34f2 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 16:50:21 -0800 Subject: [PATCH 20/33] fix stack size --- src/StackImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/StackImpl.java b/src/StackImpl.java index b49035c..1398f87 100644 --- a/src/StackImpl.java +++ b/src/StackImpl.java @@ -31,6 +31,7 @@ public Node(E data, Node prev) { @Override public void push(E item) { tail = new Node(item, tail); + size++; } /** From 28254bfbaa8cc7b3a5f18b8b2f75aee3f909fafc Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 16:50:43 -0800 Subject: [PATCH 21/33] implement stack tests --- test/DequeImplTest.java | 2 -- test/StackImplTest.java | 73 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/test/DequeImplTest.java b/test/DequeImplTest.java index 8025c6f..eba5de1 100644 --- a/test/DequeImplTest.java +++ b/test/DequeImplTest.java @@ -110,8 +110,6 @@ void popLeft() { assertTrue(deque.isEmpty()); - - } @Test diff --git a/test/StackImplTest.java b/test/StackImplTest.java index 93138d1..2b7f656 100644 --- a/test/StackImplTest.java +++ b/test/StackImplTest.java @@ -1,30 +1,103 @@ import org.junit.jupiter.api.Test; +import java.util.NoSuchElementException; + import static org.junit.jupiter.api.Assertions.*; class StackImplTest { @Test void push() { + StackImpl stack = new StackImpl<>(); + + assertEquals(stack.size(), 0); + + stack.push("1"); + assertEquals(stack.size(), 1); + + stack.push("1"); + assertEquals(stack.size(), 2); } @Test void pop() { + StackImpl stack = new StackImpl<>(); + + stack.push("1"); + stack.push("2"); + + assertEquals(2, stack.size()); + + var n = stack.pop(); + assertEquals("2", n); + assertEquals(1, stack.size()); + + n = stack.pop(); + assertEquals("1", n); + assertEquals(0, stack.size()); + } @Test void peek() { + StackImpl stack = new StackImpl<>(); + + stack.push("1"); + stack.push("2"); + + assertEquals(2, stack.size()); + + // test peek top element + var n = stack.peek(); + assertEquals("2", n); + assertEquals(2, stack.size()); + + // test popping stack and then peeking the next value + stack.pop(); + n = stack.peek(); + assertEquals("1", n); + assertEquals(1, stack.size()); + } @Test void isEmpty() { + StackImpl stack = new StackImpl<>(); + + assertTrue(stack.isEmpty()); + + stack.push("1"); + assertFalse(stack.isEmpty()); + + stack.pop(); + assertTrue(stack.isEmpty()); } @Test void size() { + StackImpl stack = new StackImpl<>(); + + assertEquals(0, stack.size()); + + stack.push(""); + assertEquals(1, stack.size()); + + stack.push(""); + assertEquals(2, stack.size()); + + stack.pop(); + assertEquals(1, stack.size()); + + stack.pop(); + assertEquals(0, stack.size()); } @Test void iterator() { + assertThrows( NoSuchElementException.class, () -> { + StackImpl stack = new StackImpl<>(); + var it = stack.iterator(); + it.next(); + }); } } \ No newline at end of file From bb7e53f86ff88aadb540a1a4d57cf47804af1013 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 16:57:16 -0800 Subject: [PATCH 22/33] implement queue tests --- test/QueueImplTest.java | 61 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/test/QueueImplTest.java b/test/QueueImplTest.java index c1fd0ba..e415817 100644 --- a/test/QueueImplTest.java +++ b/test/QueueImplTest.java @@ -1,26 +1,87 @@ import org.junit.jupiter.api.Test; +import java.util.NoSuchElementException; + import static org.junit.jupiter.api.Assertions.*; class QueueImplTest { @Test void enqueue() { + QueueImpl queue = new QueueImpl<>(); + + assertEquals(0, queue.size()); + + queue.enqueue(""); + assertEquals(1, queue.size()); + + queue.enqueue(""); + assertEquals(2, queue.size()); + + queue.enqueue(""); + assertEquals(3, queue.size()); } @Test void dequeue() { + QueueImpl queue = new QueueImpl<>(); + + queue.enqueue("1"); + queue.enqueue("2"); + queue.enqueue("3"); + queue.enqueue("4"); + + var n = queue.dequeue(); + assertEquals("1", n); + assertEquals(3, queue.size()); + + n = queue.dequeue(); + assertEquals("2", n); + assertEquals(2, queue.size()); + + n = queue.dequeue(); + assertEquals("3", n); + assertEquals(1, queue.size()); + + n = queue.dequeue(); + assertEquals("4", n); + assertEquals(0, queue.size()); + } @Test void isEmpty() { + QueueImpl queue = new QueueImpl<>(); + + assertTrue(queue.isEmpty()); + + queue.enqueue(""); + assertFalse(queue.isEmpty()); + + queue.dequeue(); + assertTrue(queue.isEmpty()); } @Test void size() { + QueueImpl queue = new QueueImpl<>(); + + assertEquals(0, queue.size()); + + queue.enqueue(""); + assertEquals(1, queue.size()); + + queue.dequeue(); + assertEquals(0, queue.size()); + } @Test void iterator() { + assertThrows( NoSuchElementException.class, () -> { + QueueImpl queue = new QueueImpl<>(); + var it = queue.iterator(); + it.next(); + }); } } \ No newline at end of file From 533021c74cf89f45fd6e10ca1ee76e55152cd243 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 17:19:51 -0800 Subject: [PATCH 23/33] rename implementations --- src/{QueueImpl.java => LinkedQueue.java} | 2 +- src/{StackImpl.java => LinkedStack.java} | 2 +- test/{QueueImplTest.java => LinkedQueueTest.java} | 12 ++++++------ test/{StackImplTest.java => LinkedStackTest.java} | 14 +++++++------- 4 files changed, 15 insertions(+), 15 deletions(-) rename src/{QueueImpl.java => LinkedQueue.java} (98%) rename src/{StackImpl.java => LinkedStack.java} (97%) rename test/{QueueImplTest.java => LinkedQueueTest.java} (83%) rename test/{StackImplTest.java => LinkedStackTest.java} (82%) diff --git a/src/QueueImpl.java b/src/LinkedQueue.java similarity index 98% rename from src/QueueImpl.java rename to src/LinkedQueue.java index 3496470..598ea9f 100644 --- a/src/QueueImpl.java +++ b/src/LinkedQueue.java @@ -3,7 +3,7 @@ import java.util.Iterator; import java.util.NoSuchElementException; -public class QueueImpl implements Queue { +public class LinkedQueue implements Queue { int size; Node head, tail; diff --git a/src/StackImpl.java b/src/LinkedStack.java similarity index 97% rename from src/StackImpl.java rename to src/LinkedStack.java index 1398f87..90cdf44 100644 --- a/src/StackImpl.java +++ b/src/LinkedStack.java @@ -3,7 +3,7 @@ import java.util.Iterator; import java.util.NoSuchElementException; -public class StackImpl implements Stack { +public class LinkedStack implements Stack { int size; Node tail; diff --git a/test/QueueImplTest.java b/test/LinkedQueueTest.java similarity index 83% rename from test/QueueImplTest.java rename to test/LinkedQueueTest.java index e415817..5d08c77 100644 --- a/test/QueueImplTest.java +++ b/test/LinkedQueueTest.java @@ -4,11 +4,11 @@ import static org.junit.jupiter.api.Assertions.*; -class QueueImplTest { +class LinkedQueueTest { @Test void enqueue() { - QueueImpl queue = new QueueImpl<>(); + LinkedQueue queue = new LinkedQueue<>(); assertEquals(0, queue.size()); @@ -24,7 +24,7 @@ void enqueue() { @Test void dequeue() { - QueueImpl queue = new QueueImpl<>(); + LinkedQueue queue = new LinkedQueue<>(); queue.enqueue("1"); queue.enqueue("2"); @@ -51,7 +51,7 @@ void dequeue() { @Test void isEmpty() { - QueueImpl queue = new QueueImpl<>(); + LinkedQueue queue = new LinkedQueue<>(); assertTrue(queue.isEmpty()); @@ -64,7 +64,7 @@ void isEmpty() { @Test void size() { - QueueImpl queue = new QueueImpl<>(); + LinkedQueue queue = new LinkedQueue<>(); assertEquals(0, queue.size()); @@ -79,7 +79,7 @@ void size() { @Test void iterator() { assertThrows( NoSuchElementException.class, () -> { - QueueImpl queue = new QueueImpl<>(); + LinkedQueue queue = new LinkedQueue<>(); var it = queue.iterator(); it.next(); }); diff --git a/test/StackImplTest.java b/test/LinkedStackTest.java similarity index 82% rename from test/StackImplTest.java rename to test/LinkedStackTest.java index 2b7f656..91733f5 100644 --- a/test/StackImplTest.java +++ b/test/LinkedStackTest.java @@ -4,11 +4,11 @@ import static org.junit.jupiter.api.Assertions.*; -class StackImplTest { +class LinkedStackTest { @Test void push() { - StackImpl stack = new StackImpl<>(); + LinkedStack stack = new LinkedStack<>(); assertEquals(stack.size(), 0); @@ -21,7 +21,7 @@ void push() { @Test void pop() { - StackImpl stack = new StackImpl<>(); + LinkedStack stack = new LinkedStack<>(); stack.push("1"); stack.push("2"); @@ -40,7 +40,7 @@ void pop() { @Test void peek() { - StackImpl stack = new StackImpl<>(); + LinkedStack stack = new LinkedStack<>(); stack.push("1"); stack.push("2"); @@ -62,7 +62,7 @@ void peek() { @Test void isEmpty() { - StackImpl stack = new StackImpl<>(); + LinkedStack stack = new LinkedStack<>(); assertTrue(stack.isEmpty()); @@ -75,7 +75,7 @@ void isEmpty() { @Test void size() { - StackImpl stack = new StackImpl<>(); + LinkedStack stack = new LinkedStack<>(); assertEquals(0, stack.size()); @@ -95,7 +95,7 @@ void size() { @Test void iterator() { assertThrows( NoSuchElementException.class, () -> { - StackImpl stack = new StackImpl<>(); + LinkedStack stack = new LinkedStack<>(); var it = stack.iterator(); it.next(); }); From 7e84951500cc8f249cb39c7cb7769b75e7cd65d3 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 17:55:11 -0800 Subject: [PATCH 24/33] implement Bag --- src/Bag.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/Bag.java diff --git a/src/Bag.java b/src/Bag.java new file mode 100644 index 0000000..e21bf60 --- /dev/null +++ b/src/Bag.java @@ -0,0 +1,19 @@ +public interface Bag extends Iterable { + /** + * Adds an item to the bag + * @param item An item of the generic type. + */ + public void add(E item); + + /** + * Returns true if the bag has no items. + * @return true if empty. + */ + public boolean isEmpty(); + + /** + * Gets the amount of items in the bag. + * @return size + */ + public int size(); +} From 38d65958c8d40d63d4debf31b5e62d5b508ce337 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 18:13:34 -0800 Subject: [PATCH 25/33] implement Bag tests, fix iterator --- src/LinkedBag.java | 91 +++++++++++++++++++++++++++++++++++++++++ test/LinkedBagTest.java | 70 +++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 src/LinkedBag.java create mode 100644 test/LinkedBagTest.java diff --git a/src/LinkedBag.java b/src/LinkedBag.java new file mode 100644 index 0000000..be5ec46 --- /dev/null +++ b/src/LinkedBag.java @@ -0,0 +1,91 @@ +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class LinkedBag implements Bag { + + int size; + Node head, tail; + + private class Node { + E data; + + Node next; + + public Node (E data) { + this.data = data; + this.next = null; + } + } + + /** + * Adds an item to the bag + * + * O(1), because we keep track of the tail end, we can always add to it without searching for it. + * + * @param item An item of the generic type. + */ + @Override + public void add(E item) { + // case: Bag is empty, create head + if (this.isEmpty()) { + tail = head = new Node(item); + } + // case: bag has elements, add element to tail end + else { + tail = tail.next = new Node(item); + } + size++; + } + + + /** + * Returns true if the bag has no items. + * + * O(1), empty access is instant + * + * @return true if empty. + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Gets the amount of items in the bag. + * + * O(1), size access is instant + * + * @return size + */ + @Override + public int size() { + return size; + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @NotNull + @Override + public Iterator iterator() { + return new Iterator() { + Node cur = head; + @Override + public boolean hasNext() { + return cur != null; + } + + @Override + public E next() { + if (!hasNext()) throw new NoSuchElementException(); + E data = cur.data; + cur = cur.next; + return data; + } + }; + } +} diff --git a/test/LinkedBagTest.java b/test/LinkedBagTest.java new file mode 100644 index 0000000..ee868d8 --- /dev/null +++ b/test/LinkedBagTest.java @@ -0,0 +1,70 @@ +import org.junit.jupiter.api.Test; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import static org.junit.jupiter.api.Assertions.*; + +class LinkedBagTest { + + @Test + void add() { + Bag bag = new LinkedBag<>(); + + assertTrue(bag.isEmpty()); + + bag.add("item"); + assertEquals(1,bag.size()); + + bag.add("item"); + assertEquals(2,bag.size()); + + } + + @Test + void isEmpty() { + Bag bag = new LinkedBag<>(); + + assertTrue(bag.isEmpty()); + + bag.add("item"); + assertFalse(bag.isEmpty()); + } + + @Test + void size() { + Bag bag = new LinkedBag<>(); + + assertEquals(0,bag.size()); + + bag.add("item"); + assertEquals(1,bag.size()); + + bag.add("item2"); + assertEquals(2,bag.size()); + } + + @Test + void iterator() { + Bag bag = new LinkedBag<>(); + + bag.add("1"); + bag.add("2"); + bag.add("3"); + + Iterator it = bag.iterator(); + + var n = it.next(); + assertEquals("1", n); + + n = it.next(); + assertEquals("2", n); + + n = it.next(); + assertEquals("3", n); + + assertThrows(NoSuchElementException.class, it::next); + + + } +} \ No newline at end of file From 060ab9c27f4fdd9086c95145647142f24f9ff1f1 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 18:45:24 -0800 Subject: [PATCH 26/33] implement resizingarraystack, add tests from linkedstack --- src/ResizingArrayStack.java | 173 +++++++++++++++++++++++++++++++ test/ResizingArrayStackTest.java | 138 ++++++++++++++++++++++++ 2 files changed, 311 insertions(+) create mode 100644 src/ResizingArrayStack.java create mode 100644 test/ResizingArrayStackTest.java diff --git a/src/ResizingArrayStack.java b/src/ResizingArrayStack.java new file mode 100644 index 0000000..70e6fba --- /dev/null +++ b/src/ResizingArrayStack.java @@ -0,0 +1,173 @@ +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class ResizingArrayStack implements Stack { + + private final int DEFAULT_BUFFER = 10; + private final double MAX_CAPACITY = 0.75; + + private final double MIN_CAPACITY = 0.5; + + private E[] stack; + private int size; + + public ResizingArrayStack() { + this.stack = (E[]) new Object[DEFAULT_BUFFER]; + this.size = 0; + } + + protected int getArraySize() { + return stack.length; + } + + private void autoResize() { + double capacity = this.size() / (double)stack.length; + + // grow when we reach max capacity + if (capacity > MAX_CAPACITY) grow(); + // shrink if we're below the min capacity, but the default buffer must have a size. + else if (capacity < MIN_CAPACITY && stack.length > DEFAULT_BUFFER) shrink(); + } + + private void grow() { + // hold old data + E[] buf = stack; + int newLength = stack.length + DEFAULT_BUFFER; + + // create new array of a larger size + stack = (E[]) new Object[newLength]; + + this.copy(buf, stack); + } + + private void shrink() { + // hold old data + E[] buf = stack; + int newLength = stack.length - DEFAULT_BUFFER; + + // don't try if the new length is too small + if (newLength < DEFAULT_BUFFER) return; + + // create new array of a smaller size + stack = (E[]) new Object[newLength]; + + this.copy(buf, stack); + } + + // O(n), linear copy. + private void copy(E[] from, E[] to) { + // copy old data to new array + int shortest = (to.length < from.length) ? to.length : from.length; + for (int i = 0; i < shortest; i++) { + to[i] = from[i]; + } + } + + /** + * Add an item to the stack. + * + * O(n) - if the buffer is full, we need to copy the whole stack + * + * @param item the item to be added + */ + @Override + public void push(E item) { + autoResize(); + + // add item, grow size + stack[size] = item; + size++; + } + + /** + * Removes the most recently added item from the stack. + * + * O(n) - if the buffer is too large, need to copy array + * + * @return the item that was removed + */ + @Override + public E pop() { + if (this.isEmpty()) throw new NoSuchElementException(); + + autoResize(); + + // grab data and lower size + E data = stack[size-1]; + size--; + return data; + } + + /** + * Returns the item at the top of the stack. + * Does not modify the stack or the item at the top. + * + * O(1) - access to peek is instant + * + * @return item at the top of the stack. + */ + @Override + public E peek() { + if (this.isEmpty()) throw new NoSuchElementException(); + return stack[size-1]; + } + + /** + * Checks to see if the stack is empty. + * + * O(1) - instant access + * + * @return true if the stack is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Returns a count of the number of items in the stack. + * + * O(1) - access to size is instant + * + * @return the number of items in the stack + */ + @Override + public int size() { + return size; + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * O(n) - always n elements unless you break early. + * + * @return an Iterator. + */ + @NotNull + @Override + public Iterator iterator() { + return new Iterator() { + int it = 0; + + E[] readonly = stack.clone(); + + int readonly_size = size(); + + + @Override + public boolean hasNext() { + return it < readonly_size; + } + + @Override + public E next() { + if (!hasNext()) throw new NoSuchElementException(); + E data = readonly[it]; + it++; + return data; + } + }; + } +} diff --git a/test/ResizingArrayStackTest.java b/test/ResizingArrayStackTest.java new file mode 100644 index 0000000..1b29bd9 --- /dev/null +++ b/test/ResizingArrayStackTest.java @@ -0,0 +1,138 @@ +import org.junit.jupiter.api.Test; + +import java.util.NoSuchElementException; + +import static org.junit.jupiter.api.Assertions.*; + +class ResizingArrayStackTest { + + @Test + void arrayWillResizeOnMaxCapacity() { + ResizingArrayStack stack = new ResizingArrayStack<>(); + + assertDoesNotThrow( () -> { + for (int i = 0; i < 100; i++) { + stack.push("" + i); + } + }); + + assertTrue(stack.getArraySize() > 100); + } + + @Test + void arrayWillResizeOnMinCapacity() { + ResizingArrayStack stack = new ResizingArrayStack<>(); + + assertDoesNotThrow( () -> { + for (int i = 0; i < 100; i++) { + stack.push("" + i); + } + }); + + for ( var v : stack ) { + stack.pop(); + } + + assertTrue( stack.getArraySize() < 100); + } + + + + @Test + void push() { + ResizingArrayStack stack = new ResizingArrayStack<>(); + + assertEquals(stack.size(), 0); + + stack.push("1"); + assertEquals(stack.size(), 1); + + stack.push("1"); + assertEquals(stack.size(), 2); + + } + + @Test + void pop() { + ResizingArrayStack stack = new ResizingArrayStack<>(); + + stack.push("1"); + stack.push("2"); + + assertEquals(2, stack.size()); + + var n = stack.pop(); + assertEquals("2", n); + assertEquals(1, stack.size()); + + n = stack.pop(); + assertEquals("1", n); + assertEquals(0, stack.size()); + + } + + @Test + void peek() { + ResizingArrayStack stack = new ResizingArrayStack<>(); + + stack.push("1"); + stack.push("2"); + + assertEquals(2, stack.size()); + + // test peek top element + var n = stack.peek(); + assertEquals("2", n); + assertEquals(2, stack.size()); + + // test popping stack and then peeking the next value + stack.pop(); + n = stack.peek(); + assertEquals("1", n); + assertEquals(1, stack.size()); + + } + + @Test + void isEmpty() { + ResizingArrayStack stack = new ResizingArrayStack<>(); + + assertTrue(stack.isEmpty()); + + stack.push("1"); + assertFalse(stack.isEmpty()); + + stack.pop(); + assertTrue(stack.isEmpty()); + } + + @Test + void size() { + ResizingArrayStack stack = new ResizingArrayStack<>(); + + assertEquals(0, stack.size()); + + stack.push(""); + assertEquals(1, stack.size()); + + stack.push(""); + assertEquals(2, stack.size()); + + stack.pop(); + assertEquals(1, stack.size()); + + stack.pop(); + assertEquals(0, stack.size()); + } + + + + @Test + void iterator() { + assertThrows( NoSuchElementException.class, () -> { + ResizingArrayStack stack = new ResizingArrayStack<>(); + var it = stack.iterator(); + it.next(); + }); + } +} \ No newline at end of file From 9eeca8e47dfeb0adead615c059ceaeb80460e92d Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 18:46:25 -0800 Subject: [PATCH 27/33] change finals to static --- src/ResizingArrayStack.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ResizingArrayStack.java b/src/ResizingArrayStack.java index 70e6fba..5c2f276 100644 --- a/src/ResizingArrayStack.java +++ b/src/ResizingArrayStack.java @@ -5,10 +5,10 @@ public class ResizingArrayStack implements Stack { - private final int DEFAULT_BUFFER = 10; - private final double MAX_CAPACITY = 0.75; + private static final int DEFAULT_BUFFER = 10; + private static final double MAX_CAPACITY = 0.75; - private final double MIN_CAPACITY = 0.5; + private static final double MIN_CAPACITY = 0.5; private E[] stack; private int size; From 620c4b3576177be6dd269ef9eb6f8c7c0ec7e79c Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 19:58:09 -0800 Subject: [PATCH 28/33] add Stat preview file --- src/Stats.java | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/Stats.java diff --git a/src/Stats.java b/src/Stats.java new file mode 100644 index 0000000..ef8d154 --- /dev/null +++ b/src/Stats.java @@ -0,0 +1,38 @@ +import java.util.Scanner; + +/** + * Previews LinkedBag + * + * @author R.J. Trenchard + * @date 2/15/2024 + */ + +public class Stats { + public static void main(String[] args) { + Scanner in = new Scanner("100 99 101 120 98 107 109 81 101 90"); + + Bag numbers = new LinkedBag<>(); + + while (in.hasNextDouble()) { + numbers.add(in.nextDouble()); + } + + int n = numbers.size(); + + double sum = 0f; + + for (double num : numbers) { + sum += num; + } + + double mean = sum / n; + + sum = 0.0; + for (double num : numbers) { + sum += (num - mean) * (num - mean); + } + double stddev = Math.sqrt(sum/(n-1)); + + System.out.printf("Mean: %.2f\nStddev: %.2f", mean, stddev); + } +} From 9b46961511dcb1ecf86c288584517175b7e4fdf4 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 19:58:32 -0800 Subject: [PATCH 29/33] formatting --- src/ArrayList.java | 4 +++- src/DequeImpl.java | 9 +++++++++ src/LinkedBag.java | 1 + src/LinkedList.java | 12 +++++++++--- src/LinkedQueue.java | 4 ++-- src/LinkedStack.java | 12 +++++++++--- 6 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/ArrayList.java b/src/ArrayList.java index f7edc54..546c289 100644 --- a/src/ArrayList.java +++ b/src/ArrayList.java @@ -42,7 +42,9 @@ private void autoResize() { // general index checker private void checkIfInRange(int i) { - if (i < 0 || i >= arraySize) throw new IndexOutOfBoundsException(String.format("%d is not a valid index.", i)); + if (i < 0 || i >= arraySize) { + throw new IndexOutOfBoundsException(String.format("%d is not a valid index.", i)); + } } private void grow() { diff --git a/src/DequeImpl.java b/src/DequeImpl.java index 719c5cf..3e080dc 100644 --- a/src/DequeImpl.java +++ b/src/DequeImpl.java @@ -1,3 +1,12 @@ +/** + * Double-ended Queue implementation + * + * Can add and remove from both sides of the queue. + * + * @author R.J. Trenchard + * @date 2/15/2024 + */ + import org.jetbrains.annotations.NotNull; import java.util.Iterator; diff --git a/src/LinkedBag.java b/src/LinkedBag.java index be5ec46..c60449f 100644 --- a/src/LinkedBag.java +++ b/src/LinkedBag.java @@ -82,6 +82,7 @@ public boolean hasNext() { @Override public E next() { if (!hasNext()) throw new NoSuchElementException(); + E data = cur.data; cur = cur.next; return data; diff --git a/src/LinkedList.java b/src/LinkedList.java index 60c6567..a7e9ddb 100644 --- a/src/LinkedList.java +++ b/src/LinkedList.java @@ -1,6 +1,7 @@ import org.jetbrains.annotations.NotNull; import java.util.Iterator; +import java.util.NoSuchElementException; public class LinkedList implements List { @@ -106,8 +107,9 @@ public E get(int i) { Node cur = head; // wind to index and return that data - for (int j = 0; j < i; j++) + for (int j = 0; j < i; j++) { cur = cur.next; + } return cur.data; } @@ -129,8 +131,9 @@ public void set(int i, E item) { // wind to index, set that item. Node cur = head; - for (int j = 0; j < i; j++) + for (int j = 0; j < i; j++) { cur = cur.next; + } cur.data = item; @@ -230,7 +233,9 @@ public E remove(int i) { public boolean contains(E item) { Node cur = head; for (int i = 0; i < size(); i++) { - if (cur.data.equals(item)) return true; + if (cur.data.equals(item)) { + return true; + } cur = cur.next; } return false; @@ -280,6 +285,7 @@ public boolean hasNext() { @Override public E next() { + if (!hasNext()) throw new NoSuchElementException(); E data = cur.data; cur = cur.next; return data; diff --git a/src/LinkedQueue.java b/src/LinkedQueue.java index 598ea9f..6662ee2 100644 --- a/src/LinkedQueue.java +++ b/src/LinkedQueue.java @@ -52,12 +52,12 @@ public void enqueue(E item) { */ @Override public E dequeue() { - + // check if there's anything in the queue if (size == 0) throw new NoSuchElementException(); size--; - // dequeuing should be generally safe unless trying to access something that isn't there. + // dequeuing should be generally safe E data = head.data; head = head.next; diff --git a/src/LinkedStack.java b/src/LinkedStack.java index 90cdf44..6306597 100644 --- a/src/LinkedStack.java +++ b/src/LinkedStack.java @@ -41,7 +41,9 @@ public void push(E item) { */ @Override public E pop() { - if (tail == null) throw new NoSuchElementException(); + if (tail == null) { + throw new NoSuchElementException(); + } size--; E data = tail.data; tail = tail.prev; @@ -56,7 +58,9 @@ public E pop() { */ @Override public E peek() { - if (tail == null) throw new NoSuchElementException(); + if (tail == null) { + throw new NoSuchElementException(); + } return tail.data; } @@ -97,7 +101,9 @@ public boolean hasNext() { @Override public E next() { - if (!hasNext()) throw new NoSuchElementException(); + if (!hasNext()) { + throw new NoSuchElementException(); + } E data = cur.data; cur = cur.prev; From 5778ee73a5a77f3373752110a66cfa2537501ba3 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 20:01:58 -0800 Subject: [PATCH 30/33] formatting --- src/ResizingArrayStack.java | 38 ++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/src/ResizingArrayStack.java b/src/ResizingArrayStack.java index 5c2f276..ef2fcef 100644 --- a/src/ResizingArrayStack.java +++ b/src/ResizingArrayStack.java @@ -1,3 +1,12 @@ +/** + * Resizing Array Stack + * + * This stack uses a built in array to store its data. + * + * @author R.J. Trenchard + * @date 2/15/2024 + */ + import org.jetbrains.annotations.NotNull; import java.util.Iterator; @@ -18,17 +27,24 @@ public ResizingArrayStack() { this.size = 0; } + // for testing protected int getArraySize() { return stack.length; } + // resizes the array when capacity is overfull or underfull private void autoResize() { double capacity = this.size() / (double)stack.length; // grow when we reach max capacity - if (capacity > MAX_CAPACITY) grow(); - // shrink if we're below the min capacity, but the default buffer must have a size. - else if (capacity < MIN_CAPACITY && stack.length > DEFAULT_BUFFER) shrink(); + if (capacity > MAX_CAPACITY) { + grow(); + } + + // shrink if we're below the min capacity, but the default buffer must have a size. + else if (capacity < MIN_CAPACITY && stack.length > DEFAULT_BUFFER) { + shrink(); + } } private void grow() { @@ -48,7 +64,9 @@ private void shrink() { int newLength = stack.length - DEFAULT_BUFFER; // don't try if the new length is too small - if (newLength < DEFAULT_BUFFER) return; + if (newLength < DEFAULT_BUFFER) { + return; + } // create new array of a smaller size stack = (E[]) new Object[newLength]; @@ -90,7 +108,9 @@ public void push(E item) { */ @Override public E pop() { - if (this.isEmpty()) throw new NoSuchElementException(); + if (this.isEmpty()) { + throw new NoSuchElementException(); + } autoResize(); @@ -110,7 +130,9 @@ public E pop() { */ @Override public E peek() { - if (this.isEmpty()) throw new NoSuchElementException(); + if (this.isEmpty()) { + throw new NoSuchElementException(); + } return stack[size-1]; } @@ -163,7 +185,9 @@ public boolean hasNext() { @Override public E next() { - if (!hasNext()) throw new NoSuchElementException(); + if (!hasNext()) { + throw new NoSuchElementException(); + } E data = readonly[it]; it++; return data; From 073dc66c289cf390fbdf73134620f4d6bfe22689 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 20:16:33 -0800 Subject: [PATCH 31/33] comment headers --- src/ArrayList.java | 9 ++++++--- src/Bag.java | 13 ++++++++++--- src/DequeImpl.java | 8 ++++---- src/LinkedBag.java | 11 ++++++++++- src/LinkedList.java | 20 +++++++++++++++----- src/LinkedQueue.java | 12 +++++++++++- src/LinkedStack.java | 20 +++++++++++++++----- src/MathSetImpl.java | 7 +++++++ src/ResizingArrayStack.java | 6 +++--- test/DequeImplTest.java | 2 -- 10 files changed, 81 insertions(+), 27 deletions(-) diff --git a/src/ArrayList.java b/src/ArrayList.java index 546c289..53e3c8f 100644 --- a/src/ArrayList.java +++ b/src/ArrayList.java @@ -1,3 +1,5 @@ +import org.jetbrains.annotations.NotNull; + import java.util.Iterator; public class ArrayList implements List { @@ -75,7 +77,7 @@ private void shrink() { // O(n), linear copy. private void copy(E[] from, E[] to) { // copy old data to new array - int shortest = (to.length < from.length) ? to.length : from.length; + int shortest = Math.min(to.length, from.length); for (int i = 0; i < shortest; i++) { to[i] = from[i]; } @@ -273,14 +275,15 @@ public int size() { * * @return an Iterator. */ + @NotNull @Override public Iterator iterator() { E[] readOnly = arrayData.clone(); - return new Iterator() { + return new Iterator<>() { int index = 0; - int size = size(); + final int size = size(); @Override public boolean hasNext() { diff --git a/src/Bag.java b/src/Bag.java index e21bf60..12d2092 100644 --- a/src/Bag.java +++ b/src/Bag.java @@ -1,19 +1,26 @@ +/** + * Bag interface only supports adding and iterating. + * + * @param Type to be added + * @author R.J. Trenchard + */ + public interface Bag extends Iterable { /** * Adds an item to the bag * @param item An item of the generic type. */ - public void add(E item); + void add(E item); /** * Returns true if the bag has no items. * @return true if empty. */ - public boolean isEmpty(); + boolean isEmpty(); /** * Gets the amount of items in the bag. * @return size */ - public int size(); + int size(); } diff --git a/src/DequeImpl.java b/src/DequeImpl.java index 3e080dc..f9a0305 100644 --- a/src/DequeImpl.java +++ b/src/DequeImpl.java @@ -85,7 +85,7 @@ else if (size == 1) { /** * Add an item to the right end of the deque. * O(1), adding right is instant - * @param item + * @param item item to add */ @Override public void pushRight(E item) { @@ -114,7 +114,7 @@ else if (size == 1) { * * O(1), left access is instant * - * @return + * @return the item on the left end of the queue */ @Override public E popLeft() { @@ -153,7 +153,7 @@ else if (size == 1) { * * O(1), contrast to something like a linked list, we can instantly access the right end of a dequeue * - * @return + * @return the item on the right end of the queue */ @Override public E popRight() { @@ -197,7 +197,7 @@ else if (size == 1) { @NotNull @Override public Iterator iterator() { - return new Iterator() { + return new Iterator<>() { Node cur = head; @Override diff --git a/src/LinkedBag.java b/src/LinkedBag.java index c60449f..72c1cc6 100644 --- a/src/LinkedBag.java +++ b/src/LinkedBag.java @@ -1,3 +1,12 @@ +/** + * Linked Bag implementation + * + * Bag uses linked nodes to store its data + * + * @author R.J. trenchard + * 2/15/2024 + */ + import org.jetbrains.annotations.NotNull; import java.util.Iterator; @@ -72,7 +81,7 @@ public int size() { @NotNull @Override public Iterator iterator() { - return new Iterator() { + return new Iterator<>() { Node cur = head; @Override public boolean hasNext() { diff --git a/src/LinkedList.java b/src/LinkedList.java index a7e9ddb..01bc055 100644 --- a/src/LinkedList.java +++ b/src/LinkedList.java @@ -1,3 +1,12 @@ +/** + * List implementation with linked nodes + * + * Allows adding elements without resizing in chunks + * + * @author R.J. Trenchard + * 2/15/2024 + */ + import org.jetbrains.annotations.NotNull; import java.util.Iterator; @@ -12,10 +21,6 @@ protected class Node { Node next; E data; - public Node() { - this(null,null); - } - public Node(E data) { this(data, null); } @@ -26,6 +31,11 @@ public Node(E data, Node next) { } } + public LinkedList() { + head = null; + size = 0; + } + /** * Add item to the front. @@ -275,7 +285,7 @@ public int size() { @NotNull @Override public Iterator iterator() { - return new Iterator() { + return new Iterator<>() { Node cur = head; @Override diff --git a/src/LinkedQueue.java b/src/LinkedQueue.java index 6662ee2..123bf2e 100644 --- a/src/LinkedQueue.java +++ b/src/LinkedQueue.java @@ -1,3 +1,13 @@ +/** + * LinkedQueue implementation + * + * This queue uses linked nodes to store data, both a head and a tail + * for quick access to enqueuing to the back, and dequeuing from the front. + * + * @author R.J. Trenchard + * 2/15/2024 + */ + import org.jetbrains.annotations.NotNull; import java.util.Iterator; @@ -99,7 +109,7 @@ public int size() { @NotNull @Override public Iterator iterator() { - return new Iterator() { + return new Iterator<>() { Node cur = head; @Override diff --git a/src/LinkedStack.java b/src/LinkedStack.java index 6306597..70f8b95 100644 --- a/src/LinkedStack.java +++ b/src/LinkedStack.java @@ -1,3 +1,12 @@ +/** + * Linked Stack + * + * Stack that uses linked nodes to store its data + * + * @author R.J. Trenchard + * 2/15/2024 + */ + import org.jetbrains.annotations.NotNull; import java.util.Iterator; @@ -13,16 +22,17 @@ private class Node { Node prev; - public Node(E data) { - this(data, null); - } - public Node(E data, Node prev) { this.data = data; this.prev = prev; } } + public LinkedStack() { + tail = null; + size = 0; + } + /** * Add an item to the stack. * @@ -92,7 +102,7 @@ public int size() { @NotNull @Override public Iterator iterator() { - return new Iterator() { + return new Iterator<>() { Node cur = tail; @Override public boolean hasNext() { diff --git a/src/MathSetImpl.java b/src/MathSetImpl.java index 93ff8fc..40bc571 100644 --- a/src/MathSetImpl.java +++ b/src/MathSetImpl.java @@ -1,3 +1,10 @@ +/** + * In progress + * + * @author R.J. Trenchard + * 2/15/2024 + */ + import org.jetbrains.annotations.NotNull; import java.util.Iterator; diff --git a/src/ResizingArrayStack.java b/src/ResizingArrayStack.java index ef2fcef..80bdbed 100644 --- a/src/ResizingArrayStack.java +++ b/src/ResizingArrayStack.java @@ -170,12 +170,12 @@ public int size() { @NotNull @Override public Iterator iterator() { - return new Iterator() { + return new Iterator<>() { int it = 0; - E[] readonly = stack.clone(); + final E[] readonly = stack.clone(); - int readonly_size = size(); + final int readonly_size = size(); @Override diff --git a/test/DequeImplTest.java b/test/DequeImplTest.java index eba5de1..4097474 100644 --- a/test/DequeImplTest.java +++ b/test/DequeImplTest.java @@ -1,7 +1,5 @@ import org.junit.jupiter.api.Test; -import java.util.Deque; -import java.util.Iterator; import java.util.NoSuchElementException; import static org.junit.jupiter.api.Assertions.*; From b1de871355fa346a943b020cd42a09f2ffca8b94 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 20:24:34 -0800 Subject: [PATCH 32/33] Beautify --- src/ArrayList.java | 22 ++++++++-------------- src/DequeImpl.java | 8 +------- src/LinkedBag.java | 5 +---- src/LinkedList.java | 14 -------------- src/LinkedQueue.java | 8 +------- src/LinkedStack.java | 1 - src/ResizingArrayStack.java | 11 ++--------- src/Stats.java | 2 +- test/MathSetImplTest.java | 2 +- 9 files changed, 15 insertions(+), 58 deletions(-) diff --git a/src/ArrayList.java b/src/ArrayList.java index 53e3c8f..b0225be 100644 --- a/src/ArrayList.java +++ b/src/ArrayList.java @@ -1,3 +1,11 @@ +/** + * ArrayList + * List that uses a built-in array to store its data + * + * @author R.J. Trenchard + * 2/15/2024 + */ + import org.jetbrains.annotations.NotNull; import java.util.Iterator; @@ -28,7 +36,6 @@ public ArrayList(int bufsize) { } // performs resizing if too large or too small of a buffer size. - // // O(n), linear progression each time we need to make new spaces. // // grow/shrink are included in this @@ -85,7 +92,6 @@ private void copy(E[] from, E[] to) { /** * Add item to the front. - * * O(n) - adding a new item to the beginning means you need to look at every element * * @param item the item to be added @@ -97,7 +103,6 @@ public void addFront(E item) { /** * Add item to the back. - * * O(n) - would be O(1) if arrays could be expanded without copying, but no luck there. * * @param item the item to be added @@ -109,7 +114,6 @@ public void addBack(E item) { /** * Add an item at specified index (position). - * * O(n) - item added to the beginning would move the whole array. * additionally, changes in array capacity would result in a second pass. * @@ -135,7 +139,6 @@ public void add(int i, E item) { /** * Get the item at a specified index. - * * O(1) - Access is constant in an array * * @param i the index where the item should be retrieved @@ -150,7 +153,6 @@ public E get(int i) { /** * Set (save) an item at a specified index. Previous * item at that index is overwritten. - * * O(1) - access/setting is constant * * @param i the index where the item should be saved @@ -164,7 +166,6 @@ public void set(int i, E item) { /** * Remove item at the front of the list. - * * O(n) - removing an element from the front results in moving the whole array * * @return the item that was removed @@ -176,7 +177,6 @@ public E removeFront() { /** * Remove item at the back of the list - * * O(n) - changes in array capacity will result in copying all data * * @return the item that was removed @@ -188,7 +188,6 @@ public E removeBack() { /** * Remove item from the list - * * O(n) - changes in array capacity will result in copying all data * * @param item the item to be removed @@ -206,7 +205,6 @@ public void remove(E item) { /** * Remove item at a specified index. - * * O(n) - changes in array capacity will result in copying all data * * @param i the index where the item should be removed @@ -231,7 +229,6 @@ public E remove(int i) { /** * Checks if an item is in the list. - * * O(n) - item not present will go over whole array * * @param item the item to search for @@ -246,7 +243,6 @@ public boolean contains(E item) { /** * Checks if the list is empty. - * * O(1) - instant access to size * * @return true if the list is empty, false otherwise @@ -258,7 +254,6 @@ public boolean isEmpty() { /** * Provides a count of the number of items in the list. - * * O(1) - instant access to size * * @return number of items in the list @@ -270,7 +265,6 @@ public int size() { /** * Returns an iterator over elements of type {@code T}. - * * O(n) - by its nature * * @return an Iterator. diff --git a/src/DequeImpl.java b/src/DequeImpl.java index f9a0305..5cd030c 100644 --- a/src/DequeImpl.java +++ b/src/DequeImpl.java @@ -1,6 +1,5 @@ /** * Double-ended Queue implementation - * * Can add and remove from both sides of the queue. * * @author R.J. Trenchard @@ -34,7 +33,6 @@ public Node(E data, Node prev, Node next) { /** * Checks if the deque is empty. - * * O(1), size access is recorded during node creation/deletion * * @return true if the deque is empty, false otherwise @@ -46,7 +44,6 @@ public boolean isEmpty() { /** * Returns the number of items in the deque. - * * O(1), size access is constant * * @return number of items in the deque @@ -58,7 +55,6 @@ public int size() { /** * Add an item to the left end of the deque. - * * @param item item to be added */ @Override @@ -85,6 +81,7 @@ else if (size == 1) { /** * Add an item to the right end of the deque. * O(1), adding right is instant + * * @param item item to add */ @Override @@ -111,7 +108,6 @@ else if (size == 1) { /** * Remove an item from the left end of the deque. - * * O(1), left access is instant * * @return the item on the left end of the queue @@ -150,7 +146,6 @@ else if (size == 1) { /** * Remove an item from the right end of the deque. - * * O(1), contrast to something like a linked list, we can instantly access the right end of a dequeue * * @return the item on the right end of the queue @@ -189,7 +184,6 @@ else if (size == 1) { /** * Returns an iterator over elements of type {@code T}. - * * O(n), as usual, an iterator will always pass a list once and once only unless break occurs. * * @return an Iterator. diff --git a/src/LinkedBag.java b/src/LinkedBag.java index 72c1cc6..59d427b 100644 --- a/src/LinkedBag.java +++ b/src/LinkedBag.java @@ -1,6 +1,5 @@ /** * Linked Bag implementation - * * Bag uses linked nodes to store its data * * @author R.J. trenchard @@ -30,7 +29,6 @@ public Node (E data) { /** * Adds an item to the bag - * * O(1), because we keep track of the tail end, we can always add to it without searching for it. * * @param item An item of the generic type. @@ -51,7 +49,6 @@ public void add(E item) { /** * Returns true if the bag has no items. - * * O(1), empty access is instant * * @return true if empty. @@ -63,7 +60,6 @@ public boolean isEmpty() { /** * Gets the amount of items in the bag. - * * O(1), size access is instant * * @return size @@ -75,6 +71,7 @@ public int size() { /** * Returns an iterator over elements of type {@code T}. + * O(n), will always loop over the whole list * * @return an Iterator. */ diff --git a/src/LinkedList.java b/src/LinkedList.java index 01bc055..3273b92 100644 --- a/src/LinkedList.java +++ b/src/LinkedList.java @@ -1,6 +1,5 @@ /** * List implementation with linked nodes - * * Allows adding elements without resizing in chunks * * @author R.J. Trenchard @@ -39,7 +38,6 @@ public LinkedList() { /** * Add item to the front. - * * O(1) - access to the front nodes are instant * * @param item the item to be added @@ -51,7 +49,6 @@ public void addFront(E item) { /** * Add item to the back. - * * O(n) - need to scroll to the end node since we don't keep track of it. * although we could and it would result in O(1) as well. * @@ -64,7 +61,6 @@ public void addBack(E item) { /** * Add an item at specified index (position). - * * O(n) - if adding to the very back, you will need to scroll the whole list. * * @param i the index where the item should be added @@ -103,7 +99,6 @@ public void add(int i, E item) { /** * Get the item at a specified index. - * * O(n) - if scrolling to the very back, will need to traverse whole list * * @param i the index where the item should be retrieved @@ -127,7 +122,6 @@ public E get(int i) { /** * Set (save) an item at a specified index. Previous * item at that index is overwritten. - * * O(n) - will need to scroll to position to set it. * * @@ -151,7 +145,6 @@ public void set(int i, E item) { /** * Remove item at the front of the list. - * * O(1) - head is readily accessible. * * @return the item that was removed @@ -163,7 +156,6 @@ public E removeFront() { /** * Remove item at the back of the list - * * O(n) - back needs to be scrolled to before removing it * * @return the item that was removed @@ -175,7 +167,6 @@ public E removeBack() { /** * Remove item from the list - * * O(n) - this implementation calls remove twice, * but is guaranteed to pass no more than twice. * thus is it 2n, not BigO Squared. @@ -196,7 +187,6 @@ public void remove(E item) { /** * Remove item at a specified index. - * * O(n) - need to scroll to index to find it, which may be at the end. * * @param i the index where the item should be removed @@ -233,7 +223,6 @@ public E remove(int i) { /** * Checks if an item is in the list. - * * O(n) - may not find an item, resulting in traversing the whole list. * * @param item the item to search for @@ -253,7 +242,6 @@ public boolean contains(E item) { /** * Checks if the list is empty. - * * O(1), size access is instant * * @return true if the list is empty, false otherwise @@ -265,7 +253,6 @@ public boolean isEmpty() { /** * Provides a count of the number of items in the list. - * * O(1) - size access is instant. * * @return number of items in the list @@ -277,7 +264,6 @@ public int size() { /** * Returns an iterator over elements of type {@code T}. - * * O(n) - traverses entire list. * * @return an Iterator. diff --git a/src/LinkedQueue.java b/src/LinkedQueue.java index 123bf2e..f1ce396 100644 --- a/src/LinkedQueue.java +++ b/src/LinkedQueue.java @@ -1,6 +1,6 @@ /** * LinkedQueue implementation - * + * This queue uses linked nodes to store data, both a head and a tail * for quick access to enqueuing to the back, and dequeuing from the front. * @@ -34,7 +34,6 @@ public Node(E data, Node next) { } /** * Add an item to the queue. - * * O(1), adding to a queue is instant if we keep track of the head and tail. * * @param item the item to be added @@ -55,7 +54,6 @@ public void enqueue(E item) { /** * Remove an item from the queue. - * * O(1), dequeuing is instant and involves no loops. * * @return the item that was removed @@ -76,7 +74,6 @@ public E dequeue() { /** * Checks to see if the queue is empty. - * * O(1), size access is instant * * @return true if the queue is empty, false otherwise @@ -88,7 +85,6 @@ public boolean isEmpty() { /** * Returns a count of the number of items in the queue. - * * O(1), size access is instant * * @return the number of items in the queue @@ -100,8 +96,6 @@ public int size() { /** * Returns an iterator over elements of type {@code T}. - * - * Most implementations of queues I find have no iterator. * O(n) - guaranteed to be O(n) if you iterate through the list once * * @return an Iterator. diff --git a/src/LinkedStack.java b/src/LinkedStack.java index 70f8b95..58d6b1c 100644 --- a/src/LinkedStack.java +++ b/src/LinkedStack.java @@ -1,6 +1,5 @@ /** * Linked Stack - * * Stack that uses linked nodes to store its data * * @author R.J. Trenchard diff --git a/src/ResizingArrayStack.java b/src/ResizingArrayStack.java index 80bdbed..019da2c 100644 --- a/src/ResizingArrayStack.java +++ b/src/ResizingArrayStack.java @@ -1,7 +1,6 @@ /** * Resizing Array Stack - * - * This stack uses a built in array to store its data. + * This stack uses a built-in array to store its data. * * @author R.J. Trenchard * @date 2/15/2024 @@ -77,7 +76,7 @@ private void shrink() { // O(n), linear copy. private void copy(E[] from, E[] to) { // copy old data to new array - int shortest = (to.length < from.length) ? to.length : from.length; + int shortest = Math.min(to.length, from.length); for (int i = 0; i < shortest; i++) { to[i] = from[i]; } @@ -85,7 +84,6 @@ private void copy(E[] from, E[] to) { /** * Add an item to the stack. - * * O(n) - if the buffer is full, we need to copy the whole stack * * @param item the item to be added @@ -101,7 +99,6 @@ public void push(E item) { /** * Removes the most recently added item from the stack. - * * O(n) - if the buffer is too large, need to copy array * * @return the item that was removed @@ -123,7 +120,6 @@ public E pop() { /** * Returns the item at the top of the stack. * Does not modify the stack or the item at the top. - * * O(1) - access to peek is instant * * @return item at the top of the stack. @@ -138,7 +134,6 @@ public E peek() { /** * Checks to see if the stack is empty. - * * O(1) - instant access * * @return true if the stack is empty, false otherwise @@ -150,7 +145,6 @@ public boolean isEmpty() { /** * Returns a count of the number of items in the stack. - * * O(1) - access to size is instant * * @return the number of items in the stack @@ -162,7 +156,6 @@ public int size() { /** * Returns an iterator over elements of type {@code T}. - * * O(n) - always n elements unless you break early. * * @return an Iterator. diff --git a/src/Stats.java b/src/Stats.java index ef8d154..46dc429 100644 --- a/src/Stats.java +++ b/src/Stats.java @@ -4,7 +4,7 @@ * Previews LinkedBag * * @author R.J. Trenchard - * @date 2/15/2024 + * 2/15/2024 */ public class Stats { diff --git a/test/MathSetImplTest.java b/test/MathSetImplTest.java index 35461aa..597b161 100644 --- a/test/MathSetImplTest.java +++ b/test/MathSetImplTest.java @@ -1,6 +1,6 @@ import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +//import static org.junit.jupiter.api.Assertions.*; class MathSetImplTest { From 5e5518fcf9b0925513558f4a90ea50277292be64 Mon Sep 17 00:00:00 2001 From: RJ Trenchard Date: Thu, 15 Feb 2024 20:55:39 -0800 Subject: [PATCH 33/33] Add default constructors, test clients --- src/DequeImpl.java | 5 +++++ src/LinkedBag.java | 5 +++++ src/LinkedList.java | 14 ++++++------- src/LinkedQueue.java | 5 +++++ src/LinkedStack.java | 10 ++++----- src/LinkedStackTestClient.java | 30 +++++++++++++++++++++++++++ src/QueueTestClient.java | 30 +++++++++++++++++++++++++++ src/ResizingArrayStackTestClient.java | 30 +++++++++++++++++++++++++++ 8 files changed, 117 insertions(+), 12 deletions(-) create mode 100644 src/LinkedStackTestClient.java create mode 100644 src/QueueTestClient.java create mode 100644 src/ResizingArrayStackTestClient.java diff --git a/src/DequeImpl.java b/src/DequeImpl.java index 5cd030c..96d131b 100644 --- a/src/DequeImpl.java +++ b/src/DequeImpl.java @@ -31,6 +31,11 @@ public Node(E data, Node prev, Node next) { } } + public DequeImpl() { + int size = 0; + head = tail = null; + } + /** * Checks if the deque is empty. * O(1), size access is recorded during node creation/deletion diff --git a/src/LinkedBag.java b/src/LinkedBag.java index 59d427b..a07b54f 100644 --- a/src/LinkedBag.java +++ b/src/LinkedBag.java @@ -16,6 +16,11 @@ public class LinkedBag implements Bag { int size; Node head, tail; + public LinkedBag(){ + size = 0; + head = tail = null; + } + private class Node { E data; diff --git a/src/LinkedList.java b/src/LinkedList.java index 3273b92..1be2574 100644 --- a/src/LinkedList.java +++ b/src/LinkedList.java @@ -16,7 +16,13 @@ public class LinkedList implements List { Node head; int size; - protected class Node { + public LinkedList() { + head = null; + size = 0; + } + + + private class Node { Node next; E data; @@ -30,12 +36,6 @@ public Node(E data, Node next) { } } - public LinkedList() { - head = null; - size = 0; - } - - /** * Add item to the front. * O(1) - access to the front nodes are instant diff --git a/src/LinkedQueue.java b/src/LinkedQueue.java index f1ce396..b8670df 100644 --- a/src/LinkedQueue.java +++ b/src/LinkedQueue.java @@ -18,6 +18,11 @@ public class LinkedQueue implements Queue { int size; Node head, tail; + public LinkedQueue() { + size = 0; + head = tail = null; + } + private class Node { E data; diff --git a/src/LinkedStack.java b/src/LinkedStack.java index 58d6b1c..f1879a9 100644 --- a/src/LinkedStack.java +++ b/src/LinkedStack.java @@ -16,6 +16,11 @@ public class LinkedStack implements Stack { int size; Node tail; + public LinkedStack() { + tail = null; + size = 0; + } + private class Node { E data; @@ -27,11 +32,6 @@ public Node(E data, Node prev) { } } - public LinkedStack() { - tail = null; - size = 0; - } - /** * Add an item to the stack. * diff --git a/src/LinkedStackTestClient.java b/src/LinkedStackTestClient.java new file mode 100644 index 0000000..f9ffc0a --- /dev/null +++ b/src/LinkedStackTestClient.java @@ -0,0 +1,30 @@ +/** + * demos the linked stack + * + * @author R.J. Trenchard + * 2/15/2024 + */ +import java.util.Scanner; + + +public class LinkedStackTestClient { + public static void main(String[] args) { + Stack s = new LinkedStack<>(); + + Scanner in = new Scanner("to be or not to - be - - that - - - is"); + + while (in.hasNext()) { + String item = in.next(); + if (!item.equals("-")) { + s.push(item); + } + else if (!s.isEmpty()) { + System.out.print(s.pop() + " "); + } + } + + System.out.println("\n(" + s.size() + " left in the stack)"); + + } + +} diff --git a/src/QueueTestClient.java b/src/QueueTestClient.java new file mode 100644 index 0000000..d8ca03d --- /dev/null +++ b/src/QueueTestClient.java @@ -0,0 +1,30 @@ +/** + * demos the queue + * + * @author R.J. Trenchard + * 2/15/2024 + */ +import java.util.Scanner; + + +public class QueueTestClient { + public static void main(String[] args) { + Queue q = new LinkedQueue<>(); + + Scanner in = new Scanner("to be or not to - be - - that - - - is"); + + while (in.hasNext()) { + String item = in.next(); + if (!item.equals("-")) { + q.enqueue(item); + } + else if (!q.isEmpty()) { + System.out.print(q.dequeue() + " "); + } + } + + System.out.println("\n(" + q.size() + " left in the queue)"); + + } + +} diff --git a/src/ResizingArrayStackTestClient.java b/src/ResizingArrayStackTestClient.java new file mode 100644 index 0000000..09d9cdb --- /dev/null +++ b/src/ResizingArrayStackTestClient.java @@ -0,0 +1,30 @@ +/** + * demos the array stack + * + * @author R.J. Trenchard + * 2/15/2024 + */ +import java.util.Scanner; + + +public class ResizingArrayStackTestClient { + public static void main(String[] args) { + Stack s = new ResizingArrayStack<>(); + + Scanner in = new Scanner("to be or not to - be - - that - - - is"); + + while (in.hasNext()) { + String item = in.next(); + if (!item.equals("-")) { + s.push(item); + } + else if (!s.isEmpty()) { + System.out.print(s.pop() + " "); + } + } + + System.out.println("\n(" + s.size() + " left in the stack)"); + + } + +}