diff --git a/src/main/java/com/dataStructures/IntQueue.java b/src/main/java/com/dataStructures/IntQueue.java new file mode 100644 index 00000000..d300f383 --- /dev/null +++ b/src/main/java/com/dataStructures/IntQueue.java @@ -0,0 +1,111 @@ +package com.dataStructures; + +/** + * This file contains an implementation of an integer only queue which is extremely quick and + * lightweight. In terms of performance it can outperform java.util.ArrayDeque (Java's fastest queue + * implementation) by a factor of 40+! See the benchmark test below for proof. However, the downside + * is you need to know an upper bound on the number of elements that will be inside the queue at any + * given time for this queue to work. + * + * + */ + + +public class IntQueue { + + private int[] ar; + private int front, end, sz; + + // maxSize is the maximum number of items + // that can be in the queue at any given time + public IntQueue(int maxSize) { + front = end = 0; + sz = maxSize + 1; + ar = new int[sz]; + } + + // Return true/false on whether the queue is empty + public boolean isEmpty() { + return front == end; + } + + // Return the number of elements inside the queue + public int size() { + if (front > end) return (end + sz - front); + return end - front; + } + + public int peek() { + return ar[front]; + } + + // Add an element to the queue + public void enqueue(int value) { + ar[end] = value; + if (++end == sz) end = 0; + if (end == front) throw new RuntimeException("Queue too small!"); + } + + // Make sure you check is the queue is not empty before calling dequeue! + public int dequeue() { + int ret_val = ar[front]; + if (++front == sz) front = 0; + return ret_val; + } + + // Example usage to check the how fast this implementation is + public static void main(String[] args) { + + IntQueue q = new IntQueue(5); + + q.enqueue(1); + q.enqueue(2); + q.enqueue(3); + q.enqueue(4); + q.enqueue(5); + + System.out.println(q.dequeue()); // 1 + System.out.println(q.dequeue()); // 2 + System.out.println(q.dequeue()); // 3 + System.out.println(q.dequeue()); // 4 + + System.out.println(q.isEmpty()); // false + + q.enqueue(1); + q.enqueue(2); + q.enqueue(3); + + System.out.println(q.dequeue()); // 5 + System.out.println(q.dequeue()); // 1 + System.out.println(q.dequeue()); // 2 + System.out.println(q.dequeue()); // 3 + + System.out.println(q.isEmpty()); // true + + benchMarkTest(); + } + + // BenchMark IntQueue vs ArrayDeque. + private static void benchMarkTest() { + + int n = 10000000; + IntQueue intQ = new IntQueue(n); + + // IntQueue times at around 0.0324 seconds + long start = System.nanoTime(); + for (int i = 0; i < n; i++) intQ.enqueue(i); + for (int i = 0; i < n; i++) intQ.dequeue(); + long end = System.nanoTime(); + System.out.println("IntQueue Time: " + (end - start) / 1e9); + + // ArrayDeque times at around 1.438 seconds + java.util.ArrayDeque arrayDeque = new java.util.ArrayDeque<>(); + // java.util.ArrayDeque arrayDeque = new java.util.ArrayDeque<>(n); // strangely the + // ArrayQueue is slower when you give it an initial capacity. + start = System.nanoTime(); + for (int i = 0; i < n; i++) arrayDeque.offer(i); + for (int i = 0; i < n; i++) arrayDeque.poll(); + end = System.nanoTime(); + System.out.println("ArrayDeque Time: " + (end - start) / 1e9); + } +} \ No newline at end of file diff --git a/src/test/java/com/dataStructures/IntQueueTest.java b/src/test/java/com/dataStructures/IntQueueTest.java new file mode 100644 index 00000000..4e107c88 --- /dev/null +++ b/src/test/java/com/dataStructures/IntQueueTest.java @@ -0,0 +1,128 @@ +package com.dataStructures; + +import static org.junit.Assert.*; + +import java.util.*; +import org.junit.Before; +import org.junit.Test; + +public class IntQueueTest { + + @Before + public void setup() {} + + @Test + public void testEmptyQueue() { + IntQueue queue = new IntQueue(0); + assertTrue(queue.isEmpty()); + assertEquals(queue.size(), 0); + } + + + + @Test + public void testEnqueueOneElement() { + IntQueue queue = new IntQueue(1); + queue.enqueue(77); + assertEquals(queue.size(), 1); + } + + @Test + public void testAll() { + int n = 5; + IntQueue queue = new IntQueue(10); + assertTrue(queue.isEmpty()); + for (int i = 1; i <= n; i++) { + queue.enqueue(i); + assertFalse(queue.isEmpty()); + } + for (int i = 1; i <= n; i++) { + assertEquals(i, queue.peek()); + assertEquals(i, queue.dequeue()); + assertEquals(queue.size(), n - i); + } + assertTrue(queue.isEmpty()); + n = 8; + for (int i = 1; i <= n; i++) { + queue.enqueue(i); + assertFalse(queue.isEmpty()); + } + for (int i = 1; i <= n; i++) { + assertEquals(i, queue.peek()); + assertEquals(i, queue.dequeue()); + assertEquals(queue.size(), n - i); + } + assertTrue(queue.isEmpty()); + n = 9; + for (int i = 1; i <= n; i++) { + queue.enqueue(i); + assertFalse(queue.isEmpty()); + } + for (int i = 1; i <= n; i++) { + assertEquals(i, queue.peek()); + assertEquals(i, queue.dequeue()); + assertEquals(queue.size(), n - i); + } + assertTrue(queue.isEmpty()); + n = 10; + for (int i = 1; i <= n; i++) { + queue.enqueue(i); + assertFalse(queue.isEmpty()); + } + for (int i = 1; i <= n; i++) { + assertEquals(i, queue.peek()); + assertEquals(i, queue.dequeue()); + assertEquals(queue.size(), n - i); + } + assertTrue(queue.isEmpty()); + } + + @Test + public void testPeekOneElement() { + IntQueue queue = new IntQueue(1); + queue.enqueue(77); + assertTrue(queue.peek() == 77); + assertEquals(queue.size(), 1); + } + + @Test + public void testDequeueOneElement() { + IntQueue queue = new IntQueue(1); + queue.enqueue(77); + assertTrue(queue.dequeue() == 77); + assertEquals(queue.size(), 0); + } + + @Test + public void testRandom() { + + for (int qSize = 1; qSize <= 50; qSize++) { + + IntQueue intQ = new IntQueue(qSize); + ArrayDeque javaQ = new ArrayDeque<>(qSize); + + assertEquals(javaQ.isEmpty(), intQ.isEmpty()); + assertEquals(javaQ.size(), intQ.size()); + + for (int operations = 0; operations < 5000; operations++) { + + double r = Math.random(); + + if (r < 0.60) { + int elem = (int) (1000 * Math.random()); + if (javaQ.size() < qSize) { + javaQ.offer(elem); + intQ.enqueue(elem); + } + } else { + if (!javaQ.isEmpty()) { + assertEquals((int) javaQ.poll(), (int) intQ.dequeue()); + } + } + + assertEquals(javaQ.isEmpty(), intQ.isEmpty()); + assertEquals(javaQ.size(), intQ.size()); + } + } + } +}