diff --git a/a1/src/edu/wmich/cs3310/a1/Controller.java b/a1/src/edu/wmich/cs3310/a1/Controller.java new file mode 100644 index 0000000000000000000000000000000000000000..778a40134d173ecee81fb0380271679713615b6b --- /dev/null +++ b/a1/src/edu/wmich/cs3310/a1/Controller.java @@ -0,0 +1,30 @@ +package edu.wmich.cs3310.a1; + + +public class Controller { + + //region Variables + + + + //endregion Variables + + + + //region Controllers + + public Controller() { + + } + + //endregion Controllers + + + + //region Methods + + + + //endregion Methods + +} diff --git a/a1/src/edu/wmich/cs3310/a1/DataStructures/CharList.java b/a1/src/edu/wmich/cs3310/a1/DataStructures/CharList.java new file mode 100644 index 0000000000000000000000000000000000000000..65f20e5ee4fe859eb0e8556ae10141ca2690a5af --- /dev/null +++ b/a1/src/edu/wmich/cs3310/a1/DataStructures/CharList.java @@ -0,0 +1,221 @@ +package edu.wmich.cs3310.a1.DataStructures; + + +/** + * Doubly linked list using CharNode for nodes. + */ +public class CharList { + + //region Variables + + private CharNode firstNode; + private CharNode lastNode; + + //endregion Variables + + + + //region Controllers + + public CharList() { + + } + + //endregion Controllers + + + + //region Properties + + /** + * Getter for first node in list. + * @return First node of list. + */ + public CharNode getFirstNode() { + return firstNode; + } + + + /** + * Getter for last node in list. + * @return Last node of list. + */ + public CharNode getLastNode() { + return lastNode; + } + + + //endregion Properties + + + + //region Methods + + /** + * Retrieves node from indicated index. + * @param index Index of node to retrieve. + * @return Retrieved node or null if failure. + */ + public CharNode Retrieve(int index) { + CharNode tempNode; + int tempIndex = 0; + + // Check that index is valid. + if (index < 0) { + return null; + } else { + tempNode = firstNode; + } + + // Loop until index is found or all nodes are searched. + while (tempIndex < index && tempNode != null) { + tempNode = tempNode.nextNode(); + tempIndex++; + } + + return tempNode; + } + + + /** + * Insert new new node at given index in linked list. + * @param character Character for node to hold. + * @param index Index of new node. + * @return True on success or false on failure. + */ + public Boolean Insert(char character, int index) { + CharNode newNode = new CharNode(); + CharNode tempNode; + CharNode nextPlaceholder; + CharNode prevPlaceholder; + + // Get node directly before desired index. + tempNode = Retrieve((index - 1)); + + // Check that returned node is valid. + if (tempNode == null && index != 0) { + return false; + } + + newNode.myData(character); + + // Check if list is empty. + if (firstNode == null) { + firstNode = newNode; + lastNode = newNode; + } else { + nextPlaceholder = Retrieve(index); + prevPlaceholder = tempNode; + + // Set nextNode properties. + newNode.nextNode(nextPlaceholder); + if (nextPlaceholder != null) { + nextPlaceholder.prevNode(newNode); + } else { + lastNode = newNode; + } + + // Set prevNode properties. + newNode.prevNode(prevPlaceholder); + if (prevPlaceholder != null) { + prevPlaceholder.nextNode(newNode); + } else { + firstNode = newNode; + } + } + return true; + } + + + /** + * Delete node with given index. + * @param index Index of node to delete. + * @return Deleted node or null on failure. + */ + public CharNode Delete(int index) { + CharNode foundNode; + CharNode nextPlaceholder; + CharNode prevPlaceholder; + + foundNode = Retrieve(index); + + // Check that returned node is valid. + if (foundNode == null) { + return null; + } + + nextPlaceholder = foundNode.nextNode(); + prevPlaceholder = foundNode.prevNode(); + + // Handling for next property. + if (prevPlaceholder != null) { + prevPlaceholder.nextNode(nextPlaceholder); + } else { + firstNode = nextPlaceholder; + } + + // Handling for prev property. + if (nextPlaceholder != null) { + nextPlaceholder.prevNode(prevPlaceholder); + } else { + lastNode = prevPlaceholder; + } + + foundNode.nextNode(null); + foundNode.prevNode(null); + return foundNode; + } + + + /** + * Delete node with given character. + * @param character Character to delete. + * @return Deleted node or null on failure. + */ + public CharNode Delete(char character) { + CharNode tempNode = firstNode; + CharNode foundNode = null; + CharNode nextPlaceholder; + CharNode prevPlaceholder; + + // Continue until character is found or all nodes are searched. + while (tempNode != null) { + + if (tempNode.myData() == character) { + foundNode = tempNode; + tempNode = null; + } else { + tempNode = tempNode.nextNode(); + } + } + + // Check for match. + if (foundNode == null) { + return null; + } else { + nextPlaceholder = foundNode.nextNode(); + prevPlaceholder = foundNode.prevNode(); + + // Handling for next property. + if (prevPlaceholder != null) { + prevPlaceholder.nextNode(nextPlaceholder); + } else { + firstNode = nextPlaceholder; + } + + // Handling for prev property. + if (nextPlaceholder != null) { + nextPlaceholder.prevNode(prevPlaceholder); + } else { + lastNode = prevPlaceholder; + } + + foundNode.nextNode(null); + foundNode.prevNode(null); + return foundNode; + } + } + + //endregion Methods + +} diff --git a/a1/src/edu/wmich/cs3310/a1/DataStructures/CharNode.java b/a1/src/edu/wmich/cs3310/a1/DataStructures/CharNode.java new file mode 100644 index 0000000000000000000000000000000000000000..5a8c634d6c98480546842b858f3f71d26d6b8bd3 --- /dev/null +++ b/a1/src/edu/wmich/cs3310/a1/DataStructures/CharNode.java @@ -0,0 +1,77 @@ +package edu.wmich.cs3310.a1.DataStructures; + + +/** + * Node class for linked list. + */ +public class CharNode { + + //region Variables + + private char data; + private CharNode nextNode; + private CharNode prevNode; + + //endregion Variables + + + + //region Properties + + /** + * Getter for node char. + * @return The char that node holds. + */ + public char myData() { + return data; + } + + + + /** + * Setter for node char. + * @param data The char for node to hold. + */ + public void myData(char data) { + this.data = data; + } + + + /** + * Getter for next node. + * @return The next node. + */ + public CharNode nextNode() { + return nextNode; + } + + + /** + * Setter for next node. + * @param nextNode The next node to hold. + */ + public void nextNode(CharNode nextNode) { + this.nextNode = nextNode; + } + + + /** + * Getter for previous node. + * @return The previous node. + */ + public CharNode prevNode() { + return prevNode; + } + + + /** + * Setter for previous node. + * @param prevNode The previous node. + */ + public void prevNode(CharNode prevNode) { + this.prevNode = prevNode; + } + + //endregion Properties + +} diff --git a/a1/src/edu/wmich/cs3310/a1/DataStructures/CharQueue.java b/a1/src/edu/wmich/cs3310/a1/DataStructures/CharQueue.java new file mode 100644 index 0000000000000000000000000000000000000000..94c0ab25b123fd4a541850a9b68b123358bd8b3b --- /dev/null +++ b/a1/src/edu/wmich/cs3310/a1/DataStructures/CharQueue.java @@ -0,0 +1,41 @@ +package edu.wmich.cs3310.a1.DataStructures; + + +/** + * Queue implementation of linked list. + */ +public class CharQueue { + + //region Variables + + + + //endregion Variables + + + + //region Controllers + + public CharQueue() { + + } + + //endregion Controllers + + + + //region Properties + + + + //endregion Properties + + + + //region Methods + + + + //endregion Methods + +} diff --git a/a1/src/edu/wmich/cs3310/a1/DataStructures/CharStack.java b/a1/src/edu/wmich/cs3310/a1/DataStructures/CharStack.java new file mode 100644 index 0000000000000000000000000000000000000000..3d728a31330bc909c1a4667106c2ad883a952960 --- /dev/null +++ b/a1/src/edu/wmich/cs3310/a1/DataStructures/CharStack.java @@ -0,0 +1,49 @@ +package edu.wmich.cs3310.a1.DataStructures; + + +/** + * Stack implementation of linked list. + */ +public class CharStack { + + //region Variables + + + + //endregion Variables + + + + //region Controllers + + public CharStack() { + + } + + //endregion Controllers + + + + //region Properties + + + + //endregion Properties + + + + //region Methods + + public void Push() { + + } + + + + //public CharNode Pop() { + + //} + + //endregion Methods + +} diff --git a/a1/src/edu/wmich/cs3310/a1/Main.java b/a1/src/edu/wmich/cs3310/a1/Main.java new file mode 100644 index 0000000000000000000000000000000000000000..f55608c39f830289276310e84353b6c8eb5c1c38 --- /dev/null +++ b/a1/src/edu/wmich/cs3310/a1/Main.java @@ -0,0 +1,9 @@ +package edu.wmich.cs3310.a1; + + +public class Main { + public static void main(String[] args) { + // Create class to run program from non-static source. + Controller controller = new Controller(); + } +} diff --git a/a1/tests/CharListTests.java b/a1/tests/CharListTests.java new file mode 100644 index 0000000000000000000000000000000000000000..6dff47d738f32dfba8157f394802b102a38b091c --- /dev/null +++ b/a1/tests/CharListTests.java @@ -0,0 +1,250 @@ + +import org.junit.Before; +import org.junit.Assert; +import org.junit.Test; + +import edu.wmich.cs3310.a1.DataStructures.CharList; +import edu.wmich.cs3310.a1.DataStructures.CharNode; + + +/** + * Tests for CharList class. + */ +public class CharListTests { + + //region Variables + + CharNode aNode; + CharList aList; + + //endregion Variables + + + + //region Tests + + @Before + public void setUp() { + aNode = new CharNode(); + aList = new CharList(); + } + + + @Test + public void Test_Insert_Success_OnlyFirst() { + // Test inserting with 0 nodes. + Assert.assertNull(aList.getFirstNode()); + Assert.assertNull(aList.getLastNode()); + + // Test inserting with 1 node. + Assert.assertTrue(aList.Insert('a', 0)); + Assert.assertEquals('a', aList.getFirstNode().myData()); + Assert.assertEquals(aList.getFirstNode(), aList.getLastNode()); + + // Test inserting with 2 nodes. + Assert.assertTrue(aList.Insert('b', 0)); + Assert.assertEquals('b', aList.getFirstNode().myData()); + Assert.assertEquals('a', aList.getLastNode().myData()); + Assert.assertEquals(aList.getFirstNode(), aList.getLastNode().prevNode()); + Assert.assertEquals(aList.getLastNode(), aList.getFirstNode().nextNode()); + + // Test inserting with 3 nodes. + Assert.assertTrue(aList.Insert('c', 0)); + Assert.assertEquals('c', aList.getFirstNode().myData()); + Assert.assertEquals('b', aList.getFirstNode().nextNode().myData()); + Assert.assertEquals(aList.getFirstNode(), aList.getLastNode().prevNode().prevNode()); + Assert.assertEquals(aList.getFirstNode().nextNode(), aList.getLastNode().prevNode()); + Assert.assertEquals(aList.getFirstNode().nextNode().nextNode(), aList.getLastNode()); + } + + + @Test + public void Test_Insert_Success_OnlyLast() { + // Test inserting with 0 nodes. + Assert.assertNull(aList.getFirstNode()); + Assert.assertNull(aList.getLastNode()); + + // Test inserting with 1 node. + Assert.assertTrue(aList.Insert('a', 0)); + Assert.assertEquals('a', aList.getFirstNode().myData()); + Assert.assertEquals(aList.getFirstNode(), aList.getLastNode()); + + // Test inserting with 2 nodes. + Assert.assertTrue(aList.Insert('b', 1)); + Assert.assertEquals('a', aList.getFirstNode().myData()); + Assert.assertEquals('b', aList.getLastNode().myData()); + Assert.assertEquals(aList.getFirstNode(), aList.getLastNode().prevNode()); + Assert.assertEquals(aList.getLastNode(), aList.getFirstNode().nextNode()); + + // Test inserting with 3 nodes. + Assert.assertTrue(aList.Insert('c', 2)); + Assert.assertEquals('c', aList.getLastNode().myData()); + Assert.assertEquals('b', aList.getLastNode().prevNode().myData()); + Assert.assertEquals(aList.getFirstNode(), aList.getLastNode().prevNode().prevNode()); + Assert.assertEquals(aList.getFirstNode().nextNode(), aList.getLastNode().prevNode()); + Assert.assertEquals(aList.getFirstNode().nextNode().nextNode(), aList.getLastNode()); + } + + + @Test + public void Test_Insert_Fail_BadIndex() { + Assert.assertNull(aList.getFirstNode()); + Assert.assertNull(aList.getLastNode()); + Assert.assertFalse(aList.Insert('a', -1)); + Assert.assertFalse(aList.Insert('a', 1)); + + Assert.assertTrue(aList.Insert('a', 0)); + Assert.assertFalse(aList.Insert('b', -1)); + Assert.assertFalse(aList.Insert('b', 2)); + + Assert.assertTrue(aList.Insert('b', 1)); + Assert.assertFalse(aList.Insert('c', -1)); + Assert.assertFalse(aList.Insert('c', 3)); + } + + + @Test + public void Test_Delete_Index_Success_OnlyFirst() { + Assert.assertTrue(aList.Insert('a', 0)); + Assert.assertTrue(aList.Insert('b', 1)); + Assert.assertTrue(aList.Insert('c', 2)); + + // Test deleting with 3 nodes. + aNode = aList.Delete(0); + Assert.assertNotNull(aNode); + Assert.assertEquals('a', aNode.myData()); + Assert.assertNull(aNode.nextNode()); + Assert.assertNull(aNode.prevNode()); + Assert.assertEquals('b', aList.getFirstNode().myData()); + Assert.assertEquals('c', aList.getLastNode().myData()); + Assert.assertEquals(aList.getFirstNode(), aList.getLastNode().prevNode()); + Assert.assertEquals(aList.getLastNode(), aList.getFirstNode().nextNode()); + + // Test deleting with 2 nodes. + aNode = aList.Delete(0); + Assert.assertNotNull(aNode); + Assert.assertEquals('b', aNode.myData()); + Assert.assertNull(aNode.nextNode()); + Assert.assertNull(aNode.prevNode()); + Assert.assertEquals('c', aList.getFirstNode().myData()); + Assert.assertEquals(aList.getFirstNode(), aList.getLastNode()); + + // Test deleting with 1 nodes. + aNode = aList.Delete(0); + Assert.assertNotNull(aNode); + Assert.assertEquals('c', aNode.myData()); + Assert.assertNull(aNode.nextNode()); + Assert.assertNull(aNode.prevNode()); + Assert.assertNull(aList.getFirstNode()); + Assert.assertNull(aList.getLastNode()); + } + + + @Test + public void Test_Delete_Index_Success_OnlyLast() { + Assert.assertTrue(aList.Insert('a', 0)); + Assert.assertTrue(aList.Insert('b', 1)); + Assert.assertTrue(aList.Insert('c', 2)); + + // Test deleting with 3 nodes. + aNode = aList.Delete(2); + Assert.assertNotNull(aNode); + Assert.assertEquals('c', aNode.myData()); + Assert.assertNull(aNode.nextNode()); + Assert.assertNull(aNode.prevNode()); + Assert.assertEquals('a', aList.getFirstNode().myData()); + Assert.assertEquals('b', aList.getLastNode().myData()); + Assert.assertEquals(aList.getFirstNode(), aList.getLastNode().prevNode()); + Assert.assertEquals(aList.getLastNode(), aList.getFirstNode().nextNode()); + + // Test deleting with 2 nodes. + aNode = aList.Delete(1); + Assert.assertNotNull(aNode); + Assert.assertEquals('b', aNode.myData()); + Assert.assertNull(aNode.nextNode()); + Assert.assertNull(aNode.prevNode()); + Assert.assertEquals('a', aList.getFirstNode().myData()); + Assert.assertEquals(aList.getFirstNode(), aList.getLastNode()); + + // Test deleting with 1 nodes. + aNode = aList.Delete(0); + Assert.assertNotNull(aNode); + Assert.assertEquals('a', aNode.myData()); + Assert.assertNull(aNode.nextNode()); + Assert.assertNull(aNode.prevNode()); + Assert.assertNull(aList.getFirstNode()); + Assert.assertNull(aList.getLastNode()); + } + + + @Test + public void Test_Delete_Index_Fail_BadIndex() { + // Test deleting with 0 nodes. + Assert.assertNull(aList.Delete(0)); + Assert.assertTrue(aList.Insert('a', 0)); + + // Test deleting with 1 nodes. + Assert.assertNull(aList.Delete(-1)); + Assert.assertNull(aList.Delete(1)); + Assert.assertTrue(aList.Insert('b', 1)); + + // Test deleting with 2 nodes. + Assert.assertNull(aList.Delete(-1)); + Assert.assertNull(aList.Delete(2)); + } + + + @Test + public void Test_Delete_Char_Success() { + Assert.assertTrue(aList.Insert('a', 0)); + Assert.assertTrue(aList.Insert('b', 1)); + Assert.assertTrue(aList.Insert('c', 2)); + + // Test deleting with 3 nodes. + aNode = aList.Delete('c'); + Assert.assertNotNull(aNode); + Assert.assertEquals('c', aNode.myData()); + Assert.assertNull(aNode.nextNode()); + Assert.assertNull(aNode.prevNode()); + Assert.assertEquals('a', aList.getFirstNode().myData()); + Assert.assertEquals('b', aList.getLastNode().myData()); + Assert.assertEquals(aList.getFirstNode(), aList.getLastNode().prevNode()); + Assert.assertEquals(aList.getLastNode(), aList.getFirstNode().nextNode()); + + // Test deleting with 2 nodes. + aNode = aList.Delete('b'); + Assert.assertNotNull(aNode); + Assert.assertEquals('b', aNode.myData()); + Assert.assertNull(aNode.nextNode()); + Assert.assertNull(aNode.prevNode()); + Assert.assertEquals('a', aList.getFirstNode().myData()); + Assert.assertEquals(aList.getFirstNode(), aList.getLastNode()); + + + // Test deleting with 1 nodes. + aNode = aList.Delete('a'); + Assert.assertNotNull(aNode); + Assert.assertEquals('a', aNode.myData()); + Assert.assertNull(aNode.nextNode()); + Assert.assertNull(aNode.prevNode()); + Assert.assertNull(aList.getFirstNode()); + Assert.assertNull(aList.getLastNode()); + } + + + @Test + public void Test_Delete_Char_Fail() { + // Test deleting with 0 nodes. + Assert.assertNull(aList.Delete('a')); + Assert.assertTrue(aList.Insert('a', 0)); + + // Test deleting with 1 nodes. + Assert.assertNull(aList.Delete('b')); + Assert.assertTrue(aList.Insert('b', 1)); + + // Test deleting with 2 nodes. + Assert.assertNull(aList.Delete('c')); + } + + //endregion Tests +} diff --git a/a1/tests/CharNodeTests.java b/a1/tests/CharNodeTests.java new file mode 100644 index 0000000000000000000000000000000000000000..76ab41e24b7f9c4529ecf0ff5243b1b710f79713 --- /dev/null +++ b/a1/tests/CharNodeTests.java @@ -0,0 +1,62 @@ + +import org.junit.Before; +import org.junit.Assert; +import org.junit.Test; + + +import edu.wmich.cs3310.a1.DataStructures.CharNode; + + +/** + * Tests for CharNode class. + */ +public class CharNodeTests { + + //region Variables + + CharNode aNode; + + //endregion Variables + + + + //region Tests + + @Before + public void setUp() { + aNode = new CharNode(); + } + + + @Test + public void TestNodeData() { + aNode.myData('a'); + Assert.assertEquals('a', aNode.myData()); + aNode.myData('b'); + Assert.assertEquals('b', aNode.myData()); + } + + + @Test + public void TestNextNode() { + Assert.assertNull(aNode.nextNode()); + CharNode nextNode = new CharNode(); + nextNode.myData('c'); + aNode.nextNode(nextNode); + Assert.assertEquals(nextNode, aNode.nextNode()); + Assert.assertEquals('c', aNode.nextNode().myData()); + } + + + @Test + public void TestPrevNode() { + Assert.assertNull(aNode.prevNode()); + CharNode prevNode = new CharNode(); + prevNode.myData('d'); + aNode.prevNode(prevNode); + Assert.assertEquals(prevNode, aNode.prevNode()); + Assert.assertEquals('d', aNode.prevNode().myData()); + } + + //endregion Tests +}