A Circular Queue is a queue in which we can insert an element at the start of the Array even if our rare is reached at the last index and if we have space at the start of the array. This reduces the problem of inefficient use of array space. Once the array is filled till the last and if we have space at the beginning of an array, we fill the element at the front we perform insertion in a circular manner that’s why it is known as a circular queue.
Approach to Implementing a Circular Queue
If we observe there is a problem in the above method.
- While inserting the element in a queue instead of incrementing the index by one what we will do here is we will increase the index as (index+1) % size.
- Because of this increment when we reach the end of the queue and do increment, we will again reach index 0.
- If that index is empty which can be because of the removal of an element we can reutilize that space to insert new elements.
- In this method, when we go to the end index, we again come to the front of the queue which is why it is known as a circular queue.
Program to Implement a Circular Queue in Java
Below is the Program to implement a Circular Queue in Java:
// Java Program to implement a Circular Queue in Java import java.util.*;
public class CircularQueue
{ // Maximum size of the circular queue
private int maxSize;
// Array to store the circular queue elements
private int [] queueArray;
// Index of the front element
private int front;
// Index of the rear element
private int rear;
// constructor to initialize the circular queue with a given size
public CircularQueue( int size)
{
maxSize = size;
queueArray = new int [maxSize];
// Initially set front and rear to -1 to indicate an empty queue
front = - 1 ;
rear = - 1 ;
}
// method to enqueue (add) an item to the circular queue
public void enqueue( int item)
{
if (isEmpty())
{
front = 0 ;
rear = 0 ;
queueArray[rear] = item;
}
else {
// Circular increment of rear index
rear = (rear + 1 ) % maxSize;
if (rear == front)
{
System.out.println( "Queue is full. Cannot enqueue." );
// Reset rear to its previous value
rear = (rear - 1 + maxSize) % maxSize;
}
else {
queueArray[rear] = item;
}
}
}
// method to dequeue (remove) an item from the circular queue
public int dequeue()
{
int item = - 1 ; // Assuming -1 represents an empty value
if (!isEmpty())
{
item = queueArray[front];
if (front == rear) {
// Reset front and rear to -1 to indicate an empty queue
front = - 1 ;
rear = - 1 ;
}
else {
// Circular increment of front index
front = (front + 1 ) % maxSize;
}
}
else {
System.out.println( "Queue is empty. Cannot dequeue." );
}
return item;
}
// Method to peek at the front element of the circular queue without removing it
public int peek()
{
if (!isEmpty())
{
return queueArray[front];
}
else {
System.out.println( "Queue is empty. No peek value." );
return - 1 ; // Assuming -1 represents an empty value
}
}
// Method to check if the circular queue is empty
public boolean isEmpty()
{
return front == - 1 && rear == - 1 ;
}
// Main method for testing the CircularQueue class
public static void main(String[] args)
{
CircularQueue circularQueue = new CircularQueue( 5 );
circularQueue.enqueue( 1 );
circularQueue.enqueue( 2 );
circularQueue.enqueue( 3 );
// Should print 1
System.out.println( "Peek: " + circularQueue.peek());
// Should print 1
System.out.println( "Dequeue: " + circularQueue.dequeue());
// Should print 2
System.out.println( "Peek after dequeue: " + circularQueue.peek());
}
} |
Peek: 1 Dequeue: 1 Peek after dequeue: 2
Explanation of code:
- In this code, while inserting instead of inserting element in next space we are incrementing it by one and then performing modulo operation with it.
- So that it can go to the first element after last element.
- It results in implementation of circular data structures which uses the memory more efficiently.
Complexity of the above Program:
Time Complexity:
- Enqueue operation: O(1)
- Dequeue operation: O(1)
- Peek operation: O(1)
- isEmpty operation: O(1)
Space Complexity: O(N) where N is the size of the circular queue.