refactor: Queue
(#5348)
This commit is contained in:
parent
04eae87512
commit
8712a7f405
153
src/main/java/com/thealgorithms/datastructures/queues/Queue.java
Normal file
153
src/main/java/com/thealgorithms/datastructures/queues/Queue.java
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
package com.thealgorithms.datastructures.queues;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class implements a Queue data structure using an array.
|
||||||
|
* A queue is a first-in-first-out (FIFO) data structure where elements are
|
||||||
|
* added to the rear and removed from the front.
|
||||||
|
*
|
||||||
|
* Note: This implementation is not thread-safe.
|
||||||
|
*/
|
||||||
|
public final class Queue<T> {
|
||||||
|
|
||||||
|
private static final int DEFAULT_CAPACITY = 10;
|
||||||
|
|
||||||
|
private final int maxSize;
|
||||||
|
private final Object[] queueArray;
|
||||||
|
private int front;
|
||||||
|
private int rear;
|
||||||
|
private int nItems;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a queue with a default capacity.
|
||||||
|
*/
|
||||||
|
public Queue() {
|
||||||
|
this(DEFAULT_CAPACITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor to initialize a queue with a specified capacity.
|
||||||
|
*
|
||||||
|
* @param capacity The initial size of the queue.
|
||||||
|
* @throws IllegalArgumentException if the capacity is less than or equal to zero.
|
||||||
|
*/
|
||||||
|
public Queue(int capacity) {
|
||||||
|
if (capacity <= 0) {
|
||||||
|
throw new IllegalArgumentException("Queue capacity must be greater than 0");
|
||||||
|
}
|
||||||
|
this.maxSize = capacity;
|
||||||
|
this.queueArray = new Object[capacity];
|
||||||
|
this.front = 0;
|
||||||
|
this.rear = -1;
|
||||||
|
this.nItems = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an element at the rear of the queue.
|
||||||
|
*
|
||||||
|
* @param element Element to be added.
|
||||||
|
* @return True if the element was added successfully, false if the queue is full.
|
||||||
|
*/
|
||||||
|
public boolean insert(T element) {
|
||||||
|
if (isFull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
rear = (rear + 1) % maxSize;
|
||||||
|
queueArray[rear] = element;
|
||||||
|
nItems++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes and returns the element from the front of the queue.
|
||||||
|
*
|
||||||
|
* @return The element removed from the front of the queue.
|
||||||
|
* @throws IllegalStateException if the queue is empty.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T remove() {
|
||||||
|
if (isEmpty()) {
|
||||||
|
throw new IllegalStateException("Queue is empty, cannot remove element");
|
||||||
|
}
|
||||||
|
T removedElement = (T) queueArray[front];
|
||||||
|
queueArray[front] = null; // Optional: Clear the reference for garbage collection
|
||||||
|
front = (front + 1) % maxSize;
|
||||||
|
nItems--;
|
||||||
|
return removedElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the element at the front of the queue without removing it.
|
||||||
|
*
|
||||||
|
* @return Element at the front of the queue.
|
||||||
|
* @throws IllegalStateException if the queue is empty.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T peekFront() {
|
||||||
|
if (isEmpty()) {
|
||||||
|
throw new IllegalStateException("Queue is empty, cannot peek front");
|
||||||
|
}
|
||||||
|
return (T) queueArray[front];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the element at the rear of the queue without removing it.
|
||||||
|
*
|
||||||
|
* @return Element at the rear of the queue.
|
||||||
|
* @throws IllegalStateException if the queue is empty.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T peekRear() {
|
||||||
|
if (isEmpty()) {
|
||||||
|
throw new IllegalStateException("Queue is empty, cannot peek rear");
|
||||||
|
}
|
||||||
|
return (T) queueArray[rear];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the queue is empty.
|
||||||
|
*
|
||||||
|
* @return True if the queue is empty.
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return nItems == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the queue is full.
|
||||||
|
*
|
||||||
|
* @return True if the queue is full.
|
||||||
|
*/
|
||||||
|
public boolean isFull() {
|
||||||
|
return nItems == maxSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of elements currently in the queue.
|
||||||
|
*
|
||||||
|
* @return Number of elements in the queue.
|
||||||
|
*/
|
||||||
|
public int getSize() {
|
||||||
|
return nItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string representation of the queue.
|
||||||
|
*
|
||||||
|
* @return String representation of the queue.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (isEmpty()) {
|
||||||
|
return "[]";
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("[");
|
||||||
|
for (int i = 0; i < nItems; i++) {
|
||||||
|
int index = (front + i) % maxSize;
|
||||||
|
sb.append(queueArray[index]).append(", ");
|
||||||
|
}
|
||||||
|
sb.setLength(sb.length() - 2); // Remove the last comma and space
|
||||||
|
sb.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
@ -1,184 +0,0 @@
|
|||||||
package com.thealgorithms.datastructures.queues;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This implements Queues by using the class Queue.
|
|
||||||
*
|
|
||||||
* A queue data structure functions the same as a real world queue. The elements
|
|
||||||
* that are added first are the first to be removed. New elements are added to
|
|
||||||
* the back/rear of the queue.
|
|
||||||
*/
|
|
||||||
class Queue {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default initial capacity.
|
|
||||||
*/
|
|
||||||
private static final int DEFAULT_CAPACITY = 10;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Max size of the queue
|
|
||||||
*/
|
|
||||||
private int maxSize;
|
|
||||||
/**
|
|
||||||
* The array representing the queue
|
|
||||||
*/
|
|
||||||
private int[] queueArray;
|
|
||||||
/**
|
|
||||||
* Front of the queue
|
|
||||||
*/
|
|
||||||
private int front;
|
|
||||||
/**
|
|
||||||
* Rear of the queue
|
|
||||||
*/
|
|
||||||
private int rear;
|
|
||||||
/**
|
|
||||||
* How many items are in the queue
|
|
||||||
*/
|
|
||||||
private int nItems;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* init with DEFAULT_CAPACITY
|
|
||||||
*/
|
|
||||||
Queue() {
|
|
||||||
this(DEFAULT_CAPACITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* @param size Size of the new queue
|
|
||||||
*/
|
|
||||||
Queue(int size) {
|
|
||||||
maxSize = size;
|
|
||||||
queueArray = new int[size];
|
|
||||||
front = 0;
|
|
||||||
rear = -1;
|
|
||||||
nItems = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts an element at the rear of the queue
|
|
||||||
*
|
|
||||||
* @param x element to be added
|
|
||||||
* @return True if the element was added successfully
|
|
||||||
*/
|
|
||||||
public boolean insert(int x) {
|
|
||||||
if (isFull()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// If the back of the queue is the end of the array wrap around to the front
|
|
||||||
rear = (rear + 1) % maxSize;
|
|
||||||
queueArray[rear] = x;
|
|
||||||
nItems++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an element from the front of the queue
|
|
||||||
*
|
|
||||||
* @return the new front of the queue
|
|
||||||
*/
|
|
||||||
public int remove() {
|
|
||||||
if (isEmpty()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int temp = queueArray[front];
|
|
||||||
front = (front + 1) % maxSize;
|
|
||||||
nItems--;
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks what's at the front of the queue
|
|
||||||
*
|
|
||||||
* @return element at the front of the queue
|
|
||||||
*/
|
|
||||||
public int peekFront() {
|
|
||||||
return queueArray[front];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks what's at the rear of the queue
|
|
||||||
*
|
|
||||||
* @return element at the rear of the queue
|
|
||||||
*/
|
|
||||||
public int peekRear() {
|
|
||||||
return queueArray[rear];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the queue is empty
|
|
||||||
*
|
|
||||||
* @return true if the queue is empty
|
|
||||||
*/
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return nItems == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the queue is full
|
|
||||||
*
|
|
||||||
* @return true if the queue is full
|
|
||||||
*/
|
|
||||||
public boolean isFull() {
|
|
||||||
return nItems == maxSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of elements in the queue
|
|
||||||
*
|
|
||||||
* @return number of elements in the queue
|
|
||||||
*/
|
|
||||||
public int getSize() {
|
|
||||||
return nItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("[");
|
|
||||||
for (int i = front;; i = ++i % maxSize) {
|
|
||||||
sb.append(queueArray[i]).append(", ");
|
|
||||||
if (i == rear) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sb.replace(sb.length() - 2, sb.length(), "]");
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is the example for the Queue class
|
|
||||||
*
|
|
||||||
* @author Unknown
|
|
||||||
*/
|
|
||||||
public final class Queues {
|
|
||||||
private Queues() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main method
|
|
||||||
*
|
|
||||||
* @param args Command line arguments
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) {
|
|
||||||
Queue myQueue = new Queue(4);
|
|
||||||
myQueue.insert(10);
|
|
||||||
myQueue.insert(2);
|
|
||||||
myQueue.insert(5);
|
|
||||||
myQueue.insert(3);
|
|
||||||
// [10(front), 2, 5, 3(rear)]
|
|
||||||
|
|
||||||
System.out.println(myQueue.isFull()); // Will print true
|
|
||||||
|
|
||||||
myQueue.remove(); // Will make 2 the new front, making 10 no longer part of the queue
|
|
||||||
// [10, 2(front), 5, 3(rear)]
|
|
||||||
|
|
||||||
myQueue.insert(7); // Insert 7 at the rear which will get 0 index because of wrap around
|
|
||||||
// [7(rear), 2(front), 5, 3]
|
|
||||||
|
|
||||||
System.out.println(myQueue.peekFront()); // Will print 2
|
|
||||||
System.out.println(myQueue.peekRear()); // Will print 7
|
|
||||||
System.out.println(myQueue); // Will print [2, 5, 3, 7]
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,127 @@
|
|||||||
|
package com.thealgorithms.datastructures.queues;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class QueueTest {
|
||||||
|
|
||||||
|
private static final int INITIAL_CAPACITY = 3;
|
||||||
|
private Queue<Integer> queue;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
queue = new Queue<>(INITIAL_CAPACITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testQueueInsertion() {
|
||||||
|
Assertions.assertTrue(queue.insert(1));
|
||||||
|
Assertions.assertTrue(queue.insert(2));
|
||||||
|
Assertions.assertTrue(queue.insert(3));
|
||||||
|
Assertions.assertFalse(queue.insert(4)); // Queue is full
|
||||||
|
|
||||||
|
Assertions.assertEquals(1, queue.peekFront());
|
||||||
|
Assertions.assertEquals(3, queue.peekRear());
|
||||||
|
Assertions.assertEquals(3, queue.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testQueueRemoval() {
|
||||||
|
queue.insert(1);
|
||||||
|
queue.insert(2);
|
||||||
|
queue.insert(3);
|
||||||
|
|
||||||
|
Assertions.assertEquals(1, queue.remove());
|
||||||
|
Assertions.assertEquals(2, queue.peekFront());
|
||||||
|
Assertions.assertEquals(2, queue.getSize());
|
||||||
|
|
||||||
|
Assertions.assertEquals(2, queue.remove());
|
||||||
|
Assertions.assertEquals(3, queue.peekFront());
|
||||||
|
Assertions.assertEquals(1, queue.getSize());
|
||||||
|
|
||||||
|
Assertions.assertEquals(3, queue.remove());
|
||||||
|
Assertions.assertTrue(queue.isEmpty());
|
||||||
|
|
||||||
|
Assertions.assertThrows(IllegalStateException.class, queue::remove); // Queue is empty
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPeekFrontAndRear() {
|
||||||
|
queue.insert(1);
|
||||||
|
queue.insert(2);
|
||||||
|
|
||||||
|
Assertions.assertEquals(1, queue.peekFront());
|
||||||
|
Assertions.assertEquals(2, queue.peekRear());
|
||||||
|
|
||||||
|
queue.insert(3);
|
||||||
|
Assertions.assertEquals(1, queue.peekFront());
|
||||||
|
Assertions.assertEquals(3, queue.peekRear());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testQueueIsEmptyAndIsFull() {
|
||||||
|
Assertions.assertTrue(queue.isEmpty());
|
||||||
|
Assertions.assertFalse(queue.isFull());
|
||||||
|
|
||||||
|
queue.insert(1);
|
||||||
|
queue.insert(2);
|
||||||
|
queue.insert(3);
|
||||||
|
|
||||||
|
Assertions.assertFalse(queue.isEmpty());
|
||||||
|
Assertions.assertTrue(queue.isFull());
|
||||||
|
|
||||||
|
queue.remove();
|
||||||
|
Assertions.assertFalse(queue.isFull());
|
||||||
|
Assertions.assertFalse(queue.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testQueueSize() {
|
||||||
|
Assertions.assertEquals(0, queue.getSize());
|
||||||
|
queue.insert(1);
|
||||||
|
Assertions.assertEquals(1, queue.getSize());
|
||||||
|
queue.insert(2);
|
||||||
|
Assertions.assertEquals(2, queue.getSize());
|
||||||
|
queue.insert(3);
|
||||||
|
Assertions.assertEquals(3, queue.getSize());
|
||||||
|
queue.remove();
|
||||||
|
Assertions.assertEquals(2, queue.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testQueueToString() {
|
||||||
|
Assertions.assertEquals("[]", queue.toString());
|
||||||
|
|
||||||
|
queue.insert(1);
|
||||||
|
queue.insert(2);
|
||||||
|
Assertions.assertEquals("[1, 2]", queue.toString());
|
||||||
|
|
||||||
|
queue.insert(3);
|
||||||
|
Assertions.assertEquals("[1, 2, 3]", queue.toString());
|
||||||
|
|
||||||
|
queue.remove();
|
||||||
|
Assertions.assertEquals("[2, 3]", queue.toString());
|
||||||
|
|
||||||
|
queue.remove();
|
||||||
|
queue.remove();
|
||||||
|
Assertions.assertEquals("[]", queue.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testQueueThrowsExceptionOnEmptyPeek() {
|
||||||
|
Assertions.assertThrows(IllegalStateException.class, queue::peekFront);
|
||||||
|
Assertions.assertThrows(IllegalStateException.class, queue::peekRear);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testQueueThrowsExceptionOnRemoveFromEmptyQueue() {
|
||||||
|
Assertions.assertThrows(IllegalStateException.class, queue::remove);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testQueueCapacityException() {
|
||||||
|
Assertions.assertThrows(IllegalArgumentException.class, () -> new Queue<>(0));
|
||||||
|
Assertions.assertThrows(IllegalArgumentException.class, () -> new Queue<>(-5));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user