diff --git a/README.md b/README.md index 75396bf4..00e6463d 100644 --- a/README.md +++ b/README.md @@ -44,9 +44,9 @@ This repository contains implementation of some of the fundamental data structur ## Short-cut to CS2040S Material 1. Basic structures - * Linked List - * Stack - * Queue + * [Linked List](src/dataStructures/linkedList) + * [Stack](src/dataStructures/stack) + * [Queue](src/dataStructures/queue) 2. Binary Search * Peak Finding 3. Sorting diff --git a/src/dataStructures/stackAndQueue/monotonicQueue/MonotonicQueue.java b/src/dataStructures/queue/MonotonicQueue.java similarity index 79% rename from src/dataStructures/stackAndQueue/monotonicQueue/MonotonicQueue.java rename to src/dataStructures/queue/MonotonicQueue.java index 825b5918..a564b1a8 100644 --- a/src/dataStructures/stackAndQueue/monotonicQueue/MonotonicQueue.java +++ b/src/dataStructures/queue/MonotonicQueue.java @@ -1,4 +1,4 @@ -package src.dataStructures.stackAndQueue.monotonicQueue; +package src.dataStructures.queue; import java.util.Deque; import java.util.ArrayDeque; @@ -11,7 +11,14 @@ * max() * pop() * push() - * @param generic type for objects to be stored or queried + * @param generic type for objects to be stored or queried + * + * index v Increasing queue Decreasing queue + * 1 5 [5] [5] + * 2 3 [3] 3 kick out 5 [5, 3] #3->5 + * 3 1 [1] 1 kick out 3 [5, 3, 1] #1->3 + * 4 2 [1, 2] #2->1 [5, 3, 2] 2 kick out 1 #2->3 + * 5 4 [1, 2, 4] #4->2 [5,4] 4 kick out 2, 3 #4->2 */ public class MonotonicQueue> { private Deque> dq = new ArrayDeque<>(); // or LinkedList @@ -54,6 +61,9 @@ public T max() { * Removal will only be done all representation of the object has been accounted for. */ public T pop() { + if (dq.isEmpty()) { + return null; + } Pair node = dq.peek(); if (node.countDeleted > 0) { node.countDeleted -= 1; diff --git a/src/dataStructures/stackAndQueue/queue/Queue.java b/src/dataStructures/queue/Queue.java similarity index 97% rename from src/dataStructures/stackAndQueue/queue/Queue.java rename to src/dataStructures/queue/Queue.java index e0a39321..fa72e07b 100644 --- a/src/dataStructures/stackAndQueue/queue/Queue.java +++ b/src/dataStructures/queue/Queue.java @@ -1,4 +1,4 @@ -package src.dataStructures.stackAndQueue.queue; +package src.dataStructures.queue; /** * Implementation of a queue structure using LinkedList. diff --git a/src/dataStructures/queue/README.md b/src/dataStructures/queue/README.md new file mode 100644 index 00000000..b282a8f0 --- /dev/null +++ b/src/dataStructures/queue/README.md @@ -0,0 +1,68 @@ +# Queue + +A queue is a linear data structure that restricts the order in which operations can be performed on its elements. + +### Operation Orders + +![Queue](https://media.geeksforgeeks.org/wp-content/cdn-uploads/20221213113312/Queue-Data-Structures.png) + +*Source: GeeksForGeeks* + +Queue follows a FIFO, first in first out order. +This means the earliest element +added to the stack is the one operations are conducted on first. + +A [stack](../stack/README.md) is a queue with operations conducted in an opposite manner. + +## Analysis + +As a queue only interacts with either the first or last element regardless during its operations, +it only needs to keep the pointers of the two element at hand, which is constantly updated as more +elements are removed / added. This allows stack operations to only incur a *O(1)* time complexity. + +## Notes + +### Stack vs Queues + +Stack and queues only differ in terms of operation order, you should aim to use a stack when +you want the most recent elements to be operated on. +Some situations where a stack would work well include build redo / undo systems and backtracking problems. + +On the other hand, a queue allows you to operate on elements that enter first. Some situations where +this would be useful include Breadth First Search algorithms and task / resource allocation systems. + +### Arrays vs Linked List +It is worth noting that queues can be implemented with either a array or with a [linked list](../linkedList/README.md). +In the context of ordered operations, the lookup is only restricted to the first element. + +Hence, there is not much advantage in using a array, which only has a better lookup speed (*O(1)* time complexity) +to implement a queue. Especially when using a linked list to construct your queue +would allow you to grow or shrink the queue as you wish. + +### Queue Variants + +These are some variants of queue that are commonly used. + +#### Double Ended Queue (Deque) + +![Deque](https://media.geeksforgeeks.org/wp-content/uploads/anod.png) + +*Source: GeeksForGeeks* + +Deque is a variant of queue where elements can be removed or added from the head and tail of the queue. +Deque could come in handy when trying to solve sliding window problems. + +A deque can be implemented in multiple ways, using doubly linked lists, arrays or two stacks. + +#### Monotonic Queue + +This is a variant of queue where elements within the queue are either strictly increasing or decreasing. +Monotonic queues are often implemented with a deque. + +Within a increasing monotonic queue, any element that is smaller than the current minimum is removed. +Within a decreasing monotonic queue, any element that is larger than the current maximum is removed. + +It is worth mentioning that the most elements added to the monotonic queue would always be in a +increasing / decreasing order, +hence, we only need to compare down the monotonic queue from the back when adding new elements. + diff --git a/src/dataStructures/stack/README.md b/src/dataStructures/stack/README.md new file mode 100644 index 00000000..a7e7c3c8 --- /dev/null +++ b/src/dataStructures/stack/README.md @@ -0,0 +1,40 @@ +# Stack +Stack is a linear data structure that restricts +the order in which operations can be performed on its elements. + +![Stack data structure](https://cdn.programiz.com/sites/tutorial2program/files/stack.png) + +*Source: Programiz* + +### Operation Orders + +Stack follows a LIFO, last in first out order. +This means the most recent element +added to the stack is the one operations are conducted on first. + +A [queue](../queue/README.md) conducts operations in the opposite order. + +## Analysis + +As a stack only interacts with the most recent element regardless of operation, +it keeps the pointer of the most recent element at hand, which is constantly updated as more +elements are removed / added. This allows stack operations to only incur a *O(1)* time complexity. + +## Notes + +### Stack vs Queues + +Stack and queues only differ in terms of operation order, you should aim to use a stack when +you want the most recent elements to be operated on. +Some situations where a stack would work well include build redo / undo systems and backtracking problems. + +On the other hand, a queue allows you to operate on elements that enter first. Some situations where +this would be useful include Breadth First Search algorithms and task / resource allocation systems. + +### Arrays vs Linked List +It is worth noting that stacks can be implemented with either a array or with a [linked list](../linkedList/README.md). +In the context of ordered operations, the lookup is only restricted to the first element. + +Hence, there is not much advantage in using a array, which only has a better lookup speed (*O(1)* time complexity) +to implement a stack. Especially when using a linked list to construct your stack +would allow you to grow or shrink the stack as you wish. \ No newline at end of file diff --git a/src/dataStructures/stackAndQueue/stack/Stack.java b/src/dataStructures/stack/Stack.java similarity index 97% rename from src/dataStructures/stackAndQueue/stack/Stack.java rename to src/dataStructures/stack/Stack.java index d91c00b5..c00d71da 100644 --- a/src/dataStructures/stackAndQueue/stack/Stack.java +++ b/src/dataStructures/stack/Stack.java @@ -1,4 +1,4 @@ -package src.dataStructures.stackAndQueue.stack; +package src.dataStructures.stack; import java.util.List; import java.util.ArrayList; diff --git a/test/dataStructures/queue/queueTest.java b/test/dataStructures/queue/queueTest.java new file mode 100644 index 00000000..2ccaf7f8 --- /dev/null +++ b/test/dataStructures/queue/queueTest.java @@ -0,0 +1,49 @@ +package test.dataStructures.queue; + +import org.junit.Assert; +import org.junit.Test; +import src.dataStructures.queue.Queue; + +public class queueTest { + @Test + public void testEmptyQueue() { + Queue q = new Queue<>(); + Assert.assertEquals(0, q.size()); + Assert.assertEquals(true, q.isEmpty()); + Assert.assertEquals(null, q.dequeue()); + } + @Test + public void testEnqueue() { + Queue q = new Queue<>(); + q.enqueue(1); + q.enqueue(2); + q.enqueue(3); + Assert.assertEquals(3, q.size()); + } + + @Test + public void testPeek() { + Queue q = new Queue<>(); + q.enqueue(1); + Assert.assertEquals("1", q.peek().toString()); + q.enqueue(2); + q.enqueue(3); + q.peek(); + Assert.assertEquals("1", q.peek().toString()); + } + + @Test + public void testDequeue() { + Queue q = new Queue<>(); + q.enqueue(1); + q.enqueue(2); + q.enqueue(3); + Assert.assertEquals("1", q.dequeue().toString()); + Assert.assertEquals(2, q.size()); + q.dequeue(); + Assert.assertEquals(1, q.size()); + Assert.assertEquals("3", q.dequeue().toString()); + Assert.assertEquals(0, q.size()); + } + +} diff --git a/test/dataStructures/stack/StackTest.java b/test/dataStructures/stack/StackTest.java new file mode 100644 index 00000000..5c0915ce --- /dev/null +++ b/test/dataStructures/stack/StackTest.java @@ -0,0 +1,32 @@ +package test.dataStructures.stack; + +import org.junit.Assert; +import org.junit.Test; +import src.dataStructures.stack.Stack; +public class StackTest { + @Test + public void testEmpty(){ + Stack stk = new Stack<>(); + Assert.assertEquals(null, stk.pop()); + Assert.assertEquals(null, stk.peek()); + } + + @Test + public void testPopAndPeek() { + Stack stk = new Stack<>(1, 2, 3); + Assert.assertEquals("3", stk.peek().toString()); + Assert.assertEquals("3", stk.pop().toString()); + Assert.assertEquals("2", stk.peek().toString()); + } + + @Test + public void testPush() { + Stack stk = new Stack<>(); + stk.push(1); + Assert.assertEquals("1", stk.peek().toString()); + stk.push(2); + stk.push(3); + Assert.assertEquals("3", stk.peek().toString()); + } + +} diff --git a/test/randomTests/changxian/stackAndQueue/monotonicQueue/Test.java b/test/randomTests/changxian/stackAndQueue/monotonicQueue/Test.java index 56482efe..eb55b63b 100644 --- a/test/randomTests/changxian/stackAndQueue/monotonicQueue/Test.java +++ b/test/randomTests/changxian/stackAndQueue/monotonicQueue/Test.java @@ -1,6 +1,6 @@ package test.randomTests.changxian.stackAndQueue.monotonicQueue; -import src.dataStructures.stackAndQueue.monotonicQueue.MonotonicQueue; +import src.dataStructures.queue.MonotonicQueue; import java.util.Arrays; import java.util.ArrayList; diff --git a/test/randomTests/changxian/stackAndQueue/queue/Test.java b/test/randomTests/changxian/stackAndQueue/queue/Test.java index de8b01c1..477c3c3e 100644 --- a/test/randomTests/changxian/stackAndQueue/queue/Test.java +++ b/test/randomTests/changxian/stackAndQueue/queue/Test.java @@ -1,6 +1,6 @@ package test.randomTests.changxian.stackAndQueue.queue; -import src.dataStructures.stackAndQueue.queue.Queue; +import src.dataStructures.queue.Queue; /** * Basic Testing diff --git a/test/randomTests/changxian/stackAndQueue/stack/Test.java b/test/randomTests/changxian/stackAndQueue/stack/Test.java index 13b0fa96..04370abb 100644 --- a/test/randomTests/changxian/stackAndQueue/stack/Test.java +++ b/test/randomTests/changxian/stackAndQueue/stack/Test.java @@ -1,6 +1,6 @@ package test.randomTests.changxian.stackAndQueue.stack; -import src.dataStructures.stackAndQueue.stack.Stack; +import src.dataStructures.stack.Stack; /* * Basic Testing