diff --git a/src/main/java/com/thealgorithms/datastructures/queues/CircularQueue.java b/src/main/java/com/thealgorithms/datastructures/queues/CircularQueue.java index c67817a6f..74ee06ca9 100644 --- a/src/main/java/com/thealgorithms/datastructures/queues/CircularQueue.java +++ b/src/main/java/com/thealgorithms/datastructures/queues/CircularQueue.java @@ -1,7 +1,27 @@ package com.thealgorithms.datastructures.queues; -// This program implements the concept of CircularQueue in Java -// Link to the concept: (https://en.wikipedia.org/wiki/Circular_buffer) +/** + * The CircularQueue class represents a generic circular queue data structure that uses an array to + * store elements. This queue allows efficient utilization of space by wrapping around the array, + * thus avoiding the need to shift elements during enqueue and dequeue operations. + * + *

When the queue reaches its maximum capacity, further enqueues will raise an exception. + * Similarly, attempts to dequeue or peek from an empty queue will also result in an exception. + * + *

Reference: Circular Buffer + * + *

Usage Example: + *

+ *     CircularQueue queue = new CircularQueue<>(3);
+ *     queue.enQueue(1);
+ *     queue.enQueue(2);
+ *     queue.enQueue(3);
+ *     queue.deQueue(); // Removes 1
+ *     queue.enQueue(4); // Wraps around and places 4 at the position of removed 1
+ * 
+ * + * @param the type of elements in this queue + */ public class CircularQueue { private T[] array; private int topOfQueue; @@ -9,8 +29,17 @@ public class CircularQueue { private final int size; private int currentSize; + /** + * Constructs a CircularQueue with a specified capacity. + * + * @param size the maximum number of elements this queue can hold + * @throws IllegalArgumentException if the size is less than 1 + */ @SuppressWarnings("unchecked") public CircularQueue(int size) { + if (size < 1) { + throw new IllegalArgumentException("Size must be greater than 0"); + } this.array = (T[]) new Object[size]; this.topOfQueue = -1; this.beginningOfQueue = -1; @@ -18,14 +47,30 @@ public class CircularQueue { this.currentSize = 0; } + /** + * Checks if the queue is empty. + * + * @return {@code true} if the queue is empty; {@code false} otherwise + */ public boolean isEmpty() { return currentSize == 0; } + /** + * Checks if the queue is full. + * + * @return {@code true} if the queue has reached its maximum capacity; {@code false} otherwise + */ public boolean isFull() { return currentSize == size; } + /** + * Adds a new element to the queue. If the queue is full, an exception is thrown. + * + * @param value the element to be added to the queue + * @throws IllegalStateException if the queue is already full + */ public void enQueue(T value) { if (isFull()) { throw new IllegalStateException("Queue is full"); @@ -38,12 +83,18 @@ public class CircularQueue { currentSize++; } + /** + * Removes and returns the element at the front of the queue. + * + * @return the element at the front of the queue + * @throws IllegalStateException if the queue is empty + */ public T deQueue() { if (isEmpty()) { throw new IllegalStateException("Queue is empty"); } T removedValue = array[beginningOfQueue]; - array[beginningOfQueue] = null; // Optional: Help GC + array[beginningOfQueue] = null; // Optional: Nullify to help garbage collection beginningOfQueue = (beginningOfQueue + 1) % size; currentSize--; if (isEmpty()) { @@ -53,6 +104,12 @@ public class CircularQueue { return removedValue; } + /** + * Returns the element at the front of the queue without removing it. + * + * @return the element at the front of the queue + * @throws IllegalStateException if the queue is empty + */ public T peek() { if (isEmpty()) { throw new IllegalStateException("Queue is empty"); @@ -60,6 +117,9 @@ public class CircularQueue { return array[beginningOfQueue]; } + /** + * Deletes the entire queue by resetting all elements and pointers. + */ public void deleteQueue() { array = null; beginningOfQueue = -1; @@ -67,35 +127,12 @@ public class CircularQueue { currentSize = 0; } + /** + * Returns the current number of elements in the queue. + * + * @return the number of elements currently in the queue + */ public int size() { return currentSize; } - - public static void main(String[] args) { - CircularQueue cq = new CircularQueue<>(5); - System.out.println(cq.isEmpty()); // true - System.out.println(cq.isFull()); // false - cq.enQueue(1); - cq.enQueue(2); - cq.enQueue(3); - cq.enQueue(4); - cq.enQueue(5); - - System.out.println(cq.deQueue()); // 1 - System.out.println(cq.deQueue()); // 2 - System.out.println(cq.deQueue()); // 3 - System.out.println(cq.deQueue()); // 4 - System.out.println(cq.deQueue()); // 5 - - System.out.println(cq.isFull()); // false - System.out.println(cq.isEmpty()); // true - cq.enQueue(6); - cq.enQueue(7); - cq.enQueue(8); - - System.out.println(cq.peek()); // 6 - System.out.println(cq.peek()); // 6 - - cq.deleteQueue(); - } } diff --git a/src/test/java/com/thealgorithms/datastructures/queues/CircularQueueTest.java b/src/test/java/com/thealgorithms/datastructures/queues/CircularQueueTest.java index 71dca8fdb..55ce9995a 100644 --- a/src/test/java/com/thealgorithms/datastructures/queues/CircularQueueTest.java +++ b/src/test/java/com/thealgorithms/datastructures/queues/CircularQueueTest.java @@ -103,4 +103,70 @@ class CircularQueueTest { cq.deQueue(); assertEquals(1, cq.size()); } + + @Test + void testCircularWrapAround() { + CircularQueue cq = new CircularQueue<>(3); + cq.enQueue(1); + cq.enQueue(2); + cq.enQueue(3); + + cq.deQueue(); + cq.enQueue(4); + + assertEquals(2, cq.deQueue()); + assertEquals(3, cq.deQueue()); + assertEquals(4, cq.deQueue()); + assertTrue(cq.isEmpty()); + } + + @Test + void testEnQueueDeQueueMultipleTimes() { + CircularQueue cq = new CircularQueue<>(3); + cq.enQueue(1); + cq.enQueue(2); + cq.deQueue(); + cq.enQueue(3); + cq.enQueue(4); + + assertTrue(cq.isFull()); + assertEquals(2, cq.deQueue()); + assertEquals(3, cq.deQueue()); + assertEquals(4, cq.deQueue()); + assertTrue(cq.isEmpty()); + } + + @Test + void testMultipleWrapArounds() { + CircularQueue cq = new CircularQueue<>(3); + cq.enQueue(1); + cq.deQueue(); + cq.enQueue(2); + cq.deQueue(); + cq.enQueue(3); + cq.deQueue(); + cq.enQueue(4); + + assertEquals(4, cq.peek()); + } + + @Test + void testSizeDuringOperations() { + CircularQueue cq = new CircularQueue<>(3); + assertEquals(0, cq.size()); + + cq.enQueue(1); + cq.enQueue(2); + assertEquals(2, cq.size()); + + cq.deQueue(); + assertEquals(1, cq.size()); + + cq.enQueue(3); + cq.enQueue(4); + assertEquals(3, cq.size()); + cq.deQueue(); + cq.deQueue(); + assertEquals(1, cq.size()); + } }