Circular Queue in Data Structure

In this Blog, we will talk about circular queue in data structure. We will cover the multiple approaches to implement circular queue in data structure. Also we will see the applications of circular queue in data structure. Circular queue is an efficient data structure in comparison with a simple queue as it doesn’t waste the space allotted to it.

Lets see What Is Circular Queue in Data Structure?

What is Circular Queue in Data Structure?

Circular queue in data structure is a linear data structure that follows the FIFO(First in first out) property. In this, the last element is connected to the first element to make a ring, which is also known as a Ring buffer.

How does the Circular queue in data structure work?

A circular queue in data structure works in the process of circular increment i.e. when we’ll increment the pointer and reach the end then pointer points to the beginning of the queue.

Operations of a Circular Queue in Data Structure:

  • front(): front is used to track the first element of the queue.
  • rear(): rear is used to track the last element of the queue.
  • Enqueue: This operation is used to Insert an element at the end of the queue.
  • Dequeue: This operation is used to remove and return an element from the front of the queue.

Steps for Enqueue Operation:

  • Check if the queue is full.
  • If the queue is full then, the print queue is full.
  • If not, check the condition(rear == size -1 && front != 0)
  • If it is true then set the rear = 0 and insert the new element.

Algorithm to Insert an Element in a Circular Queue in Data Structure

Step 1: IF (REAR+1)%MAX = FRONT
Write " OVERFLOW "
Goto step 4
[End OF IF]

Step 2: IF FRONT = -1 and REAR = -1
SET FRONT = REAR = 0
ELSE IF REAR = MAX – 1 and FRONT ! = 0
SET REAR = 0
ELSE
SET REAR = (REAR + 1) % MAX
[END OF IF]

Step 3: SET QUEUE[REAR] = VAL

Step 4: EXIT

Steps for Dequeue Operations:

  • Firstly, check whether the queue is empty or not.
  • If the queue is empty then display the queue is empty.
  • If not, check the condition(rear == front)
  • If the condition is true then set front = rear = -1.
  • Else, front == size-1 and return the element.

Algorithm to Delete an Element from the Circular Queue in Data Structure

Step 1: IF FRONT = -1
Write " UNDERFLOW "
Goto Step 4
[END of IF]

Step 2: SET VAL = QUEUE[FRONT]

Step 3: IF FRONT = REAR
SET FRONT = REAR = -1
ELSE
IF FRONT = MAX -1
SET FRONT = 0
ELSE
SET FRONT = FRONT + 1
[END of IF]
[END OF IF]

Step 4: EXIT

Code Implementation

#include<bits/stdc++.h>
using namespace std;

class Queue
{
    int rear, front;


    int size;
    int *arr;
public:
    Queue(int s)
    {
    front = rear = -1;
    size = s;
    arr = new int[s];
    }

    void enQueue(int value);
    int deQueue();
    void displayQueue();
};


void Queue::enQueue(int value)
{
    if ((front == 0 && rear == size-1) ||
            (rear == (front-1)%(size-1)))
    {
        printf("\nQueue is Full");
        return;
    }

    else if (front == -1)
    {
        front = rear = 0;
        arr[rear] = value;
    }

    else if (rear == size-1 && front != 0)
    {
        rear = 0;
        arr[rear] = value;
    }

    else
    {
        rear++;
        arr[rear] = value;
    }
}

int Queue::deQueue()
{
    if (front == -1)
    {
        printf("\nQueue is Empty");
        return INT_MIN;
    }

    int data = arr[front];
    arr[front] = -1;
    if (front == rear)
    {
        front = -1;
        rear = -1;
    }
    else if (front == size-1)
        front = 0;
    else
        front++;

    return data;
}


void Queue::displayQueue()
{
    if (front == -1)
    {
        printf("\nQueue is Empty");
        return;
    }
    printf("\nElements in Circular Queue are: ");
    if (rear >= front)
    {
        for (int i = front; i <= rear; i++)
            printf("%d ",arr[i]);
    }
    else
    {
        for (int i = front; i < size; i++)
            printf("%d ", arr[i]);

        for (int i = 0; i <= rear; i++)
            printf("%d ", arr[i]);
    }
}

