diff --git a/src/dataStructures/queue/MonotonicQueue.java b/src/dataStructures/queue/MonotonicQueue.java index a564b1a8..520a9d4e 100644 --- a/src/dataStructures/queue/MonotonicQueue.java +++ b/src/dataStructures/queue/MonotonicQueue.java @@ -4,7 +4,7 @@ import java.util.ArrayDeque; /** - * Implementation of a non-increasing monotonic queue for certain (but common) use case: + * Implementation of a non-increasing (decreasing) monotonic queue for certain (but common) use case: * When larger objects pushed to the queue are able to replace and represent smaller objects that come before it. * Callable methods are: * isEmpty() @@ -20,8 +20,9 @@ * 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 + private Deque dq = new ArrayDeque<>(); // or LinkedList /** * Checks if queue is empty. @@ -37,12 +38,10 @@ public boolean isEmpty() { */ public void push(T obj) { Integer count = 0; - while (!dq.isEmpty() && obj.compareTo(dq.peekLast().value) >= 0) { - Pair popped = dq.pollLast(); - // accumulate count of objects that were popped to maintain the non-increasing property - count += 1 + popped.countDeleted; + while (!dq.isEmpty() && obj.compareTo(dq.peekLast()) > 0) { + dq.pollLast(); // Removes elements that do not conform the non-increasing sequence. } - dq.offerLast(new Pair(obj, count)); + dq.offerLast(obj); } /** @@ -53,7 +52,7 @@ public T max() { if (isEmpty()) { return null; } - return dq.peek().value; + return dq.peek(); } /** @@ -64,26 +63,6 @@ public T pop() { if (dq.isEmpty()) { return null; } - Pair node = dq.peek(); - if (node.countDeleted > 0) { - node.countDeleted -= 1; - return node.value; - } - dq.poll(); - return node.value; - } - - /** - * Node class that is represented as a pair. - * Tracks the deleted count and the value to be wrapped. - */ - private static class Pair { - private T value; - private Integer countDeleted; - - private Pair(T val, Integer count) { - this.value = val; - this.countDeleted = count; - } + return dq.poll(); // Returns & remove head of deque } } diff --git a/test/dataStructures/queue/MonotonicQueueTest.java b/test/dataStructures/queue/MonotonicQueueTest.java new file mode 100644 index 00000000..d55ef1e9 --- /dev/null +++ b/test/dataStructures/queue/MonotonicQueueTest.java @@ -0,0 +1,57 @@ +package test.dataStructures.queue; + +import org.junit.Assert; +import org.junit.Test; +import src.dataStructures.queue.MonotonicQueue; +public class MonotonicQueueTest { + @Test + public void testEmpty() { + MonotonicQueue q = new MonotonicQueue<>(); + Assert.assertEquals(true, q.isEmpty()); + Assert.assertEquals(null, q.max()); + Assert.assertEquals(null, q.pop()); + } + + @Test + public void testMax() { + MonotonicQueue q = new MonotonicQueue<>(); + q.push(2); + Assert.assertEquals("2", q.max().toString()); + q.push(7); + Assert.assertEquals("7", q.max().toString()); + q.push(1); + Assert.assertEquals("7", q.max().toString()); + q.push(7); + Assert.assertEquals("7", q.max().toString()); + q.push(5); + Assert.assertEquals("7", q.max().toString()); + q.push(4); + Assert.assertEquals("7", q.max().toString()); + q.push(3); + q.push(2); + q.push(5); + Assert.assertEquals("7", q.max().toString()); + } + + @Test + public void testPop() { + MonotonicQueue q = new MonotonicQueue<>(); + q.push(2); + q.push(7); + q.push(1); + q.push(7); + q.push(5); + q.push(4); + q.push(3); + q.push(2); + q.push(5); + q.push(2); + + Assert.assertEquals("7", q.pop().toString()); + Assert.assertEquals("7", q.pop().toString()); + Assert.assertEquals("5", q.pop().toString()); + q.pop(); + Assert.assertEquals("2", q.pop().toString()); + Assert.assertEquals(null, q.pop()); + } +}