diff --git a/src/ArrayIntList.java b/src/ArrayIntList.java new file mode 100644 index 0000000..5d68925 --- /dev/null +++ b/src/ArrayIntList.java @@ -0,0 +1,306 @@ +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class ArrayIntList implements IntList{ + //fields + private int size; + private int[] buffer; + + public ArrayIntList(){ + //initialize my fields + size = 0; + buffer = new int[10]; + } + + /** + * Inserts the specified value at the front of the list (at index 0). + * Shifts the value currently at the front of the list (if any) and any + * subsequent values to the right. + * + * @param value value to be inserted + */ + @Override + public void addFront(int value) { + if(size == buffer.length){ + resize(size * 2); + } + + //5,4,3,2,1 then save in [0] + for (int i = size; i >= 1 ; i--) { //count 5, 4, 3, 2, 1 + buffer[i] = buffer[i - 1]; //copy from 4, 3, 2, 1, 0 + } + + //put the value at the front of the array position [0] + buffer[0] = value; + size++; + } + + /** + * Inserts the specified value at the back of the list (at index size()-1). + * + * @param value value to be inserted + */ + @Override + public void addBack(int value) { + //if buffer is full, create a larger buffer + if(size == buffer.length){ + resize(size * 2); + } + + buffer[size] = value; + size++; + } + + /** + * Inserts the specified value at the specified position in this list. + * Shifts the value currently at that position (if any) and any subsequent + * values to the right. + * + * @param index index at which the specified value is to be inserted + * @param value value to be inserted + * @throws IndexOutOfBoundsException if the index is out of range + */ + @Override + public void add(int index, int value) { + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException("Invalid Index"); + } + + if(size == buffer.length){ + resize(size * 2); + } + + //shift elements to the right + for (int i = size; i > index; i--) { + buffer[i] = buffer[i - 1]; + } + + //add the value at the specified index + buffer[index] = value; + size++; + + } + + /** + * Removes the value located at the front of the list + * (at index 0), if it is present. + * Shifts any subsequent values to the left. + */ + @Override + public void removeFront() { + if(!isEmpty()){ + for (int i = 0; i <= size - 2; i++) { + buffer[i] = buffer[i + 1]; + } + + //clear the last value to avoid duplicates + buffer[size - 1] = 0; + + size--; + } + + } + + /** + * Removes the value located at the back of the list + * (at index size()-1), if it is present. + */ + @Override + public void removeBack() { + if(!isEmpty()){ + buffer[size - 1] = 0; + size--; + } + } + + /** + * Removes the value at the specified position in this list. + * Shifts any subsequent values to the left. Returns the value + * that was removed from the list. + * + * @param index the index of the value to be removed + * @return the value previously at the specified position + * @throws IndexOutOfBoundsException if the index is out of range + */ + @Override + public int remove(int index) { + //check index to see if it is valid + if(index >= size || index < 0){ + throw new IndexOutOfBoundsException("Invalid index"); + } + + //save a copy of the value to removed, so we can return it later + int valueToRemove = buffer[index]; + + //shift values to the left + for (int i = index; i < size - 1; i++) { + buffer[i] = buffer[i+1]; + } + + //empty the last/redundant index + buffer[size - 1] = 0; + + //decrement size + size--; + + return valueToRemove; + } + + /** + * Returns the value at the specified position in the list. + * + * @param index index of the value to return + * @return the value at the specified position in this list + * @throws IndexOutOfBoundsException if the index is out of range + */ + @Override + public int get(int index) { + if (index < 0 || index > size){ + throw new IndexOutOfBoundsException("Invalid Index"); + } + System.out.println(buffer[index]); + return buffer[index]; + } + + /** + * Returns true if this list contains the specified value. + * + * @param value value whose presence in this list is to be searched for + * @return true if this list contains the specified value + */ + @Override + public boolean contains(int value) { + for (int i = 0; i < buffer.length; i++) { + if (buffer[i] == value){ + return true; + } + } + + return false; + } + + /** + * Returns the index of the first occurrence of the specified value + * in this list, or -1 if this list does not contain the value. + * + * @param value value to search for + * @return the index of the first occurrence of the specified value in this list + * or -1 if this list does not contain the value + */ + @Override + public int indexOf(int value) { + for (int i = 0; i <= size; i++) { + if (value == buffer[i]){ + return i; + }else{ + i++; + } + } + return -1; + } + + /** + * @return true if this list contains no values + */ + @Override + public boolean isEmpty() { + if (size == 0){ + return true; + } + return false; + } + + /** + * @return the number of values in this list + */ + @Override + public int size() { + return size; + } + + /** + * Removes all the values from this list. + * The list will be empty after this call returns. + */ + @Override + public void clear() { +// //go through each index of the array and set it to 0 +// for (int i = 0; i < size; i++) { +// buffer[i] = 0; +// i++; +// } + + //create a new array and overwrite the old + buffer = new int[10]; + size = 0; + } + + private void resize(int newSize){ + //create new space, separate form old space (buffer) + int[] newBuffer = new int[newSize]; + + //copy everything over from buffer into newBuffer + for (int i = 0; i < buffer.length; i++) { + newBuffer[i] = buffer[i]; + } + + //set the new space into buffer + buffer = newBuffer; + + //the old buffer space is no longer "pointed to" and will + //eventually be cleaned up by the garbage collector + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @Override + public Iterator iterator() { + return new IntListIterator(); + } + + + //create a private helper Iterator class + private class IntListIterator implements Iterator{ + //private fields + private int i; + + //constructor + private IntListIterator(){ + i = 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 i < 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 Integer next() { + if(i >= size){ + throw new NoSuchElementException("i is now out of bounds"); + } + int currentValue = buffer[i]; + i++; + return currentValue; + } + } + + //iterators are what enables main/ client to use a for-each loop + //on my IntList +} diff --git a/src/DoublyLinkedIntList.java b/src/DoublyLinkedIntList.java new file mode 100644 index 0000000..edf6883 --- /dev/null +++ b/src/DoublyLinkedIntList.java @@ -0,0 +1,316 @@ +import java.util.Iterator; + +public class DoublyLinkedIntList implements IntList{ + //private fields + private class Node{ + int data; + Node next; // address of the node "after" this one in line + Node prev; //address of the node "before" this one in line + + public Node(){ + next = null; + prev = null; + } + } + + private Node pre; + private Node post; + private int size; + + //constructor + public DoublyLinkedIntList(){ + //an empty list has 2 sentinel (dummy) nodes that serve as bookends + pre = new Node(); + post = new Node(); + pre.next = post; //sentinel node before first data node + post.prev = pre; //sentinel node after last data node + size = 0; + } + + public void printList(){ + //start at the first node, after first sentinel + Node current = pre.next; + + //go through the list until the last sentinel node + while (current != post){ + System.out.print(current.data + ", "); + current = current.next; + } + } + + /** + * Prepends (inserts) the specified value at the front of the list (at index 0). + * Shifts the value currently at the front of the list (if any) and any + * subsequent values to the right. + * + * @param value value to be inserted + */ + @Override + public void addFront(int value) { + Node newNode = new Node(); + newNode.data = value; + + //adjust references to point to new node + newNode.prev = pre; + newNode.next = pre.next; + + //update first and end sentinels + pre.next.prev = newNode; + pre.next = newNode; + + size++; + } + + /** + * Appends (inserts) the specified value at the back of the list (at index size()-1). + * + * @param value value to be inserted + */ + @Override + public void addBack(int value) { + Node lastNode = post.prev; + + //set up my new node and fill it out (data, prev, next) + Node newNode = new Node(); + newNode.data = value; + newNode.next = post; + newNode.prev = lastNode; + + //go to the end of the list's sentinel, and update it's prev + post.prev = newNode; + + //go to the node before the new on, and update it's next + lastNode.next = newNode; + size++; + } + + /** + * Inserts the specified value at the specified position in this list. + * Shifts the value currently at that position (if any) and any subsequent + * values to the right. + * + * @param index index at which the specified value is to be inserted + * @param value value to be inserted + * @throws IndexOutOfBoundsException if the index is out of range + */ + @Override + public void add(int index, int value) { + if (index < 0 || index > size){ + throw new IndexOutOfBoundsException("Invalid index"); + } + + Node newNode = new Node(); + newNode.data = value; + + Node current = pre.next; + + for (int i = 0; i < index; i++) { + current = current.next; + } + + //update references to include new node + newNode.next = current.prev; + newNode.prev = current; + + //update neighboring nodes' reference + current.prev.next = newNode; + current.prev = newNode; + + size++; + } + + /** + * Removes the value located at the front of the list + * (at index 0), if it is present. + * Shifts any subsequent values to the left. + */ + @Override + public void removeFront() { + if (size > 0){ + //the node to be removed + Node removedNode = pre.next; + + //update references + pre.next = removedNode.next; //set pre to the node after the removed one + removedNode.next.prev = pre; //new 'first' node connects back to sentinel pre + size--; + } + + } + + /** + * Removes the value located at the back of the list + * (at index size()-1), if it is present. + */ + @Override + public void removeBack() { + if(size > 0){ + //set up temporary variable + Node removedNode = post.prev; + + //go to the node before the last, and point to post node + removedNode.prev.next = post; + + //point the post node to the node before the removedNode + post.prev = removedNode.prev; + + //optional to clean up + removedNode.next = null; + removedNode.prev = null; + + size--; + } + } + + /** + * Removes the value at the specified position in this list. + * Shifts any subsequent values to the left. Returns the value + * that was removed from the list. + * + * @param index the index of the value to be removed + * @return the value previously at the specified position + * @throws IndexOutOfBoundsException if the index is out of range + */ + @Override + public int remove(int index) { + if (index < 0 || index > size){ + throw new IndexOutOfBoundsException("Invalid index"); + } + + Node removedNode = pre; + + //removing first node + if (index == 0){ + removeFront(); + } + //removing last node + else if (index == size-1){ + removeBack(); + } + //removing middle node + else{ + Node current = pre.next; + for (int i = 0; i < index; i++) { + current = current.next; + } + removedNode = current; + current.prev.next = current.next; + current.next.prev = current.prev; + } + + size--; + return removedNode.data; + } + + /** + * Returns the value at the specified position in the list. + * + * @param index index of the value to return + * @return the value at the specified position in this list + * @throws IndexOutOfBoundsException if the index is out of range + */ + @Override + public int get(int index) { + if (index < 0 || index > size){ + throw new IndexOutOfBoundsException("Invalid index"); + } + + Node current = pre.next; + + for (int i = 0; i < index; i++) { + current = current.next; + } + + //return the data at the index + return current.data; + } + + /** + * Returns true if this list contains the specified value. + * + * @param value value whose presence in this list is to be searched for + * @return true if this list contains the specified value + */ + @Override + public boolean contains(int value) { + //if list is empty + if(pre.next == post){ + return false; + } + //new node to traverse list + Node current = pre.next; + + while (current.next != post){ + if (current.data == value){ + return true; + } + current = current.next; + } + + return false; + } + + /** + * Returns the index of the first occurrence of the specified value + * in this list, or -1 if this list does not contain the value. + * + * @param value value to search for + * @return the index of the first occurrence of the specified value in this list + * or -1 if this list does not contain the value + */ + @Override + public int indexOf(int value) { + Node current = pre.next; + int index = 0; + + //go to the end of the list + while(current != post){ + if (current.data == value){ + return index; + }else{ + index++; + current = current.next; + } + } + return -1; + } + + /** + * @return true if this list contains no values + */ + @Override + public boolean isEmpty() { + if (pre.next == post){ + return true; + } + return false; + } + + /** + * @return the number of values in this list + */ + @Override + public int size() { + return size; + } + + /** + * Removes all the values from this list. + * The list will be empty after this call returns. + */ + @Override + public void clear() { + pre.next = post; + size = 0; + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @Override + public Iterator iterator() { + return null; + } +} diff --git a/src/LinkedIntList.java b/src/LinkedIntList.java new file mode 100644 index 0000000..4eea1ef --- /dev/null +++ b/src/LinkedIntList.java @@ -0,0 +1,351 @@ +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class LinkedIntList implements IntList{ + + // define what a node is + private class Node { + int data; + Node next; + } + + // set up the head + private Node head; + + //set up the size field + private int size; + + // add a constructor to initialize the fields + LinkedIntList(){ + head = null; + size = 0; + } + + /** + * Prints out the values of each node in the list + */ + public void printList() { + Node current = head; + while (current != null) { + System.out.print(current.data + ", "); + current = current.next; + } + } + + /** + * Prepends (inserts) the specified value at the front of the list (at index 0). + * Shifts the value currently at the front of the list (if any) and any + * subsequent values to the right. + * + * @param value value to be inserted + */ + @Override + public void addFront(int value) { + Node newOne = new Node(); + newOne.data = value; + 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++; + } + + /** + * Appends (inserts) the specified value at the back of the list (at index size()-1). + * + * @param value value to be inserted + */ + @Override + public void addBack(int value) { + //create a new a node with the specified value + Node newNode = new Node(); + newNode.data = value; + + Node current = head; + + //go to end of list + while (current.next != null){ + current = current.next; + } + + //add it to the back + current.next = newNode; + + size++; + + } + + /** + * Inserts the specified value at the specified position in this list. + * Shifts the value currently at that position (if any) and any subsequent + * values to the right. + * + * @param index index at which the specified value is to be inserted + * @param value value to be inserted + * @throws IndexOutOfBoundsException if the index is out of range + */ + @Override + public void add(int index, int value) { + if (index < 0 || index > size){ + throw new IndexOutOfBoundsException("Invalid Index"); + } + + //create a new node with the specified data + Node newNode = new Node(); + newNode.data = value; + + //temporary node to traverse list + Node current = head; + int currIndex = 0; + + while (currIndex != index - 1){ + current = current.next; + currIndex++; + } + + newNode.next = current.next; + current.next = newNode; + + size++; + } + + /** + * Removes the value located at the front of the list + * (at index 0), if it is present. + */ + @Override + public void removeFront() { + if (size > 0){ + head = head.next; + } + + size--; + } + + /** + * Removes the value located at the back of the list + * (at index size()-1), if it is present. + */ + @Override + public void removeBack() { + Node current = head; + int currIndex = 1; + + while (currIndex != size()- 1){ + current = current.next; + currIndex++; + } + + current.next = null; + + size--; + } + + /** + * Removes the value at the specified position in this list. + * Shifts any subsequent values to the left. Returns the value + * that was removed from the list. + * + * @param index the index of the value to be removed + * @return the value previously at the specified position + * @throws IndexOutOfBoundsException if the index is out of range + */ + @Override + public int remove(int index) { + if (index < 0 || index > size){ + throw new IndexOutOfBoundsException("Invalid index"); + } + + Node current = head; + Node prev = null; + int currIndex = 0; + + while(currIndex != index){ + prev = current; + current = current.next; + currIndex++; + } + + //remove node + if (prev != null){ + prev.next = current.next; + }else{ //if removal of head node + head = current.next; + } + + size--; + return current.data; + } + + /** + * Returns the value at the specified position in the list. + * + * @param index index of the value to return + * @return the value at the specified position in this list + * @throws IndexOutOfBoundsException if the index is out of range + */ + @Override + public int get(int index) { + if (index < 0 || index > size){ + throw new IndexOutOfBoundsException("Invalid index"); + } + + Node current = head; + int currIndex = 0; + + while(currIndex != index){ + current = current.next; + currIndex++; + + //don't go past end of list + if (current == null){ + throw new IndexOutOfBoundsException("Invalid index"); + } + } + + return current.data; + } + + /** + * Returns true if this list contains the specified value. + * + * @param value value whose presence in this list is to be searched for + * @return true if this list contains the specified value + */ + @Override + public boolean contains(int value) { + + Node current = head; + + while(current != null){ + if(current.data == value){ + return true; + }else{ + current = current.next; + } + + } + return false; + } + + /** + * Returns the index of the first occurrence of the specified value + * in this list, or -1 if this list does not contain the value. + * + * @param value value to search for + * @return the index of the first occurrence of the specified value in this list + * or -1 if this list does not contain the value + */ + @Override + public int indexOf(int value) { + Node current = new Node(); + current = head; + int currIndex = 0; + + while (current != null){ + if (current.data == value){ + return currIndex; + } + else{ + current = current.next; + currIndex++; + } + } + return -1; + } + + /** + * @return true if this list contains no values + */ + @Override + public boolean isEmpty() { + if(head.next == null){ + return true; + } + return false; + } + + /** + * @return the number of values in this list + */ + @Override + public int size() { + return size; + } + + /** + * Removes all the values from this list. + * The list will be empty after this call returns. + */ + @Override + public void clear() { + Node current = head; + while (current != null){ + Node next = current.next; + current = next; + } + head = null; + size = 0; + } + + /** + * Returns an iterator over elements of type {@code T}. + * + * @return an Iterator. + */ + @Override + public Iterator iterator() { + SinglyLinkedIterator theIterator = new SinglyLinkedIterator(); + return theIterator; + } + + // helper class/type that defines how the iterator works + private class SinglyLinkedIterator implements Iterator { + private Node current; + + public SinglyLinkedIterator() { + 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.) + * + * @return {@code true} if the iteration has more elements + */ + @Override + public boolean hasNext() { + if(current != null) + { + return true; + } + return false; + + //return current != null; + } + + /** + * 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 Integer next() { + if(current == null){ + throw new NoSuchElementException("There is no next one to go to"); + } + int item = current.data; + current = current.next; + return item; + } + } +} \ No newline at end of file diff --git a/src/Main.java b/src/Main.java index 930198c..cd9c4bb 100644 --- a/src/Main.java +++ b/src/Main.java @@ -1,15 +1,197 @@ -//TIP To Run code, press or -// click the icon in the gutter. +import java.util.Iterator; + 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.printf("Hello and welcome!"); + IntList firstList; + + IntList thirdList = new ArrayIntList(); + thirdList.addFront(15); + thirdList.addFront(12); + thirdList.addFront(8); + + //where an iterator gets used: + for (int value: thirdList) { + System.out.println(value); + } + + //alternate way to use an iterator + Iterator itr = thirdList.iterator(); + while (itr.hasNext()){ + int value = itr.next(); + System.out.println(value); + } + +// arrayIntListTest(); +// singlyLinkedIntListTest(); + doublyLinkedIntListTest(); + + } + + public static void arrayIntListTest(){ + ArrayIntList arrayTest = new ArrayIntList(); + System.out.println("Testing ArrayIntList"); + + System.out.println("\naddFront()"); + arrayTest.addFront(1); + arrayTest.addFront(2); + arrayTest.addFront(3); + arrayTest.addFront(4); + arrayTest.addFront(5); + for (int value : arrayTest){ + System.out.print(value + ", "); + //should be: 5,4,3,2,1 + } + + System.out.println("\naddBack()"); + arrayTest.addBack(20); + for (int value : arrayTest){ + System.out.print(value + ", "); + //should be: 5,4,3,2,1,20 + } - for (int i = 1; i <= 5; i++) { - //TIP Press to start debugging your code. We have set one breakpoint - // for you, but you can always add more by pressing . - System.out.println("i = " + i); + System.out.println("\nadd()"); + arrayTest.add(1,13); + for (int value : arrayTest){ + System.out.print(value + ", "); + //should be: 5,13,4,3,2,1,20 } + + System.out.println("\nremoveFront()"); + arrayTest.removeFront(); + for (int value : arrayTest){ + System.out.print(value + ", "); + //should be: 13,4,2,1,20 + } + + System.out.println("\nremoveBack()"); + arrayTest.removeBack(); + for (int value : arrayTest){ + System.out.print(value + ", "); + //should be: 13,4,3,2,1 + } + + System.out.println("\nremove()"); + arrayTest.remove(1); + for (int value : arrayTest){ + System.out.print(value + ", "); //should be: 13,3,2,1 + } + + System.out.println("\nget()"); + arrayTest.get(1); //should be: 3 + + System.out.println("contains()"); + System.out.println(arrayTest.contains(1)); //true + + System.out.println("indexOf()"); + System.out.println(arrayTest.indexOf(2)); //2 + + System.out.println("isEmpty()"); + System.out.println(arrayTest.isEmpty()); //false + + System.out.println("size()"); + System.out.println(arrayTest.size()); //4 + + System.out.println("clear()"); + arrayTest.clear(); + for (int value : arrayTest){ + System.out.print(value + ", "); //empty + } + + } + + public static void singlyLinkedIntListTest(){ + LinkedIntList linkedListTest = new LinkedIntList(); + + linkedListTest.addFront(1); + linkedListTest.addFront(2); + linkedListTest.addFront(3); + linkedListTest.addFront(4); + System.out.println("Base linked list: "); + linkedListTest.printList(); + + System.out.println("\naddBacK()"); + linkedListTest.addBack(13); + linkedListTest.printList(); //4,3,2,1,13 + + System.out.println("\nadd()"); + linkedListTest.add(3,10); + linkedListTest.printList(); //4,3,2,10,1,13 + + System.out.println("\nremoveFront()"); + linkedListTest.removeFront(); + linkedListTest.printList(); // 3,2,10,1,13 + + System.out.println("\nremoveBack()"); + linkedListTest.removeBack(); + linkedListTest.printList(); // 3,2,10,1 + + System.out.println("\nremove()"); + linkedListTest.remove(1); + linkedListTest.printList(); // 3,10,1 + + System.out.println("\nget()"); + System.out.println(linkedListTest.get(1)); // 10 + + System.out.println("\ncontains()"); + System.out.println(linkedListTest.contains(10)); //true + + System.out.println("\nindexOf()"); + System.out.println(linkedListTest.indexOf(1)); //2 + + System.out.println("\nisEmpty()"); + System.out.println(linkedListTest.isEmpty()); //false + + System.out.println("\nsize()"); + System.out.println(linkedListTest.size()); //3 + + System.out.println("\nclear"); + linkedListTest.clear(); + linkedListTest.printList(); + + } + + public static void doublyLinkedIntListTest(){ + DoublyLinkedIntList test = new DoublyLinkedIntList(); + test.addFront(1); + test.addFront(2); + test.addFront(3); + test.addFront(4); + test.addFront(5); + test.addFront(6); + test.addFront(7); + test.addBack(8); + System.out.println("Base doubly linked list"); //7, 6, 5, 4, 3, 2, 1, 8 + test.printList(); + + System.out.println("\nindexOf()"); + System.out.println(test.indexOf(6)); //1 + + System.out.println("\nget()"); + System.out.println(test.get(0)); //7 + + System.out.println("\ncontains()"); + System.out.println(test.contains(3)); //true + + System.out.println("\nremove()"); + test.remove(4); + test.printList(); //7, 6, 5, 4, 2, 1, 8 + + System.out.println("\nremoveFront"); + test.removeFront(); + test.printList(); //6, 5, 4, 2, 1, 8 + + System.out.println("\nremoveBack"); + test.removeBack(); + test.printList(); //6, 5, 4, 2, 1 + + System.out.println("\nsize()"); + System.out.println(test.size()); //5 + + System.out.println("\nclear()"); + test.clear(); + + System.out.println("\nisEmpty()"); + System.out.println(test.isEmpty()); //true + } } \ No newline at end of file