int main()
{
    Queue q(5);

    // Inserting elements in Circular Queue
    q.enQueue(40);
    q.enQueue(22);
    q.enQueue(30);
    q.enQueue(-7);

    q.displayQueue();

    printf("\nDeleted value = %d", q.deQueue());
    printf("\nDeleted value = %d", q.deQueue());

    q.displayQueue();

    q.enQueue(90);
    q.enQueue(20);
    q.enQueue(5);

    q.displayQueue();

    q.enQueue(20);
    return 0;
}
import java.util.ArrayList;

class CircularQueue{

private int size, front, rear;

private ArrayList<Integer> queue = new ArrayList<Integer>();


CircularQueue(int size)
{
    this.size = size;
    this.front = this.rear = -1;
}

public void enQueue(int data)
{
    

    if((front == 0 && rear == size - 1) ||
    (rear == (front - 1) % (size - 1)))
    {
        System.out.print("Queue is Full");
    }

    else if(front == -1)
    {
        front = 0;
        rear = 0;
        queue.add(rear, data);
    }

    else if(rear == size - 1 && front != 0)
    {
        rear = 0;
        queue.set(rear, data);
    }

    else
    {
        rear = (rear + 1);
    
        if(front <= rear)
        {
            queue.add(rear, data);
        }
    
        else
        {
            queue.set(rear, data);
        }
    }
}


public int deQueue()
{
    int temp;

    if(front == -1)
    {
        System.out.print("Queue is Empty");
        
        // Return -1 in case of empty queue
        return -1;
    }

    temp = queue.get(front);

    if(front == rear)
    {
        front = -1;
        rear = -1;
    }

    else if(front == size - 1)
    {
        front = 0;
    }
    else
    {
        front = front + 1;
    }
    
    // Returns the dequeued element
    return temp;
}

// Method to display the elements of queue
public void displayQueue()
{
    
    // Condition for empty queue.
    if(front == -1)
    {
        System.out.print("Queue is Empty");
        return;
    }


    System.out.print("Elements in the " +
                    "circular queue are: ");

    if(rear >= front)
    {
    
        for(int i = front; i <= rear; i++)
        {
            System.out.print(queue.get(i));
            System.out.print(" ");
        }
        System.out.println();
    }

    else
    {
        
        for(int i = front; i < size; i++)
        {
            System.out.print(queue.get(i));
            System.out.print(" ");
        }

        for(int i = 0; i <= rear; i++)
        {
            System.out.print(queue.get(i));
            System.out.print(" ");
        }
        System.out.println();
    }
}

public static void main(String[] args)
{

    CircularQueue q = new CircularQueue(5);
    
    q.enQueue(14);
    q.enQueue(22);
    q.enQueue(13);
    q.enQueue(-6);
    
    q.displayQueue();

    int x = q.deQueue();

    if(x != -1)
    {
        System.out.print("Deleted value = ");
        System.out.println(x);
    }

    x = q.deQueue();

    if(x != -1)
    {
        System.out.print("Deleted value = ");
        System.out.println(x);
    }

    q.displayQueue();
    
    q.enQueue(9);
    q.enQueue(20);
    q.enQueue(5);
    
    q.displayQueue();
    
    q.enQueue(20);
}
}
class CircularQueue():

    # constructor
    def __init__(self, size):
        self.size = size
        
        self.queue = [None for i in range(size)]
        self.front = self.rear = -1

    def enqueue(self, data):
        
        if ((self.rear + 1) % self.size == self.front):
            print(" Queue is Full\n")
            

        elif (self.front == -1):
            self.front = 0
            self.rear = 0
            self.queue[self.rear] = data
        else:
            
        
            self.rear = (self.rear + 1) % self.size
            self.queue[self.rear] = data
            
    def dequeue(self):
        if (self.front == -1): # condition for empty queue
            print ("Queue is Empty\n")
            

        elif (self.front == self.rear):
            temp=self.queue[self.front]
            self.front = -1
            self.rear = -1
            return temp
        else:
            temp = self.queue[self.front]
            self.front = (self.front + 1) % self.size
            return temp

    def display(self):
    

        if(self.front == -1):
            print ("Queue is Empty")

        elif (self.rear >= self.front):
            print("Elements in the circular queue are:",
                                            end = " ")
            for i in range(self.front, self.rear + 1):
                print(self.queue[i], end = " ")
            print ()

        else:
            print ("Elements in Circular Queue are:",
                                        end = " ")
            for i in range(self.front, self.size):
                print(self.queue[i], end = " ")
            for i in range(0, self.rear + 1):
                print(self.queue[i], end = " ")
            print ()

        if ((self.rear + 1) % self.size == self.front):
            print("Queue is Full")

