A circular queue is a linear data structure that operates in a circular fashion. Unlike a normal queue where the rear pointer moves only in one direction, in a circular queue, the rear pointer wraps around when it reaches the end of the array, making it circular. This helps in efficiently utilizing the memory space.

Program Explanation

The circular queue is implemented using an array with two pointers, front and rear:

  • front: Points to the first element in the queue.
  • rear: Points to the last element in the queue.

The circular nature is maintained by adjusting the front and rear pointers with modulo arithmetic to wrap around when they reach the end of the array.

C Program Code


#include <stdio.h>
#include <stdlib.h>

#define MAX 5  // Define the maximum size of the circular queue

// Circular Queue structure
struct CircularQueue {
    int arr[MAX];
    int front, rear;
};

// Initialize the circular queue
void initQueue(struct CircularQueue *q) {
    q->front = -1;
    q->rear = -1;
}

// Check if the queue is full
int isFull(struct CircularQueue *q) {
    return ((q->rear + 1) % MAX == q->front);
}

// Check if the queue is empty
int isEmpty(struct CircularQueue *q) {
    return (q->front == -1);
}

// Add an element to the circular queue
void enqueue(struct CircularQueue *q, int value) {
    if (isFull(q)) {
        printf("Queue is full. Cannot enqueue %d.\n", value);
        return;
    }
    
    if (isEmpty(q)) {
        q->front = 0;
    }
    
    q->rear = (q->rear + 1) % MAX;
    q->arr[q->rear] = value;
    printf("Enqueued %d\n", value);
}

// Remove an element from the circular queue
int dequeue(struct CircularQueue *q) {
    if (isEmpty(q)) {
        printf("Queue is empty. Cannot dequeue.\n");
        return -1;
    }
    
    int dequeuedValue = q->arr[q->front];
    
    if (q->front == q->rear) {
        // The queue becomes empty after this operation
        q->front = -1;
        q->rear = -1;
    } else {
        q->front = (q->front + 1) % MAX;
    }
    
    printf("Dequeued %d\n", dequeuedValue);
    return dequeuedValue;
}

// Display the elements of the circular queue
void displayQueue(struct CircularQueue *q) {
    if (isEmpty(q)) {
        printf("Queue is empty.\n");
        return;
    }

    printf("Queue elements: ");
    int i = q->front;
    while (i != q->rear) {
        printf("%d ", q->arr[i]);
        i = (i + 1) % MAX;
    }
    printf("%d\n", q->arr[q->rear]);  // Print the last element
}

// Main driver function
int main() {
    struct CircularQueue q;
    initQueue(&q);
    
    enqueue(&q, 10);  // Enqueue 10
    enqueue(&q, 20);  // Enqueue 20
    enqueue(&q, 30);  // Enqueue 30
    enqueue(&q, 40);  // Enqueue 40
    enqueue(&q, 50);  // Enqueue 50 (queue is full now)
    
    displayQueue(&q);  // Display the queue
    
    dequeue(&q);  // Dequeue an element
    dequeue(&q);  // Dequeue another element
    
    displayQueue(&q);  // Display the queue again
    
    enqueue(&q, 60);  // Enqueue 60 (wrap around occurs)
    enqueue(&q, 70);  // Enqueue 70 (queue is full again)
    
    displayQueue(&q);  // Display the queue after wrap around
    
    return 0;
}
    

Code Explanation

1. Circular Queue Structure: The queue is represented as an array of fixed size (MAX) and two pointers: front and rear. These pointers are used to keep track of the first and last elements of the queue.

2. Basic Queue Operations:

  • enqueue(): Adds an element to the queue. If the queue is full (when (rear + 1) % MAX == front), no more elements can be added. The rear pointer is updated using modulo arithmetic to ensure circular movement.
  • dequeue(): Removes an element from the front of the queue. If the queue becomes empty after a dequeue operation, both front and rear are set to -1.
  • isFull() and isEmpty(): Check if the queue is full or empty, respectively.
  • displayQueue(): Displays the current elements in the queue from front to rear.

Sample Output


Enqueued 10
Enqueued 20
Enqueued 30
Enqueued 40
Enqueued 50
Queue elements: 10 20 30 40 50
Dequeued 10
Dequeued 20
Queue elements: 30 40 50
Enqueued 60
Enqueued 70
Queue elements: 30 40 50 60 70
    

Conclusion

This program demonstrates the implementation of a circular queue in C using an array. The use of modulo arithmetic ensures that the queue behaves in a circular manner, allowing efficient use of space even after dequeuing elements. Circular queues are widely used in situations where buffer management is needed, such as in operating systems, network buffering, and real-time processing systems.

 

By Aditya Bhuyan

I work as a cloud specialist. In addition to being an architect and SRE specialist, I work as a cloud engineer and developer. I have assisted my clients in converting their antiquated programmes into contemporary microservices that operate on various cloud computing platforms such as AWS, GCP, Azure, or VMware Tanzu, as well as orchestration systems such as Docker Swarm or Kubernetes. For over twenty years, I have been employed in the IT sector as a Java developer, J2EE architect, scrum master, and instructor. I write about Cloud Native and Cloud often. Bangalore, India is where my family and I call home. I maintain my physical and mental fitness by doing a lot of yoga and meditation.

Leave a Reply

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

error

Enjoy this blog? Please spread the word :)