diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..9c7d568 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,299 @@ + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SDEV333-Term-Project.iml b/SDEV333-Term-Project.iml index c90834f..0f9e336 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/Main.java b/src/Main.java deleted file mode 100644 index 8f8f984..0000000 --- a/src/Main.java +++ /dev/null @@ -1,10 +0,0 @@ -//TIP To Run code, press or -// click the icon in the gutter. -public class Main { - public static void main(String[] args) { - //TIP Press with your caret at the highlighted text - // to see how IntelliJ IDEA suggests fixing it. - System.out.println("Hello and welcome!"); - - } -} \ No newline at end of file diff --git a/src/abstractDataTypes/ArrayList.java b/src/abstractDataTypes/ArrayList.java new file mode 100644 index 0000000..63aba45 --- /dev/null +++ b/src/abstractDataTypes/ArrayList.java @@ -0,0 +1,473 @@ +package abstractDataTypes; + +import interfaces.List; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * @author tobygoetz + * @version 1.0 + * Generic ArrayList, to be used with any data type + * @param specifies data type to be used in ArrayList + */ +public class ArrayList implements List { + + private static final int CAPACITY = 10; + + // fields + private E[] buffer; + private int size; + + /** + * Constructor for ArrayList + */ + public ArrayList() + { + size = 0; + buffer = (E[]) new Object[CAPACITY]; + } + + /** + * Constructor for ArrayList + * @param array any array type + */ + public ArrayList(E[] array) + { + if (array.length < CAPACITY) { + + E[] newBuffer = (E[]) new Object[CAPACITY]; + + for (int i = 0; i < array.length; i++) { // { 1 + 1 + 2 (i = i + 1) * BL + newBuffer[i] = array[i]; + size++; + } buffer = newBuffer; + } + } + + + /** + * Add item to the front. + * (7(size) + 3) + (5(BL) + 6) == 15(size) + 9 at worst + * 7(size) + 3 at best + * 0(size) + * This function is linear because it reassigns all values to the + * index proceeding it, but calls resize() which is equivalently + * linear as well. + * + * @param item the item to be added + */ + @Override + public void addFront(E item) + { + //if buffer is at capacity increase buffer by one index + if (size == buffer.length) { // 1 + this.resize(buffer.length + 1); // f(n)= 5BL + 6 + 1 == O(n) + } + size++; // 2 + //Move all indices over one to make room at front + for (int i = size - 1; i > 0; i--) { // { 1 + 1 + 2 = 4 + buffer[i] = buffer[i - 1]; // 1 + 1 } * size + } + buffer[0] = item; // 1 + } // == f(size)= 7(n) + 8(n) + 3 + + /** + * Add item to the back. + * (5BL + 6) + 3 = 5BL + 9 at worst + * f(n) = 2 at best + * This function is constant at best and linear at worst. + * Function is only linear if buffer needs to resize to + * accommodate for 1 additional index + * + * @param item the item to be added + */ + @Override + public void addBack(E item) + { + //if buffer is at capacity increase buffer by one index + if (size == buffer.length) { + resize(size + 1); + } + //add value to size which is one index greater than last value + buffer[size] = item; + size++; + } + + /** + * Add an item at specified index (position). + * (7 + n)(size - index) + (6 + n) at worst + * O(3 + n) constant at best + * This function is linear at worst because it iterates (size - index) times + * and constant at best when invalid index throws exception which I am + * assuming is a constant constructor call. + * + * @param index the index where the item should be added + * @param item the item to be added + */ + @Override + public void add(int index, E item) + { + if (index < 0 || index > size) { // 3 + throw new IndexOutOfBoundsException("Specified Index Must Be " + // + n + "In the Range of 0-" + size); + } else { + //loop while index is greater than index value specified + for (int i = size; i >= index; i--) { // { 4 + //if buffer is at capacity increase buffer by one index + if (size == buffer.length) { // 1 + this.resize(buffer.length + 1); // 5BL + 6 + } + //index at highest buffer gets shifted right + if (i != 0) { // 1 + buffer[i] = buffer[i - 1]; // 1 } * (size - index) + } // == (7 + n)(size - index) + (6 + n) + } + } + buffer[index] = item; // 1 + size++; // 2 + } + + /** + * Get the item at a specified index. + * O(2 + n) at worst + * O(3) at best + * This function is linear across assuming that + * thrown exception is a relative linear constructor call and + * accounting for branches (I presume) + * + * @param index the index where the item should be retrieved + * @return the item located at that index + */ + @Override + public E get(int index) + { + if (index < 0 ) { // 1 + throw new IndexOutOfBoundsException( // n + "Index must be greater than 0"); + } else if (index >= size ) { // 1 + if (size == 0) { // 1 + throw new IndexOutOfBoundsException( // n + "This list is empty"); + } else { + throw new IndexOutOfBoundsException( // n + "Specified Index Must Be " + + "In the Range of 0-" + (size - 1)); // 1 + } + } return buffer[index]; // 1 + } + + /** + * Set (save) an item at a specified index. Previous + * item at that index is overwritten. + * O(3 + 1) at best + * O(4 + n) at worst + * This function is constant'ish but still technically linear + * because if O(3) = O(3 * n), then n = 1. Boom math... + * I want to say constant because I know a fixed amount at worst + * and at best, but not as constant as size() + * + * @param index the index where the item should be saved + * @param item the item to be saved + */ + @Override + public void set(int index, E item) + { + if (index < 0 || index >= size) { // 3 + throw new IndexOutOfBoundsException("Specified Index Must Be " + // n + "In the Range of 0-" + (size - 1)); // 1 + } else { + buffer[index] = item; // 1 + } + } + + /** + * Remove item at the front of the list. + * (6(size - 2) + 8) + ((5BL + 6) +2) + * O(BL) at worst + * O(size - 2) at best if buffer does not need to resize + * This function is linear because it iterates over entire + * array and possibly again through resize() + * + * @return the item that was removed + */ + @Override + public E removeFront() + { + if (!isEmpty()) { // 1 + O(3) + E removed = buffer[0]; // 1 + for (int i = 0; i <= size - 2; i++) { // { 4 + buffer[i] = buffer[i + 1]; // 1 + 1 } * (size - 2) + } size--; // 2 + + //Reduce buffer until original buffer size is reached + if (size >= 10) { // 1 + resize(size); // 5BL + 6 + // after buffer becomes 10 set removed values back to null + } else { + buffer[size] = null; // 1 + } + return removed; + } else { + return null; + } + } + + /** + * Remove item at the back of the list + * O(1) at best?? + * O(9) at worst + * Constant at best because return null is an assignment'ish + * + * @return the item that was removed + */ + @Override + public E removeBack() + { + if (!isEmpty()) { // O(3) + E removed = buffer[size - 1]; // 1 + 1 + buffer[size - 1] = null; // 1 + 1 + size--; // 2 + return removed; + } else { + return null; + } + } + + /** + * Remove item from the list + * (3 + BL) or O(12) or (11(size - 1) + 3) + 3 + O(size) + 5BL + 6) + * so 0(2n) at worst + * This function could definitely been written cleaner but in Britain + * they have the phrase 'any road' meaning you'll always get there as long + * as you keep driving... My logic took a binary search approach to finding + * the answer, but instead of analyzing one or the other I analyzed both. + * + * @param item the item to be removed + */ + @Override + public void remove(E item) + { + if (this.contains(item)) { // 0(size) + if (this.buffer[0].equals(item)) { // 1array access + 1 conditional + this.removeFront(); // 0(BL) + } else if (this.buffer[size - 1].equals(item)) { // 1 + 1 + 1 + this.removeBack(); // 0(9) + } else { + int index = 0; // 1 + while (!buffer[index].equals(item)) { // { 1 + 1 + index++; // 1 + 1 } * (BL - B[i]) + } + for (int i = index; i < size - 1; i++) { // { 4 + buffer[i] = buffer[i + 1]; // 1 + 1 } * size - 1 + } + size--; // 2 + if (size >= 10) { // 1 + resize(size); // 5BL + 6 + //after buffer becomes 10 set removed values back to null + } else { + buffer[size] = null; // 1 + 1 + } + } + } + } + + /** + * Remove item at a specified index. + * (((8(size -1) + 4) + 2) + 2) + 1) + * O(size - 1) at worst + * O(2) at best + * Almost constant on invalid input but linear if removing any index + * but the index at the back of array, I think I accounted for branching + * in this one. My assumption is don't include unreachable code in + * the calculation of the y-axis, but probably the conditionals themselves. + * + * @param index the index where the item should be removed + * @return the item that was removed + */ + @Override + public E remove(int index) + { + // first, check the index to see if it is valid + if (index < 0) { // 1 + throw new IndexOutOfBoundsException("Index cannot be negative"); // 1 + } else if (index >= size) { // 1 + throw new IndexOutOfBoundsException("Index is higher than size"); // 1 + } + + // save a copy of the value to be removed so that we can return it later + E copyOfRemovedValue = buffer[index]; // 1 + 1 + + // if index is last index with valid data, set data to null + if (index == size - 1) { // 1 + 1 + buffer[index] = null; // 1 + 1 + // shift all values over starting at index to be removed + } else { // { 4 + for (int i = index; i < size - 1; i++) { // 1 + 1 + 1 + 1 } * (size - 1) + buffer[i] = buffer[i + 1]; + } + } size--; // 2 + // set trailing index to null to account for reduced size + buffer[size] = null; // 1 + 1 + + return copyOfRemovedValue; // 1 + } + + /** + * Checks if an item is in the list. + * O(size) at worst + * O(1) at best + * This function is linear but constant in the case that an + * array is empty + * + * @param item the item to search for + * @return true if the item is in the list, false otherwise + */ + @Override + public boolean contains(Object item) + { + int index = 0; // 1 + while (index != size) { // { 1 + if (buffer[index].equals(item)) { // 1 + 1 + return true; // 1 + } else { + index++; // 1 + 1 } * size + } + } return false; // 1 + } + + /** + * Checks if the list is empty. + * 0(3) at best and worst + * This method is constant and will always be constant'ish + * but linear for all intents and purposes + * + * @return true if the list is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return size == 0 && buffer[0] == null; // 3 + } + + /** + * Provides a count of the number of items in the list. + * O(1) at best and worst + * Doesn't get much better than this + * + * @return number of items in the list + */ + @Override + public int size() { + return size; // 1 + } + + /** + * Returns an iterator over elements of type {@code T}. + * O(n) at best + * O(2^n) at worst + * Depends on how it's used in the client code... + * + * @return an Iterator. + */ + @Override + public Iterator iterator() { + return new ArrayListIterator(); // 1 + 1'ish + } + + private class ArrayListIterator implements Iterator { + + private int index; + + private ArrayListIterator() { index = 0;} + + /** + * Returns {@code true} if the iteration has more elements. + * (In other words, returns {@code true} if {@link #next} would + * return an element rather than throwing an exception.) + * + * @return {@code true} if the iteration has more elements + */ + @Override + public boolean hasNext() { + return index < size; + } + + /** + * Returns the next element in the iteration. + * + * @return the next element in the iteration + * @throws NoSuchElementException if the iteration has no more elements + */ + @Override + public E next() { + if (index >= size) { + throw new NoSuchElementException("Index is out of range"); + } + + E currentValue = buffer[index]; + index++; + return currentValue; + } + + @Override + public String toString() { + return "ArrayListIterator{" + + "index=" + index + + '}'; + } + } + + /** + * Helper method to resize ArrayIntlist to support + * more data + * f(BL) = 5BL + 6 + * O(n) at worst and at best + * This function is linear at worst because it loops over all existing + * indices in the buffer and still linear but insignificantly faster + * if new buffer is less than existing buffer + */ + private void resize(int newSize) { + //create new space, separate from the old space (buffer) +// int newSize = size + CAPACITY; + E[] newBuffer = (E[]) new Object[newSize]; // 1 + 3 (Assuming that new object is constant) + + // copy everything over from buffer into newBuffer + if (newSize > buffer.length) { // 1 + for (int i = 0; i < buffer.length; i++) { // { 1 + 1 + 2 (i = i + 1) * BL + newBuffer[i] = buffer[i]; // 1 } == 5BL + 6 + } // + } else { // + for (int i = 0; i < newBuffer.length; i++) { // { 1 + 1 + 2 * NBL + newBuffer[i] = buffer[i]; // 1 } == 5BL + 6 + } // + } + + // set the new space into buffer + buffer = newBuffer; // 1 + + // the old space is no longer "pointed to" and will eventually + // be cleaned up by the garbage collector + } + + /** + * If I remember right Strings are objects which are arrays of characters, + * thus a new String = an iteration over an array to build that string. + * So that being, each new String here is actually 0(String.length) + + * operands + static method call to toString which probably iterates again... + * O(bigNumber * character) + few operands + * 0(n) at worst... + * + * @return String representation of ArrayList + */ + @Override + public String toString() { + return "ArrayList{" + + "size=" + size + + ", indices=" + Arrays.toString(buffer) + + '}'; + } +} + + + diff --git a/src/abstractDataTypes/LinkedBag.java b/src/abstractDataTypes/LinkedBag.java new file mode 100644 index 0000000..45d3438 --- /dev/null +++ b/src/abstractDataTypes/LinkedBag.java @@ -0,0 +1,169 @@ +/** + * Toby Goetz + */ + +package abstractDataTypes; + +import interfaces.Bag; +import java.util.Iterator; +import java.util.ListIterator; + +/** + * @author Book People + * @version 1.0 + * @param + */ +public class LinkedBag implements Bag +{ + private Node first; + private int size; + private class Node + { + E item; + Node next; + + private Node(E item) + { + this.item = item; + } + + @Override + public String toString() { + return "Node{" + + "item=" + item + + ", next=" + next + + '}'; + } + } + + /** + * Add an item to the Bag. + * O(1) at worst + * This function is constant at worst because it only makes + * a few assignments at the front of the list + * @param item data value of any type + */ + @Override + public void add(E item) + { // Add item to the bag + Node oldFirst = first; + first = new Node(item); + first.next = oldFirst; + size++; + } + + /** + * Checks to see if the bag is empty. + * O(1) at worst + * This function is constant because it acceses an + * instance variable and returns a boolean value + * @return boolean true if bag is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return first == null; + } + + /** + * Returns a count of the number of items in the Bag. + * O(1) at worst + * This function is constant at worst because it + * only accesses an instance variable + * @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) at worst + * This function is linear at worst because it loops over + * all elements in the array. It could be Constant if the array + * is empty. Depends on how the client code uses it. + * @return an Iterator. + */ + @Override + public Iterator iterator() + { + return new ListIterator<>() + { + private Node current = first; + + @Override + public boolean hasNext() + { + return current != null; + } + + @Override + public E next() + { + E item = current.item; + current = current.next; + return item; + } + + @Override + public boolean hasPrevious() { + return false; + } + + @Override + public E previous() { + return null; + } + + @Override + public int nextIndex() { + return 0; + } + + @Override + public int previousIndex() { + return 0; + } + + @Override + public void remove() { + + } + + @Override + public void set(E item) { + + } + + @Override + public void add(E item) { + + } + }; + } + + /** + * O(n) at worst + * This function is linear at worst because it loops over + * all elements in the array. It could be Constant if the array + * is empty. + * @return String value representing the Bag + */ + @Override + public String toString() { + Node current = first; + String nodes = ""; + if (current != null) { + nodes += (current.item + ", "); + while (current.next != null) { + current = current.next; + nodes += (current.item); + if (current.next != null) { + nodes += ", "; + } + } + } + return "LinkedBag{" + "size=" + size + + "[" + nodes + "]}"; + } +} diff --git a/src/abstractDataTypes/LinkedList.java b/src/abstractDataTypes/LinkedList.java new file mode 100644 index 0000000..cd8cdef --- /dev/null +++ b/src/abstractDataTypes/LinkedList.java @@ -0,0 +1,491 @@ +package abstractDataTypes; + +import interfaces.List; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * @author tobygoetz + * @version 1.0 + * + * Generic LinkedList to be used with any data type + * @param + */ +public class LinkedList implements List { + + // Fields + private Node head; + private int size; + + /** + * Constructor to initialize the fields of LinkedIntList + */ + public LinkedList() { + head = null; + size = 0; + } + + // Node Class + private class Node { + private E data; + private Node next; + + /** + * Constuctor for Node that accepts on Integer data + * and sets the next to null + * @param data Integer value of Node + */ + private Node(E data) { + this.data = data; + this.next = null; + } + + /** + * Constuctor for Node that accepts on Integer data + * and sets the next to null + * @param data Integer Value of Node + * @param next Points to the next Node in list + */ + private Node(E data, Node next) { + this.data = data; + this.next = next; + } + + public String toString() { + return data + " -> "; + } + } + + /** + * Add item to the front. + * O(5) at best + * O(6) at worst + * This function is Constant because it makes + * a few assignments at most + * + * @param item the item to be added + */ + @Override + public void addFront(E item) + { + // new Node to be added + Node addedToFront = new Node(item); + // the list currently has some nodes in it + if (head != null) { + addedToFront.next = head; + } + head = addedToFront; + size++; + } + + /** + * Add item to the back. + * O(5) at best + * O(n) at worst + * This function is Linear because it loops over all + * values in the list, but can be constant in the case + * the list is empty + * @param item the item to be added + */ + @Override + public void addBack(E item) + { + Node addToBack = new Node(item); + + if (head == null) { + head = addToBack; + } else { + Node current = head; + + while (current.next != null) { + current = current.next; + } + current.next = addToBack; + } size++; + } + + /** + * Add an item at specified index (position). + * O(12) at best + * O(n) at worst + * This function is Linear because it loops over all + * values in the list if inserted at back and/or inserted + * in the middle (if inserted in between it iterates + * exactly equal to the index number provided). This + * function can be constant at best if exception are thrown + * or index requested is 0. + * + * @param index the index where the item should be added + * @param item the item to be added + */ + @Override + public void add(int index, E item) + { + int dex = 1; + //if requested index is out of range throw exception + if (index < 0 || index > (size)) { + throw new IndexOutOfBoundsException( + "Index must be in the Range 0-" + (size)); + //else find Node at index + } else { + //check if index is head + if (index == 0) { + addFront(item); + //check if index is at the end + } else if (index == size) { + addBack(item); + //remove everywhere else + } else { + Node current = head; + while (dex <= index - 1) { + current = current.next; + dex++; + } + current.next = new Node(item, current.next); + size++; + } + } + } + + /** + * Get the item at a specified index. + * O(7) at best + * O(n) at worst + * This function is Linear because it loops over all + * values in the list if the index being retrieved is + * at back and/or inserted in the middle (if inserted + * in between it iterates exactly equal to the index + * number provided). This function can be constant at + * best if exception are thrown or index requested is 0. + * + * @param index the index where the item should be retrieved + * @return the item located at that index + */ + @Override + public E get(int index) + { + int dex = 1; + + //if requested index is out of range throw exception + if (index < 0 || index > (size - 1)) { + throw new IndexOutOfBoundsException( + "Index must be in the Range 0-" + (size - 1)); + //else find Node at index + } else { + //head is always at index 0 + if (index == 0) { + return head.data; + } else { + Node current = head; + while(dex <= index) { + current = current.next; + dex++; + } + return current.data; + } + } + } + + /** + * Set (save) an item at a specified index. Previous + * item at that index is overwritten. + * O(5) at best + * O(n) + * This function is Linear because it loops over all + * values in the list if the index being set is + * at back and/or towards the middle (if inserted + * in between it iterates exactly equal to the index + * number provided). This function can be constant at + * best if exception are thrown or index requested is 0. + * + * @param index the index where the item should be saved + * @param item the item to be saved + */ + @Override + public void set(int index, E item) + { + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException("Specified Index Must Be " + + "In the Range of 0-" + (size - 1)); + } else { + Node newNode = new Node(item); + Node current = head; + + if (index == 0) { + if (head != null) { + newNode.next = head.next; + } head = newNode; + + } else if (index == (size - 1)) { + while (current.next.next != null) { + current = current.next; + } current.next = newNode; + + } else { + for (int i = 1; i < index; i++) { + current = current.next; + } + newNode.next = current.next.next; + current.next = newNode; + } + } + } + + /** + * Remove item at the front of the list. + * O(1) at best + * O(7) at worst + * This function is constant because it is a few + * assignments, but could be O(1) if head is + * being retrieved from an empty list. + * + * @return the item that was removed + */ + @Override + public E removeFront() + { + if (head != null) { + E removedData = head.data; + if (head.next != null) { + head = head.next; + } else { + head = null; + } + size--; + return removedData; + } return null; + } + + /** + * Remove item at the back of the list + * O(2) at best + * O(n) at worst + * This function is Linear because it loops over all + * values in the list when trying to remove the back + * value. This function can be constant at best if the + * list is empty. + * @return the item that was removed + */ + @Override + public E removeBack() + { + if (head != null) { + Node current = head; + + if (current.next != null) { + while (current.next.next != null) { + current = current.next; + } + E removedData = current.next.data; + current.next = null; + size--; + return removedData; + } else { + E removedData = head.data; + head = null; + size = 0; + return removedData; + } + } return null; + } + + /** + * Remove item from the list + * O(n) at best + * O(2n) at worst? + * This function is linear but could potentially + * loop over all values twice. + * @param item the item to be removed + */ + @Override + public void remove(E item) + { + if (this.contains(item)) { + Node current = head; + if (head.data.equals(item)) { + removeFront(); + } else { + while (!current.next.data.equals(item)) { + current = current.next; + } + current.next = current.next.next; + size--; + } + } + } + + /** + * Remove item at a specified index. + * O(1) at best + * O(n) at worst + * Very likely to loop over all elements unless + * exceptions are thrown or removeFront() is + * called. + * @param index the index where the item should be removed + * @return the item that was removed + */ + @Override + public E remove(int index) + { + int dex = 1; + E removedData; + + //if requested index is out of range throw exception + if (index < 0 || index > (size - 1)) { + throw new IndexOutOfBoundsException( + "Index must be in the Range 0-" + (size - 1)); + } else { + //check if index is head + if (index == 0) { + removedData = head.data; + removeFront(); + } else { + Node current = head; + while (dex <= index - 1) { + current = current.next; + dex++; + } + removedData = current.next.data; + current.next = current.next.next; + size--; + } + return removedData; + } + } + + /** + * Checks if an item is in the list. + * O(1) at best + * O(n) at worst + * This function is linear because it will potentially + * loop over all elements in the list, but rarely + * constant if the list is empty. + * @param item the item to search for + * @return true if the item is in the list, false otherwise + */ + @Override + public boolean contains(E item) + { + if (head != null) { + Node current = head; + if (current.data.equals(item)) { + return true; + } else { + while (current.next != null) { + current = current.next; + if (current.data.equals(item)) { + return true; + } + } + } + } return false; + } + + /** + * Checks if the list is empty. + * O(1) + * This Function is constant because it is one + * conditional and one return. + * + * @return true if the list is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return size == 0; + } + + /** + * Provides a count of the number of items in the list. + * O(1) + * This Function is constant because it is one return. + * + * @return number of items in the list + */ + @Override + public int size() { + return size; + } + + /** + * Returns an iterator over elements of type {@code T}. + * O(1) at best + * O(2^n) at worst + * Depends on how it's used in the client code... + * + * @return an Iterator. + */ + @Override + public Iterator iterator() { + return new LinkedListIterator(); + } + + private class LinkedListIterator implements Iterator { + + private Node current; + + public LinkedListIterator() { + current = head; + } + + /** + * Returns {@code true} if the iteration has more elements. + * (In other words, returns {@code true} if {@link #next} would + * return an element rather than throwing an exception.) + * O(1) + * This function is constant because it returns a conditional. + * + * @return {@code true} if the iteration has more elements + */ + @Override + public boolean hasNext() { + return current != null; + } + + /** + * Returns the next element in the iteration. + * O(1) + * This function is constant because it returns an assignment. + * @return the next element in the iteration + * @throws NoSuchElementException if the iteration has no more elements + */ + @Override + public E next() { + if (current == null) { + throw new NoSuchElementException("There is no next one to go to!"); + } + E dataValue = current.data; + current = current.next; + return dataValue; + } + + @Override + public String toString() { + return "LinkedListIterator{" + + "current=" + current + + '}'; + } + } + + + + @Override + public String toString() { + Node current = head; + String list = "LinkedIntList{size=" + size + ", list=["; + + if (current == null) { + list += "]}"; + } else { + while (current != null) { + list += current.data; + if (current.next != null) { + list += ", "; + } else { + list += "]}"; + } + current = current.next; + } + } return list; + } +} diff --git a/src/abstractDataTypes/LinkedQueue.java b/src/abstractDataTypes/LinkedQueue.java new file mode 100644 index 0000000..5778974 --- /dev/null +++ b/src/abstractDataTypes/LinkedQueue.java @@ -0,0 +1,201 @@ +/** + * Toby Goetz + */ + +package abstractDataTypes; + +import interfaces.Queue; +import java.util.Iterator; +import java.util.ListIterator; + +/** + * @author Book People + * @version 1.0 + * @param + */ +public class LinkedQueue implements Queue +{ + private Node first; + private Node last; + private int size; + + private class Node + { + E item; + Node next; + + private Node(E item) + { + this.item = item; + } + + @Override + public String toString() { + return "Node{" + + "item=" + item + + ", next=" + next + + '}'; + } + } + + /** + * Add an item to the queue. + * O(1) at worst + * This function is constant at worst because it only makes + * a few assignments at the front of the list and isEmpty() + * is constant as well + * @param item the item to be added + */ + @Override + public void enqueue(E item) + { // Add item to the end of the list. + Node oldLast = last; + last = new Node(item); + last.next = null; + + if (isEmpty()) { + first = last; + } else { + oldLast.next = last; + } size++; + } + + /** + * Remove an item from the queue. + * O(1) at worst + * This function is constant at worst because it only makes + * a few assignments at the front of the list and isEmpty() + * is constant as well + * @return the item that was removed + */ + @Override + public E dequeue() + { // Remove item from the beginning of the list. + E item = first.item; + first = first.next; + + if ( isEmpty()) { + last = null; + } size--; + + return item; + } + + /** + * Checks to see if the queue is empty. + * O(1) at worst + * This function is constant because it acceses an + * instance variable and returns a boolean value + * @return true if the queue is empty, false otherwise + */ + @Override + public boolean isEmpty() + { + return first == null; + } + + /** + * Returns a count of the number of items in the queue. + * O(1) at worst + * This function is constant at worst because it + * only accesses an instance variable + * @return the number of items in the queue + */ + @Override + public int size() + { + return size; + } + + /** + * Returns an iterator over elements of type {@code T}. + * O(n) at worst + * This function is linear at worst because it loops over + * all elements in the array. It could be Constant if the array + * is empty. Depends on how the client code uses it. + * @return an Iterator. + */ + @Override + public Iterator iterator() + { + return new ListIterator<>() + { + private Node current = first; + + @Override + public boolean hasNext() { + return current != null; + } + + @Override + public E next() { + E item = current.item; + current = current.next; + return item; + } + + @Override + public boolean hasPrevious() { + return false; + } + + @Override + public E previous() { + return null; + } + + @Override + public int nextIndex() { + return 0; + } + + @Override + public int previousIndex() { + return 0; + } + + @Override + public void remove() { + + } + + @Override + public void set(E item) { + + } + + @Override + public void add(E item) { + + } + }; + } + + /** + * O(n) at worst + * This function is linear at worst because it loops over + * all elements in the array. It could be Constant if the array + * is empty. + * @return String value representing the queue + */ + @Override + public String toString() + { + Node current = first; + String nodes = ""; + if (current != null) { + nodes += (current.item + ", "); + while (current.next != null) { + current = current.next; + nodes += (current.item); + if (current.next != null) { + nodes += ", "; + } + } + } + return "LinkedQueue{" + + "(" + size + " left on stack) " + + nodes; + + } +} diff --git a/src/abstractDataTypes/LinkedStack.java b/src/abstractDataTypes/LinkedStack.java new file mode 100644 index 0000000..9be839e --- /dev/null +++ b/src/abstractDataTypes/LinkedStack.java @@ -0,0 +1,199 @@ +/** + * Toby Goetz + */ + +package abstractDataTypes; + +import interfaces.Stack; +import java.util.Iterator; +import java.util.ListIterator; + +/** + * @author Book People + * @version 1.0 + * @param + */ +public class LinkedStack implements Stack { + + private Node first; + private int size; + + private class Node + { // Nested class to define Node + E item; + Node next; + + private Node(E item) + { + this.item = item; + } + + @Override + public String toString() { + return "Node{" + + "item=" + item + + ", next=" + next + + '}'; + } + } + + /** + * Add an item to the stack. + * O(1) at worst + * This function is constant at worst because it only makes + * a few assignments at the front of the list + * @param item the item to be added + */ + @Override + public void push(E item) + { // Add item to the top of the stack + Node oldFirst = first; + first = new Node(item); + first.next = oldFirst; + size++; + } + + /** + * Removes the most recently added item from the stack. + * O(1) at worst + * This function is constant at worst because it only makes + * a few assignments at the front of the list + * @return the item that was removed + */ + @Override + public E pop() + { // Remove item from the top of the stack + E item = first.item; + first = first.next; + size--; + return item; + } + + /** + * Returns the item at the top of the stack. + * Does not modify the stack or the item at the top. + * O(1) at worst + * This function is constant because it accesses an + * element in an array + * @return item at the top of the stack. + */ + @Override + public E peek() { + return first.item; + } + + /** + * Checks to see if the stack is empty. + * O(1) at worst + * This function is constant because it acceses an + * instance variable and returns a boolean value + * @return true if the stack is empty, false otherwise + */ + @Override + public boolean isEmpty() { + return first == null; + } + + /** + * Returns a count of the number of items in the stack. + * O(1) at worst + * This function is constant at worst because it + * only accesses an instance variable + * @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) at worst + * This function is linear at worst because it loops over + * all elements in the array. It could be Constant if the array + * is empty. Depends on how the client code uses it. + * @return an Iterator. + */ + @Override + public Iterator iterator() + { + return new ListIterator<>() + { + private Node current = first; + + @Override + public boolean hasNext() { + return current != null; + } + + @Override + public E next() + { + E item = current.item; + current = current.next; + return null; + } + + @Override + public boolean hasPrevious() { + return false; + } + + @Override + public E previous() { + return null; + } + + @Override + public int nextIndex() { + return 0; + } + + @Override + public int previousIndex() { + return 0; + } + + @Override + public void remove() { + + } + + @Override + public void set(E item) { + + } + + @Override + public void add(E item) { + + } + }; + } + + /** + * O(n) at worst + * This function is linear at worst because it loops over + * all elements in the array. It could be Constant if the array + * is empty. + * @return String value representing the list + */ + @Override + public String toString() { + Node current = first; + String nodes = ""; + if (current != null) { + nodes += (current.item + ", "); + while (current.next != null) { + current = current.next; + nodes += (current.item); + if (current.next != null) { + nodes += ", "; + } + } + } + return "LinkedStack{" + + "(" + size + " left on stack) " + + nodes; + } +} diff --git a/src/abstractDataTypes/ResizingArrayStack.java b/src/abstractDataTypes/ResizingArrayStack.java new file mode 100644 index 0000000..352f468 --- /dev/null +++ b/src/abstractDataTypes/ResizingArrayStack.java @@ -0,0 +1,174 @@ +/** + * Toby Goetz + */ + +package abstractDataTypes; + +import interfaces.Stack; +import java.util.Arrays; +import java.util.Iterator; + +/** + * @author Book People + * @version 1.0 + * @param + */ +public class ResizingArrayStack implements Stack { + + private E[] arr; + private int size; + + /** + * Constructor to instantiate ResizingArrayStack + * 0(1) at worst because of a few assignments + */ + public ResizingArrayStack() + { + this.arr = (E[]) new Object[1]; + size = 0; + } + + /** + * Add an item to the stack. + * O(n) at worst + * O(1) at best + * This function is linear at worst because it utilizes + * resize() to resize the array which is linear. It is + * logarithmically constant, meaning that resize() is + * only called n^2 times + * @param item the item to be added + */ + @Override + public void push(E item) + { // Add item to the top of stack + if (size == arr.length) { + resize(2 * arr.length); + } + arr[size++] = item; + } + + /** + * Removes the most recently added item from the stack. + * O(n) at worst + * O(1) at best + * This function is linear at worst because it utilizes + * resize() to resize the array which is linear. It is + * logarithmically constant, meaning that resize() is + * only called n^2 times (math might be wrong) + * @return the item that was removed + */ + @Override + public E pop() + { // Remove item from top of Stack + E item = arr[--size]; + arr[size] = null; + if (size > 0 && size == arr.length/4) { + resize(arr.length/2); + } + return item; + } + + /** + * Returns the item at the top of the stack. + * Does not modify the stack or the item at the top. + * O(1) at worst + * This function is constant because it accesses an + * element in an array + * @return item at the top of the stack. + */ + @Override + public E peek() { + return arr[size - 1]; + } + + /** + * Checks to see if the stack is empty. + * O(1) at worst + * This function is constant because it acceses an + * instance variable and returns a boolean value + * @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) at worst + * This function is constant at worst because it + * only accesses an instance variable + * @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) at worst + * This function is linear at worst because it loops over + * all elements in the array. It could be Constant if the array + * is empty. Depends on how the client code uses it. + * @return an Iterator. + */ + @Override + public Iterator iterator() + { + return new ReverseArrayIterator(); + } + + private class ReverseArrayIterator implements Iterator + { // Support LIFO iteration + private int current = size; + @Override + public boolean hasNext() { + return current > 0; + } + @Override + public E next() { + return arr[--current]; + } + @Override + public void remove() {} + + @Override + public String toString() { + return "ReverseArrayIterator{" + + "i=" + current + + '}'; + } + } + + /** + * Resizes the instance Array arr + * O(n) at worst + * This function is linear at worst because it loops over + * all elements in the array. It could be Constant if the array + * is empty. + * @param newLength initializes the Array arr to newLength size + */ + private void resize(int newLength) + { //Move stack to a new array of size newLength + E[] temp = (E[]) new Object[newLength]; + for (int i = 0; i < size; i++) { + temp[i] = arr[i]; + } + arr = temp; + } + + /** + * O(n) at worst + * This function is linear at worst because it loops over + * all elements in the array. It could be Constant if the array + * is empty. + * @return String value representing the list + */ + @Override + public String toString() { + return "ResizingArrayStack{ " + + "(" + size + " left on stack) " + + Arrays.toString(arr) + " }"; + } +} diff --git a/src/driver/Main.java b/src/driver/Main.java new file mode 100644 index 0000000..c8767f8 --- /dev/null +++ b/src/driver/Main.java @@ -0,0 +1,159 @@ +package driver; + +import abstractDataTypes.ArrayList; +import abstractDataTypes.LinkedList; + +//TIP To Run code, press or +// click the icon in the gutter. + +/** + * @author tobygoetz + * @version 1.0 + * Driver class to test ArrayList and LinkedList that + * implement list.java + */ +public class Main { + + public static final int ITERATIONS = 25; + + /** + * program to run Main Class + * @param args command line arguments + */ + public static void main(String[] args) { + //TIP Press with your caret at the highlighted text + // to see how IntelliJ IDEA suggests fixing it. + System.out.println("Hello and welcome!"); + + class Cat { + private String breed; + + public Cat(String breed) { + this.breed = breed; + } + + @Override + public String toString() { + return breed; + } + } + + String[] breeds = new String[]{ + "Tabby", "Siamese", "Calico"}; + + ArrayList listOfObjects = new ArrayList<>(); + listOfObjects.addFront(10); + listOfObjects.addFront("Fresno"); + listOfObjects.addFront(ITERATIONS); + listOfObjects.addFront('a'); + listOfObjects.addFront(new Cat(breeds[1])); + listOfObjects.addFront(breeds); + + System.out.println(listOfObjects); + + listOfObjects.addBack(new Cat(breeds[0])); + listOfObjects.addBack(new Cat(breeds[1])); + listOfObjects.addBack(new Cat(breeds[0])); + listOfObjects.addBack(new Cat(breeds[0])); + listOfObjects.addBack(new Cat(breeds[0])); + listOfObjects.addBack(new Cat(breeds[0])); + System.out.println(listOfObjects); + + listOfObjects.set(0, 0); + System.out.println(listOfObjects); + + listOfObjects.set((listOfObjects.size() -1), (listOfObjects.size() - 1)); + listOfObjects.set(0, "front"); + System.out.println(listOfObjects.size()); + System.out.println(listOfObjects); + + System.out.println(listOfObjects.removeFront()); + System.out.println(listOfObjects.removeFront()); + System.out.println(listOfObjects.removeBack()); + System.out.println(listOfObjects.removeBack()); + Cat lion = new Cat("Lion"); + listOfObjects.addFront(lion); + + System.out.println(listOfObjects.contains(lion)); + listOfObjects.removeBack(); + listOfObjects.removeBack(); + listOfObjects.removeBack(); + listOfObjects.removeBack(); + listOfObjects.removeBack(); + System.out.println(listOfObjects.contains("Fresn!")); + + System.out.println(listOfObjects); + + System.out.println(listOfObjects.contains('a')); + + System.out.println(); + System.out.println(listOfObjects); + listOfObjects.remove((Object) 'a'); + System.out.println(listOfObjects); + + System.out.println(listOfObjects.remove(0)); + System.out.println(listOfObjects); + + + + + + + // LinkedList Tests + + LinkedList linkedList = new LinkedList<>(); + + linkedList.addFront("Toby"); + linkedList.addFront(Math.random()); + linkedList.addFront('%'); + + linkedList.addBack(3); + linkedList.addBack(4); + linkedList.addBack(5); + + linkedList.add(3, "Middle"); + linkedList.add(0, "Front"); + linkedList.add(8, "End"); + + System.out.println(linkedList); + + System.out.println(linkedList.get(3)); + + System.out.println(linkedList.contains(Math.random())); + + System.out.println(linkedList); + + linkedList.set(0, "Tobiah"); + linkedList.set(8, "Howdy"); + linkedList.set(4, "Howdy"); + System.out.println(linkedList); + + System.out.println(linkedList.removeFront()); + System.out.println(linkedList); + System.out.println(linkedList.removeFront()); + System.out.println(linkedList); + System.out.println(linkedList.removeFront()); + System.out.println(linkedList); + + System.out.println(linkedList.removeBack()); + System.out.println(linkedList); + System.out.println(linkedList.removeBack()); + System.out.println(linkedList); + + linkedList.remove("Toby"); + System.out.println(linkedList); + + System.out.println(linkedList.remove(0)); + System.out.println(linkedList); + + System.out.println(); + System.out.println(); + System.out.println(); + System.out.println(); + + ArrayList tobysList = new ArrayList<>(); + System.out.println(tobysList); + tobysList.addFront("Toby"); + System.out.println(tobysList.get(0)); + } +} \ No newline at end of file diff --git a/src/driver/QueueTestClient.java b/src/driver/QueueTestClient.java new file mode 100644 index 0000000..a4fd33d --- /dev/null +++ b/src/driver/QueueTestClient.java @@ -0,0 +1,39 @@ +/** + * Toby Goetz + */ + +package driver; + +import abstractDataTypes.LinkedQueue; +import java.util.Scanner; + +/** + * @author Book People + * @version 1.0 + */ +public class QueueTestClient +{ + public static final String SHAKESPREARE = "to be or not to - be - - that - - - is"; + + public static void main(String[] args) + { // Create a queue and enqueue/dequeue strings. + LinkedQueue linkedQueue = new LinkedQueue(); + Scanner in = new Scanner(SHAKESPREARE); + String poppedValues = ""; + + System.out.println("LinkedQueue:::Trace"); + System.out.println("-------------------"); + + while (in.hasNext()) { + String item = in.next(); + if (!item.equals("-")) { + linkedQueue.enqueue(item); + } + else if (!linkedQueue.isEmpty()) { + poppedValues += linkedQueue.dequeue() + " "; + } + System.out.println("(" + linkedQueue); + } + System.out.println("\n" + poppedValues + " (" + linkedQueue.size() + " left on stack)"); + } +} diff --git a/src/driver/StackTestClient.java b/src/driver/StackTestClient.java new file mode 100644 index 0000000..a2363ef --- /dev/null +++ b/src/driver/StackTestClient.java @@ -0,0 +1,64 @@ +/** + * Toby Goetz + */ + +package driver; +import abstractDataTypes.LinkedStack; +import abstractDataTypes.ResizingArrayStack; +import interfaces.Stack; + +import java.util.Scanner; + +/** + * @author Book People + * @version 1.0 + */ +public class StackTestClient { + + public static final String SHAKESPREARE = "to be or not to - be - - that - - - is"; + + public static void main(String[] args) + { + String poppedValues = ""; + + System.out.println("ResizingArrayStack:::Trace"); + System.out.println("--------------------------"); + + Stack arrayStack = new ResizingArrayStack(); + Scanner in = new Scanner(SHAKESPREARE); + + while (in.hasNext()) { + String item = in.next(); + if (!item.equals("-")) { + arrayStack.push(item); + } + else if (!arrayStack.isEmpty()) { + poppedValues += arrayStack.pop() + " "; + } + System.out.println("(" + arrayStack); + } + System.out.println("\n" + poppedValues + " (" + arrayStack.size() + " left on stack)"); + + + + poppedValues = ""; + System.out.println("\n \nLinkedStack:::Trace"); + System.out.println("---------------------"); + + Stack linkedStack = new LinkedStack(); + in = new Scanner(SHAKESPREARE); + + while (in.hasNext()) { + String item = in.next(); + if (!item.equals("-")) { + linkedStack.push(item); + } + else if (!linkedStack.isEmpty()) { + poppedValues += linkedStack.pop() + " "; + } + System.out.println("(" + linkedStack); + } + System.out.println("\n" + poppedValues + " (" + linkedStack.size() + " left on stack)"); + + } +} diff --git a/src/driver/Stats.java b/src/driver/Stats.java new file mode 100644 index 0000000..883e326 --- /dev/null +++ b/src/driver/Stats.java @@ -0,0 +1,37 @@ +/** + * Toby Goetz + */ + +package driver; +import abstractDataTypes.LinkedBag; +import java.util.Scanner; + +public class Stats +{ + public static void main(String[] args) + { + Scanner in = new Scanner("100 99 101 120 98 107 109 81 101 90"); + LinkedBag bagOfNumbers = new LinkedBag<>(); + + while (in.hasNext()) { + bagOfNumbers.add(in.nextDouble()); + } + int bagSize = bagOfNumbers.size(); + double sum = 0.0; + + for (double x : bagOfNumbers) { + sum += x; + } + double mean = sum/bagSize; + sum = 0.0; + + for (double x : bagOfNumbers) { + sum += (x - mean) * (x - mean); + } + double std = Math.sqrt(sum/(bagSize-1)); + + System.out.println(bagOfNumbers); + System.out.printf("Mean: %.2f\n", mean); + System.out.printf("Std dev: %.2f\n", std); + } +} diff --git a/src/interfaces/Bag.java b/src/interfaces/Bag.java new file mode 100644 index 0000000..3a03166 --- /dev/null +++ b/src/interfaces/Bag.java @@ -0,0 +1,27 @@ +package interfaces; + +/** + * interfaces.Bag (API / abstract data type) + * @param Class or data type of the items in the list + * @author unknown + * @version 1.0 + */ +public interface Bag extends Iterable { + + /** + * Add item to the Bag + * @param item the item to be added + */ + void add(E item); + /** + * Checks if the list is empty. + * @return true if the list is empty, false otherwise + */ + boolean isEmpty(); + /** + * Provides a count of the number of items in the list. + * @return number of items in the list + */ + int size(); + +} diff --git a/src/Deque.java b/src/interfaces/Deque.java similarity index 92% rename from src/Deque.java rename to src/interfaces/Deque.java index 0107f47..ccc0916 100644 --- a/src/Deque.java +++ b/src/interfaces/Deque.java @@ -1,5 +1,7 @@ +package interfaces; + /** - * Deque: double-ended queue API + * interfaces.Deque: double-ended queue API * Supports adding and removing items at both ends. * * @param diff --git a/src/List.java b/src/interfaces/List.java similarity index 75% rename from src/List.java rename to src/interfaces/List.java index 2bf4aef..87be239 100644 --- a/src/List.java +++ b/src/interfaces/List.java @@ -1,6 +1,12 @@ -/*** - * List interface (API / abstract data type) +package interfaces; + +import abstractDataTypes.ArrayList; + +/** + * interfaces.List interface (API / abstract data type) * @param Class or data type of the items in the list. + * @author unknown + * @version 1.0 */ public interface List extends Iterable { /** @@ -17,25 +23,25 @@ public interface List extends Iterable { /** * Add an item at specified index (position). - * @param i the index where the item should be added + * @param index the index where the item should be added * @param item the item to be added */ - void add(int i, E item); + void add(int index, E item); /** * Get the item at a specified index. - * @param i the index where the item should be retrieved + * @param index the index where the item should be retrieved * @return the item located at that index */ - E get(int i); + E get(int index); /** * 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 index the index where the item should be saved * @param item the item to be saved */ - void set(int i, E item); + void set(int index, E item); /** * Remove item at the front of the list. @@ -57,10 +63,10 @@ public interface List extends Iterable { /** * Remove item at a specified index. - * @param i the index where the item should be removed + * @param index the index where the item should be removed * @return the item that was removed */ - E remove(int i); + E remove(int index); /** * Checks if an item is in the list. @@ -81,3 +87,5 @@ public interface List extends Iterable { */ int size(); } + + diff --git a/src/MathSet.java b/src/interfaces/MathSet.java similarity index 85% rename from src/MathSet.java rename to src/interfaces/MathSet.java index 5464cf7..b8ca20d 100644 --- a/src/MathSet.java +++ b/src/interfaces/MathSet.java @@ -1,12 +1,14 @@ +package interfaces; + /** - * MathSet API (interface / abstract data type) + * interfaces.MathSet API (interface / abstract data type) * represents a mathematical set. Sets in mathematics * have unique elements (keys) and there are no duplicate keys. * - * In this MathSet API, we have an additional constraint that + * In this interfaces.MathSet API, we have an additional constraint that * traditional mathematical sets do not have. In mathematical sets, * elements are unordered, order of keys does not matter. In this - * MathSet API, we require items to be Comparable so we can maintain + * interfaces.MathSet API, we require items to be Comparable so we can maintain * them in order. By keeping items in order, we can guarantee * some reasonable performance for the set operations (union, * intersection, difference, symmetric difference) and for search @@ -60,7 +62,7 @@ public interface MathSet extends Iterable { * 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 + * @return new interfaces.MathSet that contains the union */ MathSet union(MathSet other); @@ -68,7 +70,7 @@ public interface MathSet extends Iterable { * 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 + * @return new interfaces.MathSet that contains the intersection */ MathSet intersection(MathSet other); @@ -76,7 +78,7 @@ public interface MathSet extends Iterable { * 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 + * @return new interfaces.MathSet that contains the difference */ MathSet difference(MathSet other); @@ -84,7 +86,7 @@ public interface MathSet extends Iterable { * 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 + * @return new interfaces.MathSet that contains the symmetric difference */ MathSet symmetricDifference(MathSet other); diff --git a/src/Queue.java b/src/interfaces/Queue.java similarity index 89% rename from src/Queue.java rename to src/interfaces/Queue.java index ab5ca29..bceaf58 100644 --- a/src/Queue.java +++ b/src/interfaces/Queue.java @@ -1,5 +1,7 @@ +package interfaces; + /** - * FIFO (first-in, first-out) Queue API + * FIFO (first-in, first-out) interfaces.Queue API * @param class / data type of the items in the queue */ public interface Queue extends Iterable { diff --git a/src/Stack.java b/src/interfaces/Stack.java similarity index 91% rename from src/Stack.java rename to src/interfaces/Stack.java index bb1000d..f6ddac7 100644 --- a/src/Stack.java +++ b/src/interfaces/Stack.java @@ -1,5 +1,7 @@ +package interfaces; + /** - * Stack (LIFO: last-in, first-out) API + * interfaces.Stack (LIFO: last-in, first-out) API * @param class / data type of the items in the stack */ public interface Stack extends Iterable { diff --git a/tests/ArrayListTest.java b/tests/ArrayListTest.java new file mode 100644 index 0000000..f3716cb --- /dev/null +++ b/tests/ArrayListTest.java @@ -0,0 +1,320 @@ +import abstractDataTypes.ArrayList; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Test Class for ArrayIntList + * @author tobygoetz + * @version 1.0 + */ +public class ArrayListTest { + private ArrayList testArrayList = new ArrayList<>((E[]) new Object[]{}); + private E[] genericArray = (E[]) new Object[]{ + "Test", 1, 'a', Math.random(), 1L, (byte) 0x00, 7, 8, 9, 10, "Eleven", "Twelve"}; + private Exception exception; + private static final int ITERATIONS = 15; + + /** + * Test adds genericArray values to the front when empty, almost empty, + * not empty and when buffer is larger than the initial size of 10 is + * surpassed. + */ + @Test + public void addFrontTest() + { + for (int i = 0; i < genericArray.length; i++) { + testArrayList.addFront(genericArray[i]); + assertEquals(genericArray[i], testArrayList.get(0)); + } + } + + /** + * Test adds genericArray values to the back when empty, almost empty, + * not empty and when buffer is larger than initial size of 10 is + * surpassed. + */ + @Test + public void addBackTest() + { + for (int i = 0; i < genericArray.length; i++) { + testArrayList.addBack(genericArray[i]); + // Index 0 changes everytime addFront is called + assertEquals(genericArray[i], testArrayList.get(testArrayList.size() - 1)); + } + } + + /** + * Test adds Integer values at specific index when empty, almost + * empty,not empty and when buffer is larger than initial size of + * 10 is surpassed. + */ + @Test + public void addTest() + { + // Adds Index at i incrementing + for (int i = 0; i < ITERATIONS; i++) { + testArrayList.add(i, (E) (Integer) i); + assertEquals(i, testArrayList.get(i)); + } + + // Adds Index at i decrementing + for (int i = ITERATIONS; i >= 0; i--) { + testArrayList.add(i, (E) (Integer) i); + assertEquals(i, testArrayList.get(i)); + } + + //IndexOutOfBoundsException is thrown if -1 is called + exception = assertThrows( + IndexOutOfBoundsException.class, () -> { + testArrayList.add(-1, (E) (Integer) ITERATIONS); + }); + + //IndexOutOfBoundsException is thrown if index larger than size of ArrayList is requested + exception = assertThrows( + IndexOutOfBoundsException.class, () -> { + testArrayList.add(testArrayList.size() + 1, (E) (Integer) ITERATIONS); + }); + } + + /** + * Tests if values at specific index have been set when empty, + * almost empty,not empty and when buffer is larger than initial + * size of 10 is surpassed. Tests exceptions when attempting to + * set index that is out of range. + * */ + @Test + public void setTest() { + + assertTrue(testArrayList.isEmpty()); + + //IndexOutOfBoundsException is thrown if -1 is called + exception = assertThrows( + IndexOutOfBoundsException.class, () -> { + testArrayList.set(-1, (E) (Integer) ITERATIONS); + }); + + //IndexOutOfBoundsException is thrown if index larger than size of ArrayList is requested + exception = assertThrows( + IndexOutOfBoundsException.class, () -> { + testArrayList.set(testArrayList.size() + 1, (E) (Integer) ITERATIONS); + }); + + //reassign values + this.fillArray(); + assertFalse(testArrayList.isEmpty()); + for (int i = 0; i < genericArray.length; i++) { + testArrayList.set(i, (E)(Integer) ITERATIONS); + assertEquals(ITERATIONS, testArrayList.get(i)); + } + } + + /** + * Test removes Integer values from the front of ArrayIntList when + * empty, almost empty and not empty. Asserts that null is returned + * when removeFront() is called don an empty array. + */ + @Test + public void removeFrontTest() + { + //test that an empty array returns null when removeFront() is called + testArrayList.removeFront(); + assertTrue(testArrayList.isEmpty()); + assertNull(testArrayList.removeFront()); + + + //test with 1 value in array + testArrayList.addFront((E) (Integer) ITERATIONS); + testArrayList.removeFront(); + assertTrue(testArrayList.isEmpty()); + + //fill the Array + for (int i = 0; i <= ITERATIONS; i++) { + testArrayList.add(i, (E) (Integer) i); + } + for (int i = 0; i < ITERATIONS; i++) { + E removedValue = testArrayList.get(1); + testArrayList.removeFront(); + assertEquals(removedValue, testArrayList.get(0)); + } + } + + /** + * Test removes Integer values from the front of ArrayIntList when + * empty, almost empty and not empty. Asserts that null is returned + * when removeBack() is called don an empty array. + */ + @Test + public void removeBackTest() + { + //test with empty array + assertTrue(testArrayList.isEmpty()); + assertNull(testArrayList.removeBack()); + + //reassign values + this.fillArray(); + for (int i = 0; i < genericArray.length; i++) { + E removedValue = testArrayList.get(testArrayList.size() - 1); + assertEquals(removedValue, testArrayList.removeBack()); + } + } + + /** + * Test removes genericArray values at specific index when empty, almost + * empty,not empty and when buffer is larger than initial size of + * 10 is surpassed. + */ + @Test + public void removeIndexTest() + { + //test with empty array + assertTrue(testArrayList.isEmpty()); + exception = assertThrows( + IndexOutOfBoundsException.class, () -> { + testArrayList.remove(0); + }); + + //test with index greater than size of array + exception = assertThrows( + IndexOutOfBoundsException.class, () -> { + testArrayList.remove(1); + }); + + //reassign values + this.fillArray(); + assertFalse(testArrayList.isEmpty()); + + //test with index greater than size of array + exception = assertThrows( + IndexOutOfBoundsException.class, () -> { + testArrayList.remove(testArrayList.size()); + }); + + for (int i = 0; i < genericArray.length - 1; i++) { + E valueAfterRemoved = testArrayList.get(1); + testArrayList.remove(0); + assertEquals(valueAfterRemoved, testArrayList.get(0)); + } + } + + /** + * Test removes genericArray values if present when empty, almost + * empty,not empty and when buffer is larger than initial size of + * 10 is surpassed. + */ + @Test + public void removeItemTest() { + + assertTrue(testArrayList.isEmpty()); + + //reassign values at back to maintain order of genericArray + for (int i = 0; i < genericArray.length; i++) { + testArrayList.addBack(genericArray[i]); + } + assertFalse(testArrayList.isEmpty()); + + for (int i = 0; i < genericArray.length; i++) { + E valueRemoved = testArrayList.get(i); + testArrayList.remove(genericArray[i]); + testArrayList.addFront((E)(Integer) ITERATIONS); + assertFalse(testArrayList.contains(valueRemoved)); + } + } + + /** + * Test get method returns for empty, almost empty + * and exception throw due to Index out of bounds + */ + @Test + public void getTest() + { + //test with empty array + assertTrue(testArrayList.isEmpty()); + + exception = assertThrows( + IndexOutOfBoundsException.class, () -> { + testArrayList.get(0); + }); + + //test with index greater than size of array + exception = assertThrows( + IndexOutOfBoundsException.class, () -> { + testArrayList.get(1); + }); + + //reassign values at back to maintain order of genericArray + for (int i = 0; i < genericArray.length; i++) { + testArrayList.addBack(genericArray[i]); + } + assertFalse(testArrayList.isEmpty()); + + //test the return values of get() + for (int i = 0; i < genericArray.length; i++) { + assertEquals(genericArray[i], testArrayList.get(i)); + } + } + + /** + * Test contains() for non-existent values, existing values, + * against empty list + */ + @Test + public void containsTest() + { + //Test if empty + assertTrue(testArrayList.isEmpty()); + assertFalse(testArrayList.contains(ITERATIONS)); + + //Test if value 1 exists + testArrayList.add(0, (E)(Integer) ITERATIONS); + assertTrue(testArrayList.contains(ITERATIONS)); + + //test if number does not exist + assertFalse(testArrayList.contains(80085)); + } + + /** + * Test isEmpty() against empty and non-empty ArrayList + */ + @Test + public void isEmptyTest() + { + //test against empty array + assertTrue(testArrayList.isEmpty()); + + //test against non-empty array + this.fillArray(); + assertFalse(testArrayList.isEmpty()); + } + + /** + * Test size() for no values, some values, + * against empty list + */ + @Test + public void sizeTest() + { + //test against empty ArrayList + assertTrue(testArrayList.isEmpty()); + assertEquals(0, testArrayList.size()); + + //test against non-empty ArrayList + for (int i = 0; i < ITERATIONS; i++) { + testArrayList.addBack((E)(Integer) i); + assertEquals(i + 1, testArrayList.size()); + } + } + + /* + * Helper method to fill the array in this class + */ + private void fillArray() + { + //reassign values + for (int i = 0; i < genericArray.length; i++) { + testArrayList.addFront(genericArray[i]); + assertEquals(genericArray[i], testArrayList.get(0)); + } + } +} + diff --git a/tests/LinkedIntListTest.java b/tests/LinkedIntListTest.java new file mode 100644 index 0000000..c390399 --- /dev/null +++ b/tests/LinkedIntListTest.java @@ -0,0 +1,343 @@ +import abstractDataTypes.LinkedList; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertFalse; + +/** + * Test Class for ArrayIntList + * @author tobygoetz + * @version 1.0 + */ +public class LinkedIntListTest { + private LinkedList testLinkedList = new LinkedList<>(); + private E[] genericArray = (E[]) new Object[]{ + "Test", 1, 'a', Math.random(), 1L, (byte) 0x00, 7, 8, 9, 10, "Eleven", "Twelve"}; + private static final int ITERATIONS = 15; + private Exception exception; + + protected void setException(Exception exception) { + this.exception = exception; + } + + /** + * Test adds Integer values to the front when empty, almost empty, + * not empty and when buffer is larger than intial size of 10 is + * surpassed. + */ + @Test + public void addFrontTest() { + assertEquals(0, testLinkedList.size()); + for (int i = 0; i < genericArray.length; i++) { + testLinkedList.addFront(genericArray[i]); + // Index 0 changes everytime addFront is called + assertEquals(genericArray[i], testLinkedList.get(0)); + } + } + + /** + * Test adds Integer values to the back when empty, almost empty, + * not empty and when buffer is larger than intial size of 10 is + * surpassed. + */ + @Test + public void addBackTest() { + assertEquals(0, testLinkedList.size()); + for (int i = 0; i < genericArray.length; i++) { + testLinkedList.addBack(genericArray[i]); + // Index 0 changes everytime addFront is called + assertEquals(genericArray[i], testLinkedList.get(testLinkedList.size() - 1)); + } + } + + /** + * Test adds Integer values at specific index when empty, almost + * empty,not empty and when buffer is larger than intial size of + * 10 is surpassed. + */ + @Test + public void addTest() + { + // Adds Index at i incrementing + for (int i = 0; i < ITERATIONS; i++) { + testLinkedList.add(i, (E) (Integer) i); + assertEquals(i, testLinkedList.get(i)); + } + + // Adds Index at i decrementing + for (int i = ITERATIONS; i >= 0; i--) { + testLinkedList.add(i, (E) (Integer) i); + assertEquals(i, testLinkedList.get(i)); + } + + + //IndexOutOfBoundsException is thrown if -1 is called + setException(assertThrows( + IndexOutOfBoundsException.class, + () -> testLinkedList.add(-1, (E)(Integer) ITERATIONS))); + + //IndexOutOfBoundsException is thrown if index larger than + // the amount of indices is called + setException(assertThrows( + IndexOutOfBoundsException.class, + () -> testLinkedList.add(testLinkedList.size() + 1, (E)(Integer)ITERATIONS))); + } + + /** + * Tests if values at specific index have been set when empty, + * almost empty,not empty and when buffer is larger than intial + * size of 10 is surpassed. Tests exceptions when attempting to + * set index that is out of range. + * */ + @Test + public void setTest() { + + assertTrue(testLinkedList.isEmpty()); + + //IndexOutOfBoundsException is thrown if -1 is called + exception = assertThrows( + IndexOutOfBoundsException.class, () -> { + testLinkedList.set(-1, (E) (Integer) ITERATIONS); + }); + + //IndexOutOfBoundsException is thrown if index larger than size of ArrayList is requested + exception = assertThrows( + IndexOutOfBoundsException.class, () -> { + testLinkedList.set(testLinkedList.size() + 1, (E) (Integer) ITERATIONS); + }); + + //reassign values + this.fillArray(); + assertFalse(testLinkedList.isEmpty()); + for (int i = 0; i < genericArray.length; i++) { + testLinkedList.set(i, (E)(Integer) ITERATIONS); + assertEquals(ITERATIONS, testLinkedList.get(i)); + } + } + + /** + * Test removes Integer values from the front of ArrayIntList when + * empty, almost empty and not empty + */ + @Test + public void removeFrontTest() { + assertEquals(0, testLinkedList.size()); + + //test with empty array + testLinkedList.removeFront(); + setException(assertThrows( + IndexOutOfBoundsException.class, () -> testLinkedList.get(0))); + assertTrue(testLinkedList.isEmpty()); + + //test with 1 value in array + testLinkedList.addFront((E)(Integer) ITERATIONS); + testLinkedList.removeFront(); + assertTrue(testLinkedList.isEmpty()); + + /* Check that next index value is now equal to index 0 + after the first index is removed */ + + this.fillArray(); + for (int i = 0; i < genericArray.length; i++) { + if (testLinkedList.size() > 1) { + E nextIndex = testLinkedList.get(1); + testLinkedList.removeFront(); + assertEquals(nextIndex, testLinkedList.get(0)); + } else { + testLinkedList.removeFront(); + assertTrue(testLinkedList.isEmpty()); + } + } + } + + /** + * Test removes Integer values from the front of ArrayIntList when + * empty, almost empty and not empty + */ + @Test + public void removeBackTest() + { + assertEquals(0, testLinkedList.size()); + assertNull(testLinkedList.removeBack()); + + //test with empty array + testLinkedList.removeBack(); + setException(assertThrows( + IndexOutOfBoundsException.class, () -> testLinkedList.get(0))); + assertTrue(testLinkedList.isEmpty()); + + //test with 1 value in array + testLinkedList.addFront((E)(Integer) ITERATIONS); + testLinkedList.removeBack(); + assertTrue(testLinkedList.isEmpty()); + + /* Check that next index value is now equal to index 0 + after the first index is removed */ + this.fillArray(); + this.fillArray(); + for (int i = 0; i < genericArray.length; i++) { + E removedValue = testLinkedList.get(testLinkedList.size() - 1); + assertEquals(removedValue, testLinkedList.removeBack()); + } + } + + /** + * Test removes genericArray values at specific index when empty, almost + * empty,not empty and when buffer is larger than intial size of + * 10 is surpassed. + */ + @Test + public void removeIndexTest() + { + //test with empty array + assertTrue(testLinkedList.isEmpty()); + exception = assertThrows( + IndexOutOfBoundsException.class, () -> { + testLinkedList.remove(0); + }); + + //test with index greater than size of array + exception = assertThrows( + IndexOutOfBoundsException.class, () -> { + testLinkedList.remove(1); + }); + + //reassign values + this.fillArray(); + assertFalse(testLinkedList.isEmpty()); + + //test with index greater than size of array + exception = assertThrows( + IndexOutOfBoundsException.class, () -> { + testLinkedList.remove(testLinkedList.size()); + }); + + for (int i = 0; i < genericArray.length - 1; i++) { + E valueAfterRemoved = testLinkedList.get(1); + testLinkedList.remove(0); + assertEquals(valueAfterRemoved, testLinkedList.get(0)); + } + } + + /** + * Test removes genericArray values if present when empty, almost + * empty,not empty and when buffer is larger than intial size of + * 10 is surpassed. + */ + @Test + public void removeItemTest() { + + assertTrue(testLinkedList.isEmpty()); + + //reassign values at back to maintain order of genericArray + for (int i = 0; i < genericArray.length; i++) { + testLinkedList.addBack(genericArray[i]); + } + assertFalse(testLinkedList.isEmpty()); + + for (int i = 0; i < genericArray.length; i++) { + E valueRemoved = testLinkedList.get(i); + testLinkedList.remove(genericArray[i]); + testLinkedList.addFront((E)(Integer) ITERATIONS); + assertFalse(testLinkedList.contains(valueRemoved)); + } + } + + /** + * Test get method returns for empty, almost empty + * and exception throw due to Index out of bounds + */ + @Test + public void getTest() { + assertEquals(0, testLinkedList.size()); + + //test with empty array + setException(assertThrows( + IndexOutOfBoundsException.class, () -> testLinkedList.get(0))); + assertTrue(testLinkedList.isEmpty()); + + //test with index greater than size of array + //test with empty array + setException(assertThrows( + IndexOutOfBoundsException.class, () -> testLinkedList.get(1))); + assertTrue(testLinkedList.isEmpty()); + + //reassign values at back to maintain order of genericArray + for (int i = 0; i < genericArray.length; i++) { + testLinkedList.addBack(genericArray[i]); + } + assertFalse(testLinkedList.isEmpty()); + + //test the return values of get() + for (int i = 0; i < genericArray.length; i++) { + assertEquals(genericArray[i], testLinkedList.get(i)); + } + } + + /** + * Test contains() for non-existent values, existing values, + * against empty list + */ + @Test + public void containsTest() + { + //Test if empty + assertEquals(0, testLinkedList.size()); + assertFalse(testLinkedList.contains((E)(Integer) ITERATIONS)); + + //Test if value 1 exists + testLinkedList.add(0, (E)(Integer) 1); + assertTrue(testLinkedList.contains((E)(Integer) 1)); + + //test if Iterations exists + this.fillArray(); + testLinkedList.set(0, (E)(Integer) ITERATIONS); + assertTrue(testLinkedList.contains((E)(Integer) ITERATIONS)); + + //test if number does not exist + assertFalse(testLinkedList.contains((E)(Integer) 80085)); + } + + /** + * Test isEmpty() for no values, some values, + * against empty list + */ + @Test + public void isEmptyTest() + { + //test against empty array + assertEquals(0, testLinkedList.size()); + + //test against non-empty array + this.fillArray(); + assertFalse(testLinkedList.isEmpty()); + } + + /** + * Test size() for no values, some values, + * against empty list + */ + @Test + public void sizeTest() { + //saftey check + assertEquals(0, testLinkedList.size()); + + //test against non-empty array + for (int i = 0; i < ITERATIONS; i++) { + testLinkedList.addBack((E)(Integer) i); + assertEquals(i + 1, testLinkedList.size()); + } + } + + /* + * Helper method to fill the array in this class + */ + private void fillArray() + { + //reassign values + for (int i = 0; i < genericArray.length; i++) { + testLinkedList.addFront(genericArray[i]); + assertEquals(genericArray[i], testLinkedList.get(0)); + } + } +}