ob = CircularQueue(5)
ob.enqueue(14)
ob.enqueue(22)
ob.enqueue(13)
ob.enqueue(-6)
ob.display()
print ("Deleted value = ", ob.dequeue())
print ("Deleted value = ", ob.dequeue())
ob.display()
ob.enqueue(9)
ob.enqueue(20)
ob.enqueue(5)
ob.display()

Time complexity: O(1)

Implementation of Circular Queue using Linked List

The address part of a linked list, a linear data structure that stores two parts—the data part and the address part—contains the node’s address is a linear data structure that stores two parts—the data part and the address part—contains the address of the node after it. Since the circular queue in this case is implemented using a linked list, the linked list complies with the Queue’s rules. Enqueue and dequeue operations take O(1) time when we implement a circular queue using a linked list.

Code Implementation:

#include <stdio.h>  
// Declaration of struct type node  
struct node  
{  
    int data;  
    struct node *next;  
};  
struct node *front=-1;  
struct node *rear=-1;  
// function to insert the element in the Queue  
void enqueue(int x)  
{  
    struct node *newnode;  // declaration of pointer of struct node type.  
    newnode=(struct node *)malloc(sizeof(struct node));  // allocating the memory to the newnode  
    newnode->data=x;  
    newnode->next=0;  
    if(rear==-1)  // checking whether the Queue is empty or not.  
    {  
        front=rear=newnode;  
        rear->next=front;  
    }  
    else  
    {  
        rear->next=newnode;  
        rear=newnode;  
        rear->next=front;  
    }  
}  
  
// function to delete the element from the queue  
void dequeue()  
{  
    struct node *temp;   // declaration of pointer of node type  
    temp=front;  
    if((front==-1)&&(rear==-1))  // checking whether the queue is empty or not  
    {  
        printf("\nQueue is empty");  
    }  
    else if(front==rear)  // checking whether the single element is left in the queue  
    {  
        front=rear=-1;  
        free(temp);  
    }  
    else  
    {  
        front=front->next;  
        rear->next=front;  
        free(temp);  
    }  
}  
  
// function to get the front of the queue  
int peek()  
{  
    if((front==-1) &&(rear==-1))  
    {  
        printf("\nQueue is empty");  
    }  
    else  
    {  
        printf("\nThe front element is %d", front->data);  
    }  
}  
  
// function to display all the elements of the queue  
void display()  
{  
    struct node *temp;  
    temp=front;  
    printf("\n The elements in a Queue are : ");  
    if((front==-1) && (rear==-1))  
    {  
        printf("Queue is empty");  
    }  
  
    else   
    {  
        while(temp->next!=front)  
        {  
            printf("%d,", temp->data);  
            temp=temp->next;  
        }  
        printf("%d", temp->data);  
    }  
}  
  
void main()  
{  
    enqueue(34);   
    enqueue(10);  
    enqueue(23);  
    display();   
    dequeue();   
    peek();  
}

Applications of Circular Queue in Data Structure

The circular Queue in data structure can be used in the following scenarios:

  • Memory Management: Memory management is provided by the circular queue. As we’ve just shown, memory is not managed particularly effectively in a linear queue. However, in the case of a circular queue, the memory is effectively managed by putting the elements in an empty space.
  • CPU Scheduling: The circular queue in data structure is another tool the operating system employs to insert and then run programs.
  • Traffic System: One of the best instances of a circular queue in a traffic management system controlled by computers is a traffic signal. After each interval of time, each traffic light turns on one at a time. Like when a red light comes on for a minute, followed by a yellow light for a minute, and then a green light. The red light turns on after the green light.

Conclusion
In this tutorial, you explored the circular queues in data structure. A circular queue in data structure resolves memory wastage drawback, which is faced in the implementation of a linear queue. You also went through the steps to implement primary circular queue operations.

Leave a Reply

Your email address will not be published. Required fields are marked *