mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-06 17:29:31 +08:00
Enhance docs, add tests in CircularQueue
(#6015)
This commit is contained in:
@ -1,7 +1,27 @@
|
|||||||
package com.thealgorithms.datastructures.queues;
|
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.
|
||||||
|
*
|
||||||
|
* <p>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.
|
||||||
|
*
|
||||||
|
* <p>Reference: <a href="https://en.wikipedia.org/wiki/Circular_buffer">Circular Buffer</a>
|
||||||
|
*
|
||||||
|
* <p>Usage Example:
|
||||||
|
* <pre>
|
||||||
|
* CircularQueue<Integer> 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
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param <T> the type of elements in this queue
|
||||||
|
*/
|
||||||
public class CircularQueue<T> {
|
public class CircularQueue<T> {
|
||||||
private T[] array;
|
private T[] array;
|
||||||
private int topOfQueue;
|
private int topOfQueue;
|
||||||
@ -9,8 +29,17 @@ public class CircularQueue<T> {
|
|||||||
private final int size;
|
private final int size;
|
||||||
private int currentSize;
|
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")
|
@SuppressWarnings("unchecked")
|
||||||
public CircularQueue(int size) {
|
public CircularQueue(int size) {
|
||||||
|
if (size < 1) {
|
||||||
|
throw new IllegalArgumentException("Size must be greater than 0");
|
||||||
|
}
|
||||||
this.array = (T[]) new Object[size];
|
this.array = (T[]) new Object[size];
|
||||||
this.topOfQueue = -1;
|
this.topOfQueue = -1;
|
||||||
this.beginningOfQueue = -1;
|
this.beginningOfQueue = -1;
|
||||||
@ -18,14 +47,30 @@ public class CircularQueue<T> {
|
|||||||
this.currentSize = 0;
|
this.currentSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the queue is empty.
|
||||||
|
*
|
||||||
|
* @return {@code true} if the queue is empty; {@code false} otherwise
|
||||||
|
*/
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return currentSize == 0;
|
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() {
|
public boolean isFull() {
|
||||||
return currentSize == size;
|
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) {
|
public void enQueue(T value) {
|
||||||
if (isFull()) {
|
if (isFull()) {
|
||||||
throw new IllegalStateException("Queue is full");
|
throw new IllegalStateException("Queue is full");
|
||||||
@ -38,12 +83,18 @@ public class CircularQueue<T> {
|
|||||||
currentSize++;
|
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() {
|
public T deQueue() {
|
||||||
if (isEmpty()) {
|
if (isEmpty()) {
|
||||||
throw new IllegalStateException("Queue is empty");
|
throw new IllegalStateException("Queue is empty");
|
||||||
}
|
}
|
||||||
T removedValue = array[beginningOfQueue];
|
T removedValue = array[beginningOfQueue];
|
||||||
array[beginningOfQueue] = null; // Optional: Help GC
|
array[beginningOfQueue] = null; // Optional: Nullify to help garbage collection
|
||||||
beginningOfQueue = (beginningOfQueue + 1) % size;
|
beginningOfQueue = (beginningOfQueue + 1) % size;
|
||||||
currentSize--;
|
currentSize--;
|
||||||
if (isEmpty()) {
|
if (isEmpty()) {
|
||||||
@ -53,6 +104,12 @@ public class CircularQueue<T> {
|
|||||||
return removedValue;
|
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() {
|
public T peek() {
|
||||||
if (isEmpty()) {
|
if (isEmpty()) {
|
||||||
throw new IllegalStateException("Queue is empty");
|
throw new IllegalStateException("Queue is empty");
|
||||||
@ -60,6 +117,9 @@ public class CircularQueue<T> {
|
|||||||
return array[beginningOfQueue];
|
return array[beginningOfQueue];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the entire queue by resetting all elements and pointers.
|
||||||
|
*/
|
||||||
public void deleteQueue() {
|
public void deleteQueue() {
|
||||||
array = null;
|
array = null;
|
||||||
beginningOfQueue = -1;
|
beginningOfQueue = -1;
|
||||||
@ -67,35 +127,12 @@ public class CircularQueue<T> {
|
|||||||
currentSize = 0;
|
currentSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current number of elements in the queue.
|
||||||
|
*
|
||||||
|
* @return the number of elements currently in the queue
|
||||||
|
*/
|
||||||
public int size() {
|
public int size() {
|
||||||
return currentSize;
|
return currentSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
CircularQueue<Integer> 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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -103,4 +103,70 @@ class CircularQueueTest {
|
|||||||
cq.deQueue();
|
cq.deQueue();
|
||||||
assertEquals(1, cq.size());
|
assertEquals(1, cq.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testCircularWrapAround() {
|
||||||
|
CircularQueue<Integer> 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<Integer> 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<Integer> 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<Integer> 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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user