diff --git a/.gitignore b/.gitignore index f68d109..97a4001 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ out/ !**/src/main/**/out/ !**/src/test/**/out/ +/.idea/vcs.xml +/.idea/misc.xml ### Eclipse ### .apt_generated @@ -26,4 +28,5 @@ bin/ .vscode/ ### Mac OS ### -.DS_Store \ No newline at end of file +.DS_Store + diff --git a/.idea/misc.xml b/.idea/misc.xml index 6f29fee..69ace3f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/SDEV333-Term-Project.iml b/SDEV333-Term-Project.iml index c90834f..0f07f6c 100644 --- a/SDEV333-Term-Project.iml +++ b/SDEV333-Term-Project.iml @@ -4,8 +4,25 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ArrayList.java b/src/ArrayList.java new file mode 100644 index 0000000..fd01b5c --- /dev/null +++ b/src/ArrayList.java @@ -0,0 +1,305 @@ +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class ArrayList implements List{ + + // fields + private int size; + private E[] buffer; + + public ArrayList() + { + //initialize my fields + size = 0; + buffer = (E[]) new Object[10]; + } + + /** + * Runtime analysis: Worst case scenario, this will run at O(2n) time. + * This is because if we have a full buffer, we will need to resize. + * To resize, we go through every element and copy to a new buffer. + * We then have to addFront() by moving all elements over right one, + * and then add the item to the front. + * @param item the item to be added + */ + @java.lang.Override + public void addFront(E item) { + if(size == buffer.length) + { + resize(size * 2); + } + + for(int i = size; i >= 1; i--) + { + buffer[i] = buffer[i-1]; + } + buffer[0] = item; + size++; + } + + /** + * Runtime analysis: Worst case scenario, this will run at O(n). This is because + * if our buffer is full, we will have to resize. Resizing means visiting all + * elements in our original buffer and copying them over to a new one. + * Then we will add our new item to the end of our buffer. Best case scenario, + * this runs in constant time since we can just add an item to the back + * and increment size. + * @param item the item to be added + */ + @java.lang.Override + public void addBack(E item) { + if(size == buffer.length) + { + resize(size * 2); + } + + buffer[size] = item; + size++; + } + + /** + * Worst case scenario, this would run at O(2n) time. This is because + * if our buffer is full, we would need to resize, meaning we have to + * loop through the entire buffer to add all items to a new, larger buffer. + * After that, the index could be the first index meaning we have to shift + * every element over to the right one index. + * @param i the index where the item should be added + * @param item the item to be added + */ + @java.lang.Override + public void add(int i, E item) { + if(i > size || i < 0) + { + throw new IndexOutOfBoundsException("Invalid index"); + } + if(size == buffer.length) + { + resize(size * 2); + } + if (i != size) { + for (int j = size; j > i; j--) { + buffer[j] = buffer[j - 1]; + } + } + buffer[i] = item; + size++; + } + + /** + * In every scenario, this would run in constant time. Since we are just + * returning an element located at in index, this is a single line return + * statement. There is no need to do a loop, traversal, or shifting of elements. + * @param i the index where the item should be retrieved + * @return + */ + @java.lang.Override + public E get(int i) { + if(i > size) + { + throw new IndexOutOfBoundsException(); + } + return buffer[i]; + } + + /** + * In every scenario, this would run in constant time. Since we are just + * changing a single elements value at an index, this is a single line, + * with no traversal, loop, or shifting of the buffer required. + * @param i the index where the item should be saved + * @param item the item to be saved + */ + @java.lang.Override + public void set(int i, E item) { + if(i > size) + { + throw new IndexOutOfBoundsException("Invalid index given!"); + } + buffer[i] = item; + } + + /** + * In every scenario, this would run at O(n). This is because since we are + * removing the front element, we have to shift every element over to the + * left one. This requires a loop to visit every element in the buffer. + * @return + */ + @java.lang.Override + public E removeFront() { + if(!isEmpty()) + { + E returnedItem = buffer[0]; + for (int i = 0; i <= size - 2; i++) { + buffer[i] = buffer[i + 1]; + } + buffer[size - 1] = null; + size--; + return returnedItem; + } + throw new NoSuchElementException("There are no elements to remove!"); + } + + /** + * Best and worst case scenario, if not accounting for the exception thrown, + * this would run in constant time. This is because we have no need to + * shift elements over since we are removing the final index. + * We also do not need to loop through any elements since we can + * remove the item from the index of size-1. + * @return + */ + @java.lang.Override + public E removeBack() { + if(!isEmpty()) + { + E returnedItem = buffer[size-1]; + buffer[size-1] = null; + size--; + return returnedItem; + } + throw new NoSuchElementException("There are no elements to remove!"); + } + + /** + * Worst case scenario, this would be O(2n) runtime. This is because + * the worst case would be either that the item is at the front + * or at the back. If the item is at the front, we would find + * the item immediately, but then would need to shift every item + * over to the left. If the item is at the back, we still have to + * search through the entire buffer until we find it at the final + * index. + * @param item the item to be removed + */ + @java.lang.Override + public void remove(E item) { + if(!contains(item)) + { + throw new NoSuchElementException("This element does not exist!"); + } + for (int i = 0; i < size; i++) { + if(buffer[i].equals(item)) + { + for (int j = i; j < size-2; j++) { + buffer[j] = buffer[j+1]; + } + //remove the final index value + buffer[size - 1] = null; + //decrement size + size--; + } + } + } + + /** + * Worst case scenario, this method will run at O(n). This is because the + * index it could be searching for could be the first index in the buffer. + * meaning it would have to reorder every index over to the left. + * Best case scenario, this would run at constant time, as + * it could be the very last index given, meaning it would have to do + * no reordering, or the index could not be valid, meaning an exception would + * be thrown. + * @param i the index where the item should be removed + * @return + */ + @java.lang.Override + public E remove(int i) { + //check to see if index is valid + if(i >= size || i < 0) + { + throw new IndexOutOfBoundsException("Invalid index"); + } + // save a copy of the value to be returned later + E removedItem = buffer[i]; + + //shift values to the left + for (int j = i; j < size-2; j++) { + buffer[j] = buffer[j+1]; + } + //remove the final index value + buffer[size - 1] = null; + //decrement size + size--; + //return the removed value + return removedItem; + } + + /** + * Worst case scenario, this will run at linear time or O(n). This is because + * the contains method could loop to the last element in the buffer and find + * the item, or it could loop to the end of the buffer and not find the item. + * Either way, it could potentially have to search through every index. + * @param item the item to search for + * @return + */ + @java.lang.Override + public boolean contains(E item) { + for (int i = 0; i < size; i++) { + if(buffer[i].equals(item)) + { + return true; + } + } + return false; + } + + /** + * This will always run in constant time since we are just returning + * a true or false based on if size is equal to 0. + * @return + */ + @java.lang.Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Runtime analysis: This will always run in constant time since we are just + * returning the variable size. + * @return + */ + @java.lang.Override + public int size() { + return size; + } + + /** + * In every scenario, this would run at O(n). This is because we have to + * create a new buffer, and go through the old buffer to copy all the + * elements over to the new one. + * @param newSize + */ + private void resize(int newSize) + { + E[] newBuffer = (E[])new Object[newSize]; + + for (int i = 0; i < size; i++) { + newBuffer[i] = buffer[i]; + } + //set the new space into the buffer + buffer = newBuffer; + + //the old space is no longer "pointed to" and will eventually + //be cleaned up by the garbage collector + } + + @java.lang.Override + public Iterator iterator() { + return new Iterator() { + // fields + private int i; + @Override + public boolean hasNext() { + return i < size; + } + + @Override + public E next() { + if(i >= size) + { + throw new NoSuchElementException("i is out of bounds"); + } + E currentValue = buffer[i]; + i++; + return currentValue; + } + }; + } +} diff --git a/src/Bag.java b/src/Bag.java new file mode 100644 index 0000000..26decf4 --- /dev/null +++ b/src/Bag.java @@ -0,0 +1,22 @@ +/** + * Bag API + */ +public interface Bag extends Iterable { + /** + * Add an item to the bag. + * @param item the item to be added + */ + void add(E item); + + /** + * Checks to see if the bag is emtpy + * @return true if the bag is empty, false otherwise. + */ + boolean isEmpty(); + + /** + * Returns a count of the number of items in the bag. + * @return the number of items in the bag + */ + int size(); +} diff --git a/src/LinkedBag.java b/src/LinkedBag.java new file mode 100644 index 0000000..b9f8388 --- /dev/null +++ b/src/LinkedBag.java @@ -0,0 +1,84 @@ +import java.util.Iterator; + +/** + * Creates a linked list bag object. Has the ability to add items, check the + * size of the bag, and status of if the bag is empty. + * @author Sage Bain + * @param + */ +public class LinkedBag implements Bag { + private Node head; + private int size; + + public LinkedBag() + { + head = null; + size = 0; + } + private class Node + { + E item; + Node next; + } + + /** + * This will always run in constant time as we are simply creating a new + * head Node and incrementing size, no looping or iteration required. + * @param item the item to be added + */ + @Override + public void add(E item) { + Node oldHead = head; + head = new Node(); + head.item = item; + head.next = oldHead; + size++; + } + + /** + * This will always run in constant time as we are simply returning + * true or false based on if head is equal to null. + * @return true or false based on if the bag is empty. + */ + @Override + public boolean isEmpty() { + return head == null; + } + + /** + * This will always run in constant time as we are simply returning + * the value of size. + * @return size + */ + @Override + public int size() { + return size; + } + + /** + * + * @return a new ListIterator + */ + @Override + public Iterator iterator() { + return new ListIterator(); + } + private class ListIterator implements Iterator + { + private Node current = head; + public boolean hasNext() + { + return current != null; + } + public void remove() + { + + } + public E next() + { + E item = current.item; + current = current.next; + return item; + } + } +} diff --git a/src/LinkedList.java b/src/LinkedList.java new file mode 100644 index 0000000..a3e565e --- /dev/null +++ b/src/LinkedList.java @@ -0,0 +1,364 @@ +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class LinkedList implements List{ + + // Node class + private class Node { + E data; + Node next; + } + + // fields + private Node head; + private int size; + + public LinkedList() { + head = null; + size = 0; + } + + /** + * Runtime analysis: Worst case scenario, this would run at constant time + * since in every case, you only change the head reference to the new Node. + * There is no need to visit every Node. + * @param item the item to be added + */ + @Override + public void addFront(E item) { + Node newOne = new Node(); + newOne.data = item; + if(head == null) + { + // the list is currently empty + newOne.next = null; + head = newOne; + size++; + return; + } + // the list currently has some nodes in it + newOne.next = head; + head = newOne; + size++; + } + + /** + * Runtime analysis: Worst case scenario, this would run at O(n) or linear time + * because you have to visit every Node to reach the back of the LinkedList + * and then assign a new Node to the back. + * @param item the item to be added + */ + @Override + public void addBack(E item) { + Node newOne = new Node(); + newOne.data = item; + if(head == null) + { + // the list is currently empty + newOne.next = null; + head = newOne; + size++; + return; + } + // the list currently has some nodes in it + Node current = head; + while(current.next != null) + { + current = current.next; + } + current.next = newOne; + size++; + } + + /** + * Runtime analysis: Worst case scenario, this would be O(n), as in the worst case scenario, + * the index being added to could be the last index, meaning we would have to traverse the + * entire LinkedList to add the new Node. Best case scenario, it would be constant time, as + * the user could ask to put the new Node at index 0, meaning no iterating is required. + * @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) { +// throw exception if index given is out of bounds + if(i > size || i < 0) + { + throw new IndexOutOfBoundsException("Invalid index given!"); + } + if(head == null) + { + head = new Node(); + head.data = item; + head.next = null; + size++; + return; + } + // current Node to keep track of index + Node current = head; + // create a new Node + Node theNewOne = new Node(); + // set the new Nodes value + theNewOne.data = item; + // check if index is at the front of the LinkedList + if(i == 0) + { + theNewOne.next = head; + head = theNewOne; + size++; + return; + } + // check if index is at the end of the LinkedList + if(i == size()) + { + // loop to end of the list + while(current.next != null) + { + current = current.next; + } + // add the new Node + current.next = theNewOne; + size++; + return; + } + // else, for loop that stops one before new indexed Node + for (int j = 0; j < i-1; j++) { + current = current.next; + } + // save the old Node from that index, so we can move it forward one space + Node nodeAfterAdded = current.next; + // put the new Node in current.next position + current.next = theNewOne; + // move current forward one + current = current.next; + // set the previous index Node forward one index position (e.g. index 3 Node would now become index 4) + current.next = nodeAfterAdded; + size++; + } + + /** + * Runtime analysis: Worst case scenario, this would be O(n) runtime because + * you might have to go to the end of the LinkedList to find an item, or + * not find the item at all. + * @param i the index where the item should be retrieved + * @return E + */ + @Override + public E get(int i) { + if(i >= size || i < 0) + { + throw new IndexOutOfBoundsException("Invalid index given!"); + } + Node current = head; + for (int j = 0; j < i; j++) { + current = current.next; + } + return current.data; + } + + /** + * Runtime analysis: Worst case scenario, this would be O(n) runtime. + * This is because the item you are wanting to set could be at + * the end of the list, or not there at all, meaning you + * iterate through each item in the LinkedList. + * @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) { + if(i > size || i < 0) + { + throw new IndexOutOfBoundsException("Invalid index given!"); + } + Node current = head; + for (int j = 0; j < i; j++) { + current = current.next; + } + current.data = item; + } + + /** + * Runtime analysis: This will always be constant time because + * removing the front Node does not vary. You simply move the head Node + * reference forward and that is it. + * @return E + */ + @Override + public E removeFront() { + if(size() > 0) + { + E returnedItem = head.data; + head = head.next; + size--; + return returnedItem; + } + return null; + } + + /** + * Runtime analysis: Worst case scenario, and best case scenario, + * this runs at O(n). This is because you always have to loop + * until you reach the end of the list to remove the last Node. + * @return E + */ + @Override + public E removeBack() { + E returnedItem; + if(size == 0) + { + return null; + } + if(size == 1) + { + returnedItem = head.data; + head = null; + size --; + return returnedItem; + } + Node current = head; + for (int i = 0; i < size()-2; i++) { + current = current.next; + } + returnedItem = current.next.data; + current.next = null; + size--; + return returnedItem; + } + + /** + * Runtime analysis: Worst case scenario, this would be O(n). + * That is because you could iterate through the whole list + * only to find the item does not exist within the LinkedList. + * @param item the item to be removed + */ + @Override + public void remove(E item) { + if(!contains(item)) + { + throw new NoSuchElementException("Item does not exist!"); + } + Node current = head; + if(current.data.equals(item)) + { + head = head.next; + size--; + return; + } + while(current.next != null) + { + if(current.next.data.equals(item)) + { + current.next = current.next.next; + size--; + return; + } + current = current.next; + } + } + + /** + * Runtime analysis: Worst case scenario, this would run at O(n) runtime. + * This is because the index given to the remove() method could be the + * very last index, meaning the method has to go individually node by + * node until it reaches the last node to remove. + * @param i the index where the item should be removed + * @return item to be removed + */ + @Override + public E remove(int i) { + // check if index is invalid + if(i >= size() || i < 0) + { + throw new IndexOutOfBoundsException("Invalid index given!"); + } + E dataToBeRemoved; + if(i == 0) + { + dataToBeRemoved = head.data; + head.data = null; + head = head.next; + size--; + return dataToBeRemoved; + } + // current Node to iterate through LinkedList + Node current = head; + // loop until one Node before our index + for (int j = 0; j < i-1; j++) { + current = current.next; + } + // save our value that will be removed + dataToBeRemoved = current.next.data; + // check if there are two Nodes ahead for easy shifting + if(size()-i > 1) + { + // move current.next an additional space forward + current.next = current.next.next; + size--; + return dataToBeRemoved; + } + // else, remove the next Node (there are no Nodes ahead of our index) + current.next = null; + size--; + return dataToBeRemoved; + } + + /** + * Runtime analysis: Worst case scenario, this method will run until the + * end of the list, and not find the item it is searching for. + * This would make its runtime O(n), as it has to search through every + * item in the LinkedList. + * @param item the item to search for + * @return boolean + */ + @Override + public boolean contains(E item) { + Node current = head; + while(current != null) + { + if(current.data.equals(item)) + { + return true; + } + current = current.next; + } + return false; + } + + /** + * Runtime analysis: This will always run in constant time because + * there is no variation based on size of the LinkedList. + * This is a simple 1 line return statement. + * @return boolean + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Runtime analysis: This will always run in constant time + * because there is no variation based on size of the LinkedList. + * This is a simple 1 line return statement to return the size + * of the LinkedList. + * @return int + */ + @Override + public int size() { + return size; + } + + @Override + public Iterator iterator() { + Node current = head; + return new Iterator<>() { + @Override + public boolean hasNext() { + return current.next != null; + } + + @Override + public E next() { + return current.next.data; + } + }; + } +} diff --git a/src/LinkedQueue.java b/src/LinkedQueue.java new file mode 100644 index 0000000..290b1ba --- /dev/null +++ b/src/LinkedQueue.java @@ -0,0 +1,108 @@ +import java.util.Iterator; + +/** + * Creates a new LinkedQueue object. Has the ability to add and remove items + * from the linked queue, as well as check the size and status of if the + * linked queue is empty. + * @author Sage Bain + * @param + */ +public class LinkedQueue implements Queue{ + private Node head; + private Node tail; + private int size; + + private class Node + { + E item; + Node next; + } + + /** + * This will always run in constant time, as there is no need to iterate + * through the linked queue. We are simply making adding a new item to the + * tail of the queue, and checking if the linked queue was originally empty. + * @param item the item to be added + */ + @Override + public void enqueue(E item) { + Node oldTail = tail; + tail = new Node(); + tail.item = item; + tail.next = null; + if(isEmpty()) { + head = tail; + } + else { + oldTail.next = tail; + } + size++; + } + + /** + * This will always run in constant time, as there is no need to iterate + * through the linked queue. We are simply moving head forward one space. + * Afterward, we check to see the linked queue was originally empty. If so, + * we set tail to null. Then we decrement size and return the removed item. + * @return item to be removed + */ + @Override + public E dequeue() { + E item = head.item; + head = head.next; + if(isEmpty()) { + tail = null; + } + size--; + return item; + } + + /** + * This will always run at constant time since we are simply returning + * true or false based on if head is equal to null. + * @return true or false based on if the queue is empty + */ + @Override + public boolean isEmpty() { + return head == null; + } + + /** + * This will always run at constant time since we are simply returning + * the value of size. + * @return size + */ + @Override + public int size() { + return size; + } + + /** + * + * @return a new ListIterator + */ + @Override + public Iterator iterator() { + return new ListIterator(); + } + private class ListIterator implements Iterator + { + private Node current = head; + @Override + public boolean hasNext() { + return current != null; + } + + @Override + public E next() { + E item = current.item; + current = current.next; + return item; + } + + @Override + public void remove() { + + } + } +} diff --git a/src/LinkedStack.java b/src/LinkedStack.java new file mode 100644 index 0000000..d161e8e --- /dev/null +++ b/src/LinkedStack.java @@ -0,0 +1,113 @@ +import java.util.Iterator; + +/** + * Creates a linked stack object. Has the ability to add and remove items, + * peek at the top item, and view the size and status of if the linked stack is + * empty. + * @author Sage Bain + * @param + */ +public class LinkedStack implements Stack { + + private Node head; + private int size; + private class Node + { + E item; + Node next; + } + + public LinkedStack() + { + head = null; + size = 0; + } + + /** + * This will always run at constant time, since there is no need to + * go through all the elements in the LinkedStack. This method + * simply creates a new head element and increments size in 5 lines. + * @param item the item to be added + */ + @Override + public void push(E item) { + Node oldHead = head; + head = new Node(); + head.item = item; + head.next = oldHead; + size++; + } + + /** + * This will always run at constant time, since there is no need to go + * through all the elements in the LinkedStack. This method simply + * saves the element to be removed in a variable, moves head one element + * forward, decrements size, and returns the removed Node. + * @return item removed from the stack + */ + @Override + public E pop() { + E toBeRemoved = head.item; + head = head.next; + size--; + return toBeRemoved; + } + + /** + * This will always run at constant time, since we are simply + * returning the value at head. + * @return item at the top of the stack + */ + @Override + public E peek() { + return head.item; + } + + /** + * This will always run at constant time, since we are simply + * returning true or false based on if size is equal to 0 or not. + * @return true or false based on if size is equal to 0. + */ + @Override + public boolean isEmpty() { + return size == 0; + } + /** + * This will always run at constant time, since we are simply + * returning the value of size. + * @return size + */ + @Override + public int size() { + return size; + } + + /** + * + * @return a new ListIterator + */ + @Override + public Iterator iterator() { + return new ListIterator(); + } + private class ListIterator implements Iterator + { + private Node current = head; + @Override + public boolean hasNext() { + return current != null; + } + + @Override + public E next() { + E item = current.item; + current = current.next; + return item; + } + + @Override + public void remove() { + + } + } +} diff --git a/src/QueueTestClient.java b/src/QueueTestClient.java new file mode 100644 index 0000000..4802053 --- /dev/null +++ b/src/QueueTestClient.java @@ -0,0 +1,19 @@ +import java.util.Scanner; + +public class QueueTestClient { + public static void main(String[] args) + { // Create a queue and enqueue/dequeue strings. + 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.println((q.dequeue() + " ")); + } + } + System.out.println("(" + q.size() + " left on queue)"); + } +} diff --git a/src/ResizingArrayStack.java b/src/ResizingArrayStack.java new file mode 100644 index 0000000..b27ab95 --- /dev/null +++ b/src/ResizingArrayStack.java @@ -0,0 +1,126 @@ +import java.util.Iterator; + +/** + * Creates a resizing array stack object. Has the ability to add and remove items, + * peek at the top item, and view the size and status of if the linked stack is + * empty. + * @author Sage Bain + * @param + */ +public class ResizingArrayStack implements Stack{ + private E[] buffer; + private int size; + + public ResizingArrayStack() + { + buffer = (E[])new Object[1]; + size = 0; + } + + /** + * This method will always run at O(n) because we are manually copying + * all items over from the original buffer to a new buffer. + * @param max capacity of the buffer + */ + private void resize(int max) + { + E[] temp = (E[]) new Object[max]; + for (int i = 0; i < size; i++) { + temp[i] = buffer[i]; + } + buffer = temp; + } + + /** + * Worst case scenario, this method will run at O(n) if we need to resize + * the buffer due to it being at max capacity. Best case scenario, + * this method runs at constant time due to being able to insert the new + * item at the end of the buffer in a single statement. + * @param item the item to be added + */ + @Override + public void push(E item) + { // Add item to top of stack. + if (size == buffer.length) { + resize(buffer.length*2); + } + buffer[size++] = item; + } + + /** + * Worst case scenario, this method will run at O(n). + * This is because if the method detects the buffer is using only 1/4 + * of its capacity, it will resize itself down by 1/2 of its original + * capacity. Best case scenario, this will run at constant time. + * @return removed item + */ + @Override + public E pop() + { // Remove item from top of stack. + E item = buffer[--size]; + buffer[size] = null; // Avoid loitering + if (size > 0 && size == buffer.length/4) { + resize(buffer.length/2); + } + return item; + } + + /** + * This will always run at constant time since it simply returns + * the item located at buffer index 0. + * @return top item of the stack + */ + @Override + public E peek() + { + return buffer[size-1]; + } + + /** + * This will always run at constant time since it simply returns + * true or false based on if size is equal to 0. + * @return true or false based on if size is equal to 0 + */ + @Override + public boolean isEmpty() + { + return size == 0; + } + + /** + * This will always run at constant time since it simply returns the + * value of size. + * @return size + */ + @Override + public int size() + { + return size; + } + + /** + * + * @return a new ListIterator + */ + @Override + public Iterator iterator() + { + return new ReverseArrayIterator(); + } + private class ReverseArrayIterator implements Iterator + { + private int i = size; + public boolean hasNext() + { + return i > 0; + } + public E next() + { + return buffer[--i]; + } + public void remove() + { + + } + } +} diff --git a/src/StackTestClient.java b/src/StackTestClient.java new file mode 100644 index 0000000..736a64f --- /dev/null +++ b/src/StackTestClient.java @@ -0,0 +1,17 @@ +import java.util.Scanner; +public class StackTestClient { + 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.println(s.pop() + " "); + } + } + System.out.println("(" + s.size() + " left on the stack)"); + } + } diff --git a/src/Stats.java b/src/Stats.java new file mode 100644 index 0000000..fe943b9 --- /dev/null +++ b/src/Stats.java @@ -0,0 +1,25 @@ +import java.util.Scanner; + +public class Stats { + public static void main(String[] args) + { + Bag numbers = new LinkedBag<>(); + Scanner in = new Scanner("100 99 101 120 98 107 109 81 101 90"); + while(in.hasNextDouble()) { + numbers.add(in.nextDouble()); + } + int size = numbers.size(); + double sum = 0.0; + for (double x : numbers) { + sum += x; + } + double mean = sum/size; + sum = 0.0; + for (double x : numbers) { + sum += (x - mean)*(x - mean); + } + double std = Math.sqrt(sum/(size-1)); + System.out.printf("Mean: %.2f\n", mean); + System.out.printf("Std dev: %.2f\n", std); + } +} diff --git a/tests/ArrayListTest.java b/tests/ArrayListTest.java new file mode 100644 index 0000000..64b1987 --- /dev/null +++ b/tests/ArrayListTest.java @@ -0,0 +1,316 @@ +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class ArrayListTest { + + @Test + void addFront() { + ArrayList list = new ArrayList<>(); + assertEquals(0, list.size()); + list.addFront("Banana"); + assertEquals("Banana", list.get(0)); + assertEquals(1, list.size()); + list.addFront("Apple"); + assertEquals("Apple", list.get(0)); + assertEquals(2, list.size()); + list.addFront("Cucumber"); + list.addFront("Pickle"); + list.addFront("Kiwi"); + list.addFront("Pizza"); + list.addFront("Grape"); + list.addFront("Melon"); + list.addFront("Passion fruit"); + list.addFront("Brownie"); + assertEquals(10, list.size()); + assertEquals("Brownie", list.get(0)); + assertEquals("Passion fruit", list.get(1)); + assertEquals("Melon", list.get(2)); + assertEquals("Grape", list.get(3)); + assertEquals("Banana", list.get(list.size()-1)); + } + + @Test + void addBack() { + ArrayList list = new ArrayList<>(); + assertEquals(0, list.size()); + list.addBack("Pickle"); + assertEquals(1, list.size()); + assertEquals("Pickle", list.get(list.size()-1)); + list.addBack("Cucumber"); + assertEquals(2, list.size()); + assertEquals("Cucumber", list.get(list.size()-1)); + list.addBack("Pear"); + list.addBack("Peach"); + list.addBack("Chicken"); + list.addBack("Lime"); + list.addBack("Lemon"); + list.addBack("Apple"); + list.addBack("Orange"); + list.addBack("Kiwi"); + assertEquals(10, list.size()); + assertEquals("Pear", list.get(2)); + assertEquals("Peach", list.get(3)); + assertEquals("Chicken", list.get(4)); + assertEquals("Lime", list.get(5)); + assertEquals("Lemon", list.get(6)); + assertEquals("Apple", list.get(7)); + assertEquals("Orange", list.get(8)); + assertEquals("Kiwi", list.get(9)); + } + + @Test + void add() { + ArrayList list = new ArrayList<>(); + assertEquals(0, list.size()); + list.add(0, "Pickle"); + assertEquals(1, list.size()); + list.add(1, "Cucumber"); + assertEquals("Pickle", list.get(0)); + assertEquals("Cucumber", list.get(1)); + assertEquals(2, list.size()); + list.add(0, "Pear"); + list.add(1, "Peach"); + assertEquals("Pear", list.get(0)); + assertEquals("Peach", list.get(1)); + assertEquals("Pickle", list.get(2)); + assertEquals("Cucumber", list.get(3)); + list.add(4, "Pizza"); + list.add(5, "Pasta"); + list.add(6, "Chicken"); + list.add(7, "Kiwi"); + list.add(8, "Melon"); + list.add(9, "Lemon"); + assertEquals("Lemon", list.get(9)); + assertEquals("Melon", list.get(8)); + assertEquals("Kiwi", list.get(7)); + assertEquals("Chicken", list.get(6)); + assertEquals("Pasta", list.get(5)); + assertEquals("Pizza", list.get(4)); + } + + @Test + void get() { + ArrayList list = new ArrayList<>(); + list.add(0, "Banana"); + assertEquals("Banana", list.get(0)); + list.add(1, "Kiwi"); + assertEquals("Kiwi", list.get(1)); + list.add(2, "Pear"); + list.add(3, "Peach"); + list.add(4, "Pizza"); + list.add(5, "Pasta"); + list.add(6, "Chicken"); + list.add(7, "Sandwich"); + list.add(8, "Pickle"); + list.add(9, "Cucumber"); + assertEquals("Pear", list.get(2)); + assertEquals("Peach", list.get(3)); + assertEquals("Pizza", list.get(4)); + assertEquals("Pasta", list.get(5)); + assertEquals("Chicken", list.get(6)); + assertEquals("Sandwich", list.get(7)); + assertEquals("Pickle", list.get(8)); + assertEquals("Cucumber", list.get(9)); + assertEquals("Banana", list.get(0)); + assertEquals("Kiwi", list.get(1)); + } + + @Test + void set() { + ArrayList list = new ArrayList<>(); + list.add(0, "Pickle"); + assertEquals("Pickle", list.get(0)); + list.set(0, "Cucumber"); + assertEquals("Cucumber", list.get(0)); + list.add(1, "Peach"); + assertEquals("Peach", list.get(1)); + list.set(1, "Pear"); + assertEquals("Pear", list.get(1)); + list.add(2, "Pizza"); + list.add(3, "Pasta"); + list.add(4, "Chicken"); + list.add(5, "Cookie"); + list.add(6, "Cake"); + list.add(7, "Pie"); + list.add(8, "Sandwich"); + list.add(9, "Eggs"); + assertEquals("Eggs", list.get(9)); + list.set(9, "Hashbrowns"); + assertEquals("Hashbrowns", list.get(9)); + } + + @Test + void removeFront() { + ArrayList list = new ArrayList<>(); + list.addFront("Banana"); + assertEquals(1, list.size()); + assertEquals("Banana", list.get(0)); + assertEquals("Banana", list.removeFront()); + assertEquals(0, list.size()); + list.addFront("Peach"); + list.addFront("Pear"); + assertEquals(2, list.size()); + assertEquals("Peach", list.get(1)); + assertEquals("Pear", list.get(0)); + assertEquals("Pear", list.removeFront()); + assertEquals("Peach", list.removeFront()); + list.addFront("Pizza"); + list.addFront("Brownie"); + list.addFront("Kiwi"); + list.addFront("Lime"); + list.addFront("Lemon"); + list.addFront("Pasta"); + list.addFront("Chicken"); + list.addFront("Rice"); + list.addFront("Cucumber"); + list.addFront("Pickle"); + assertEquals(10, list.size()); + assertEquals("Pickle", list.get(0)); + assertEquals("Pickle", list.removeFront()); + assertEquals("Cucumber", list.get(0)); + assertEquals("Cucumber", list.removeFront()); + assertEquals("Rice", list.get(0)); + assertEquals("Rice", list.removeFront()); + assertEquals("Chicken", list.get(0)); + assertEquals("Chicken", list.removeFront()); + assertEquals("Pasta", list.get(0)); + assertEquals("Pasta", list.removeFront()); + assertEquals(5, list.size()); + } + + @Test + void removeBack() { + ArrayList list = new ArrayList<>(); + list.addBack("Banana"); + assertEquals(1, list.size()); + assertEquals("Banana", list.removeBack()); + list.addBack("Cookie"); + list.addBack("Cake"); + assertEquals("Cake", list.removeBack()); + assertEquals("Cookie", list.removeBack()); + list.addBack("Pizza"); + list.addBack("Brownie"); + list.addBack("Grilled Cheese"); + list.addBack("Apple"); + list.addBack("Kiwi"); + list.addBack("Orange"); + list.addBack("Peach"); + list.addBack("Pear"); + list.addBack("Lemon"); + list.addBack("Lime"); + assertEquals(10, list.size()); + assertEquals("Lime", list.get(list.size()-1)); + assertEquals("Lime", list.removeBack()); + assertEquals("Lemon", list.get(list.size()-1)); + assertEquals("Lemon", list.removeBack()); + assertEquals("Pear", list.get(list.size()-1)); + assertEquals("Pear", list.removeBack()); + assertEquals("Peach", list.get(list.size()-1)); + assertEquals("Peach", list.removeBack()); + assertEquals(6, list.size()); + } + + @Test + void removeItem() { + ArrayList list = new ArrayList<>(); + list.addBack("Banana"); + list.addBack("Pizza"); + list.addBack("Kiwi"); + list.addBack("Apple"); + list.addBack("Orange"); + list.addBack("Pasta"); + list.addBack("Lemon"); + list.addBack("Lime"); + list.addBack("Peach"); + list.addBack("Pear"); + assertEquals(10, list.size()); + assertEquals("Pear", list.get(list.size()-1)); + list.remove("Pear"); + assertEquals("Peach", list.get(list.size()-1)); + } + + @Test + void removeIndex() { + ArrayList list = new ArrayList<>(); + list.addFront("Banana"); + assertEquals("Banana", list.remove(0)); + list.addFront("Kiwi"); + list.addFront("Orange"); + assertEquals("Kiwi", list.remove(1)); + list.addFront("Apple"); + list.addFront("Pasta"); + list.addFront("Chicken"); + list.addFront("Cucumber"); + list.addFront("Pizza"); + list.addFront("Brownie"); + list.addFront("Cookie"); + list.addFront("Cake"); + list.addFront("Pie"); + assertEquals("Orange", list.get(list.size()-1)); + assertEquals("Orange", list.remove(list.size()-1)); + assertEquals("Apple", list.get(list.size()-1)); + assertEquals("Pizza", list.remove(4)); + assertEquals("Cucumber", list.get(4)); + assertEquals("Brownie", list.remove(3)); + assertEquals("Cucumber", list.get(3)); + assertEquals("Pie", list.remove(0)); + assertEquals("Cookie", list.remove(1)); + } + + @Test + void contains() { + ArrayList list = new ArrayList<>(); + assertFalse(list.contains("Banana")); + list.addFront("Banana"); + assertTrue(list.contains("Banana")); + list.addFront("Kiwi"); + list.addFront("Watermelon"); + list.addFront("Cantaloupe"); + list.addFront("Apple"); + list.addFront("Orange"); + list.addFront("Passion fruit"); + assertFalse(list.contains("Pizza")); + assertTrue(list.contains("Orange")); + assertTrue(list.contains("Watermelon")); + assertFalse(list.contains("Brownie")); + assertFalse(list.contains("Pickle")); + assertTrue(list.contains("Kiwi")); + assertTrue(list.contains("Apple")); + } + + @Test + void isEmpty() { + ArrayList list = new ArrayList<>(); + assertTrue(list.isEmpty()); + list.addFront("Banana"); + assertFalse(list.isEmpty()); + list.addFront("Kiwi"); + assertFalse(list.isEmpty()); + list.removeFront(); + list.removeFront(); + assertTrue(list.isEmpty()); + } + + @Test + void size() { + ArrayList list = new ArrayList<>(); + assertEquals(0, list.size()); + list.addFront("Banana"); + assertEquals(1, list.size()); + list.addFront("Apple"); + list.addFront("Kumquat"); + list.addFront("Kiwi"); + list.addFront("Pizza"); + list.addFront("Brownie"); + list.addFront("Cracker"); + assertEquals(7, list.size()); + list.removeFront(); + assertEquals(6, list.size()); + list.removeFront(); + list.removeFront(); + list.removeFront(); + list.removeFront(); + assertEquals(2, list.size()); + } +} \ No newline at end of file diff --git a/tests/LinkedListTest.java b/tests/LinkedListTest.java new file mode 100644 index 0000000..0cc0e68 --- /dev/null +++ b/tests/LinkedListTest.java @@ -0,0 +1,284 @@ +import static org.junit.jupiter.api.Assertions.*; + +class LinkedListTest { + + @org.junit.jupiter.api.Test + void addFront() { + LinkedList list = new LinkedList<>(); + assertEquals(0, list.size()); + list.addFront("Banana"); + assertEquals("Banana", list.get(0)); + assertEquals(1, list.size()); + list.addFront("Orange"); + assertEquals("Orange", list.get(0)); + assertEquals("Banana", list.get(1)); + assertEquals(2, list.size()); + list.addFront("Apple"); + list.addFront("Pear"); + list.addFront("Grapefruit"); + list.addFront("Grape"); + list.addFront("Lemon"); + list.addFront("Lime"); + list.addFront("Melon"); + assertEquals("Melon", list.get(0)); + assertEquals("Banana", list.get(list.size()-1)); + assertEquals(9, list.size()); + } + + @org.junit.jupiter.api.Test + void addBack() { + LinkedList list = new LinkedList<>(); + assertEquals(0, list.size()); + list.addBack("Banana"); + assertEquals("Banana", list.get(list.size()-1)); + assertEquals(1, list.size()); + list.addBack("Orange"); + assertEquals("Orange", list.get(list.size()-1)); + assertEquals("Banana", list.get(0)); + assertEquals(2, list.size()); + list.addBack("Apple"); + list.addBack("Pear"); + list.addBack("Grapefruit"); + list.addBack("Grape"); + list.addBack("Lemon"); + list.addBack("Lime"); + list.addBack("Melon"); + assertEquals("Melon", list.get(list.size()-1)); + assertEquals("Banana", list.get(0)); + assertEquals(9, list.size()); + } + + @org.junit.jupiter.api.Test + void add() { + LinkedList list = new LinkedList<>(); + list.add(0, "Banana"); + assertEquals(1, list.size()); + assertEquals("Banana", list.get(0)); + list.add(1, "Orange"); + assertEquals(2, list.size()); + assertEquals("Orange", list.get(1)); + list.add(0, "Pear"); + list.add(3, "Pineapple"); + list.add(4, "Kiwi"); + list.add(5, "Plum"); + list.add(6, "Peach"); + list.add(7, "Apple"); + list.add(8, "Grape"); + assertEquals(9, list.size()); + assertEquals("Pear", list.get(0)); + assertEquals("Banana", list.get(1)); + assertEquals("Orange", list.get(2)); + assertEquals("Plum", list.get(5)); + assertEquals("Peach", list.get(6)); + assertEquals("Apple", list.get(7)); + assertEquals("Grape", list.get(8)); + } + + @org.junit.jupiter.api.Test + void get() { + LinkedList list = new LinkedList<>(); + list.addBack("Banana"); + assertEquals("Banana", list.get(0)); + list.addBack("Apple"); + list.addBack("Pear"); + list.addBack("Peach"); + list.addBack("Pineapple"); + list.addBack("Orange"); + assertEquals("Orange", list.get(list.size()-1)); + list.removeBack(); + assertEquals("Pineapple", list.get(list.size()-1)); + assertEquals("Apple", list.get(1)); + assertEquals("Pear", list.get(2)); + } + + @org.junit.jupiter.api.Test + void set() { + LinkedList list = new LinkedList<>(); + list.addBack("Pear"); + assertEquals("Pear", list.get(0)); + list.set(0, "Peach"); + assertEquals("Peach", list.get(0)); + list.addBack("Pear"); + list.addBack("Apple"); + list.addBack("Plum"); + list.addBack("Kiwi"); + list.addBack("Orange"); + list.addBack("Pickle"); + list.addBack("Cucumber"); + assertEquals("Kiwi", list.get(4)); + list.set(4, "Pizza"); + assertEquals("Pizza", list.get(4)); + assertEquals("Pickle", list.get(6)); + list.set(6, "Coca Cola"); + assertEquals("Coca Cola", list.get(6)); + assertEquals("Cucumber", list.get(7)); + list.set(7, "Coconut"); + assertEquals("Coconut", list.get(7)); + } + + @org.junit.jupiter.api.Test + void removeFront() { + LinkedList list = new LinkedList<>(); + assertEquals(null, list.removeFront()); + list.add(0, "Banana"); + assertEquals("Banana", list.get(0)); + assertEquals(1, list.size()); + assertEquals("Banana", list.removeFront()); + list.add(0, "Pear"); + list.add(1, "Plum"); + assertEquals("Pear", list.removeFront()); + list.addBack("Peach"); + list.addBack("Orange"); + list.addBack("Pineapple"); + list.addBack("Kiwi"); + list.addBack("Pizza"); + list.addBack("Brownie"); + list.addBack("Pickle"); + list.addBack("Cucumber"); + assertEquals("Plum", list.removeFront()); + assertEquals("Peach", list.removeFront()); + assertEquals("Orange", list.removeFront()); + assertEquals("Pineapple", list.removeFront()); + assertEquals("Kiwi", list.removeFront()); + } + + @org.junit.jupiter.api.Test + void removeBack() { + LinkedList list = new LinkedList<>(); + assertEquals(null, list.removeBack()); + list.addBack("Peach"); + assertEquals("Peach", list.removeBack()); + list.addBack("Pear"); + list.addBack("Plum"); + assertEquals("Plum", list.removeBack()); + list.addBack("Pineapple"); + list.addBack("Pizza"); + list.addBack("Pickle"); + list.addBack("Crackers"); + list.addBack("Brownie"); + list.addBack("Cheese"); + list.addBack("Asparagus"); + assertEquals("Asparagus", list.removeBack()); + assertEquals("Cheese", list.removeBack()); + assertEquals("Brownie", list.removeBack()); + assertEquals("Crackers", list.removeBack()); + assertEquals("Pickle", list.removeBack()); + } + + @org.junit.jupiter.api.Test + void removeIndex() { // removes based on index given + LinkedList list = new LinkedList<>(); + list.addBack("Banana"); + assertEquals("Banana", list.remove(0)); + assertEquals(0, list.size()); + list.addBack("Peach"); + list.addBack("Pear"); + list.addBack("Pineapple"); + assertEquals("Pear", list.remove(1)); + list.addBack("Pizza"); + list.addBack("Pickle"); + list.addBack("Cucumber"); + list.addBack("Apple"); + list.addBack("Orange"); + assertEquals("Pickle", list.remove(3)); + assertEquals("Orange", list.remove(5)); + assertEquals("Apple", list.remove(4)); + } + + @org.junit.jupiter.api.Test + void removeItem() { // removes based on item given + LinkedList list = new LinkedList<>(); + list.addBack("Banana"); + list.remove("Banana"); + assertEquals(0, list.size()); + list.addBack("Banana"); + list.addBack("Peach"); + list.addBack("Orange"); + list.addBack("Pear"); + list.addBack("Banana"); + list.addBack("Pineapple"); + list.addBack("Carrot"); + list.addBack("Bread"); + assertEquals("Banana", list.get(0)); + list.remove("Banana"); + assertEquals("Peach", list.get(0)); + assertEquals("Banana", list.get(3)); + assertEquals("Pineapple", list.get(4)); + assertEquals("Carrot", list.get(5)); + assertEquals("Bread", list.get(list.size()-1)); + list.remove("Bread"); + assertEquals("Carrot", list.get(list.size()-1)); + } + + @org.junit.jupiter.api.Test + void contains() { + LinkedList list = new LinkedList<>(); + assertEquals(false, list.contains("")); + assertEquals(false, list.contains("Banana")); + assertEquals(false, list.contains("Orange")); + list.addBack("Banana"); + assertEquals(true, list.contains("Banana")); + list.addBack("Orange"); + assertEquals(true, list.contains("Orange")); + list.addBack("Pineapple"); + list.addBack("Lemon"); + list.addBack("Lime"); + list.addBack("Peach"); + list.addBack("Pear"); + list.addBack("Apple"); + list.addBack("Kiwi"); + assertEquals(true, list.contains("Lime")); + assertEquals(true, list.contains("Peach")); + assertEquals(true, list.contains("Kiwi")); + assertEquals(true, list.contains("Pear")); + assertEquals(true, list.contains("Pineapple")); + assertEquals(false, list.contains("Kumquat")); + assertEquals(false, list.contains("Pizza")); + list.remove("Pineapple"); + assertEquals(false, list.contains("Pineapple")); + } + + @org.junit.jupiter.api.Test + void isEmpty() { + LinkedList list = new LinkedList<>(); + assertEquals(true, list.isEmpty()); + list.addBack("Apple"); + assertEquals(false, list.isEmpty()); + list.addBack("Banana"); + assertEquals(false, list.isEmpty()); + list.addBack("Orange"); + list.addBack("Pear"); + list.addBack("Cucumber"); + list.addBack("Pizza"); + list.addBack("Brownies"); + list.addBack("Salad"); + list.addBack("Eggs"); + assertEquals(false, list.isEmpty()); + for (int i = 0; i < list.size(); i++) { + list.remove(i); + i--; + } + assertEquals(true, list.isEmpty()); + } + + @org.junit.jupiter.api.Test + void size() { + LinkedList list = new LinkedList<>(); + assertEquals(0, list.size()); + list.addBack("Banana"); + assertEquals(1, list.size()); + list.addBack("Orange"); + list.addBack("Grape"); + list.addBack("Pear"); + list.addBack("Apple"); + list.addBack("Melon"); + list.addBack("Passion fruit"); + assertEquals(7, list.size()); + list.remove("Melon"); + assertEquals(6, list.size()); + list.remove("Pear"); + assertEquals(5, list.size()); + list.remove("Banana"); + assertEquals(4, list.size()); + } +} \ No newline at end of file