Circular Queue

Introduction to Circular Queue

In the realm of data structures, queues play a fundamental role in managing data in a First-In-First-Out (FIFO) manner. Circular queue , also known as circular buffers or ring buffers, offer a unique solution for managing sequential data processing with limited resources. In this article, we delve into the intricacies of circular queues, exploring their definition, applications, characteristics, types, advantages, and disadvantages.

Circular Queue

What is Circular Queues

A circular queue is a linear data structure that follows the FIFO principle, where elements are inserted at the rear and removed from the front. Unlike traditional linear queues, circular queues have a fixed-size buffer and wrap-around behavior, allowing elements to be added and removed cyclically. Circular queues are commonly implemented using arrays or linked lists, offering efficient memory utilization and seamless data processing.

Why We Use Circular Queues in Programming

Circular queues are used in programming for several reasons:

  1. Efficient Memory Utilization: Circular queues utilize a fixed-size buffer, enabling efficient memory utilization and optimal storage of elements.
  2. Wrap-Around Behavior: Circular queues exhibit wrap-around behavior, allowing seamless cyclic processing of data without the need for expensive resizing operations.
  3. Real-time Applications: Circular queues are well-suited for real-time applications, such as data buffering, task scheduling, and event handling, where predictable and bounded response times are crucial.
  4. Resource-Constrained Environments: Circular queues are ideal for resource-constrained environments, such as embedded systems and microcontrollers, where memory and processing power are limited.

Characteristics of Circular Queues

  1. Fixed-Size Buffer: Circular queues have a fixed-size buffer, which remains constant throughout the lifetime of the queue.
  2. Wrap-Around Behavior: Circular queues exhibit wrap-around behavior, allowing elements to be added and removed cyclically without the need for resizing operations.
  3. Front and Rear Pointers: Circular queues maintain front and rear pointers to track the position of the first and last elements in the queue, respectively.
  4. Full and Empty Conditions: Circular queues have mechanisms to detect full and empty conditions, preventing overflow and underflow errors during enqueue and dequeue operations.
Circular Queue

Types of Circular Queues

  1. Array-based Circular Queues: An array-based implementation of circular queue, where elements are stored in a fixed-size array and wrap-around behavior is achieved using modular arithmetic.
  2. Linked List-based Circular Queues: A linked list-based implementation of circular queue, where elements are stored in dynamically allocated nodes and wrap-around behavior is achieved by connecting the last node to the first node.

Advantages of Circular Queue

  1. Efficient Memory Utilization: Circular queues utilize a fixed-size buffer, enabling efficient memory utilization and optimal storage of elements.
  2. Seamless Wrap-Around Behavior: Circular queues exhibit wrap-around behavior, allowing seamless cyclic processing of data without the need for expensive resizing operations.
  3. Real-time Processing: Circular queues are well-suited for real-time applications, providing predictable and bounded response times essential for critical systems.
  4. Reduced Overhead: Circular queues eliminate the need for resizing operations, reducing overhead and improving overall performance in resource-constrained environments.

Disadvantages of Circular Queues

  1. Fixed Size Limitation: Circular queues have a fixed-size buffer, limiting the maximum number of elements that can be stored in the queue at any given time.
  2. Implementation Complexity: Implementing circular queues requires careful handling of wrap-around behavior and pointer manipulation, which may increase the complexity of the code.
  3. Overhead in Dynamic Memory Allocation: In linked list-based implementations, dynamic memory allocation for each node may incur overhead, especially in resource-constrained environments with limited memory resources.

Code Examples of Circular Queues

Below are code examples demonstrating circular queue implementation in various programming languages:

Circular Queues in C#

using System;

class CircularQueue
{
    const int MAX_SIZE = 5;
    int[] queue = new int[MAX_SIZE];
    int front = -1, rear = -1;

    void Enqueue(int value)
    {
        if ((rear + 1) % MAX_SIZE == front)
        {
            Console.WriteLine("Queue is full");
            return;
        }
        if (front == -1)
        {
            front = 0;
        }
        rear = (rear + 1) % MAX_SIZE;
        queue[rear] = value;
    }

    int Dequeue()
    {
        if (front == -1)
        {
            Console.WriteLine("Queue is empty");
            return -1;
        }
        int value = queue[front];
        if (front == rear)
        {
            front = rear = -1;
        }
        else
        {
            front = (front + 1) % MAX_SIZE;
        }
        return value;
    }

    void Display()
    {
        if (front == -1)
        {
            Console.WriteLine("Queue is empty");
            return;
        }
        int i = front;
        Console.Write("Queue: ");
        do
        {
            Console.Write($"{queue[i]} ");
            i = (i + 1) % MAX_SIZE;
        } while (i != (rear + 1) % MAX_SIZE);
        Console.WriteLine();
    }

    static void Main(string[] args)
    {
        var queue = new CircularQueue();
        queue.Enqueue(1);
        queue.Enqueue(2);
        queue.Enqueue(3);
        queue.Display();
        Console.WriteLine($"Dequeued element: {queue.Dequeue()}");
        queue.Display();
    }
}

Output

Queue: 1 2 3
Dequeued element: 1
Queue: 2 3

Circular Queues in C

#include <stdio.h>

#define MAX_SIZE 5

int queue[MAX_SIZE];
int front = -1, rear = -1;

void enqueue(int value) {
    if ((rear + 1) % MAX_SIZE == front) {
        printf("Queue is full\n");
        return;
    }
    if (front == -1) {
        front = 0;
    }
    rear = (rear + 1) % MAX_SIZE;
    queue[rear] = value;
}

int dequeue() {
    if (front == -1) {
        printf("Queue is empty\n");
        return -1;
    }
    int value = queue[front];
    if (front == rear) {
        front = rear = -1;
    } else {
        front = (front + 1) % MAX_SIZE;
    }
    return value;
}

void display() {
    if (front == -1) {
        printf("Queue is empty\n");
        return;
    }
    int i = front;
    printf("Queue: ");
    do {
        printf("%d ", queue[i]);
        i = (i + 1) % MAX_SIZE;
    } while (i != (rear + 1) % MAX_SIZE);
    printf("\n");
}

int main() {
    enqueue(1);
    enqueue(2);
    enqueue(3);
    display();
    printf("Dequeued element: %d\n", dequeue());
    display();
    return 0;
}

Output

Queue: 1 2 3 
Dequeued element: 1
Queue: 2 3

Circular Queues in C++

#include <iostream>

#define MAX_SIZE 5

class CircularQueue {
private:
    int queue[MAX_SIZE];
    int front;
    int rear;

public:
    CircularQueue() : front(-1), rear(-1) {}

    void enqueue(int value) {
        if ((rear + 1) % MAX_SIZE == front) {
            std::cout << "Queue is full" << std::endl;
            return;
        }
        if (front == -1) {
            front = 0;
        }
        rear = (rear + 1) % MAX_SIZE;
        queue[rear] = value;
    }

    int dequeue() {
        if (front == -1) {
            std::cout << "Queue is empty" << std::endl;
            return -1;
        }
        int value = queue[front];
        if (front == rear) {
            front = rear = -1;
        } else {
            front = (front + 1) % MAX_SIZE;
        }
        return value;
    }

    void display() {
        if (front == -1) {
            std::cout << "Queue is empty" << std::endl;
            return;
        }
        int i = front;
        std::cout << "Queue: ";
        do {
            std::cout << queue[i] << " ";
            i = (i + 1) % MAX_SIZE;
        } while (i != (rear + 1) % MAX_SIZE);
        std::cout << std::endl;
    }
};

int main() {
    CircularQueue queue;
    queue.enqueue(1);
    queue.enqueue(2);
    queue.enqueue(3);
    queue.display();
    std::cout << "Dequeued element: " << queue.dequeue() << std::endl;
    queue.display();
    return 0;
}

Output

Queue: 1 2 3 
Dequeued element: 1
Queue: 2 3

Circular Queues in Python

class CircularQueue:
    def __init__(self, max_size):
        self.max_size = max_size
        self.queue = [None] * max_size
        self.front = self.rear = -1

    def enqueue(self, value):
        if (self.rear + 1) % self.max_size == self.front:
            print("Queue is full")
            return
        if self.front == -1:
            self.front = 0
        self.rear = (self.rear + 1) % self.max_size
        self.queue[self.rear] = value

    def dequeue(self):
        if self.front == -1:
            print("Queue is empty")
            return None
        value = self.queue[self.front]
        if self.front == self.rear:
            self.front = self.rear = -1
        else:
            self.front = (self.front + 1) % self.max_size
        return value

    def display(self):
        if self.front == -1:
            print("Queue is empty")
            return
        i = self.front
        print("Queue: ", end="")
        while True:
            print(self.queue[i], end=" ")
            if i == self.rear:
                break
            i = (i + 1) % self.max_size
        print()

queue = CircularQueue(5)
queue.enqueue(1)
queue.enqueue(2)
queue.enqueue(3)
queue.display()
print("Dequeued element:", queue.dequeue())
queue.display()

Output

Queue: 1 2 3 
Dequeued element: 1
Queue: 2 3

Circular Queues in PHP

<?php
class CircularQueue {
    const MAX_SIZE = 5;
    private $queue = array();
    private $front = -1;
    private $rear = -1;

    public function enqueue($value) {
        if (($this->rear + 1) % self::MAX_SIZE == $this->front) {
            echo "Queue is full\n";
            return;
        }
        if ($this->front == -1) {
            $this->front = 0;
        }
        $this->rear = ($this->rear + 1) % self::MAX_SIZE;
        $this->queue[$this->rear] = $value;
    }

    public function dequeue() {
        if ($this->front == -1) {
            echo "Queue is empty\n";
            return -1;
        }
        $value = $this->queue[$this->front];
        if ($this->front == $this->rear) {
            $this->front = $this->rear = -1;
        } else {
            $this->front = ($this->front + 1) % self::MAX_SIZE;
        }
        return $value;
    }

    public function display() {
        if ($this->front == -1) {
            echo "Queue is empty\n";
            return;
        }
        $i = $this->front;
        echo "Queue: ";
        do {
            echo $this->queue[$i] . " ";
            $i = ($i + 1) % self::MAX_SIZE;
        } while ($i != ($this->rear + 1) % self::MAX_SIZE);
        echo "\n";
    }
}

$queue = new CircularQueue();
$queue->enqueue(1);
$queue->enqueue(2);
$queue->enqueue(3);
$queue->display();
echo "Dequeued element: " . $queue->dequeue() . "\n";
$queue->display();
?>

Output

Queue: 1 2 3
Dequeued element: 1
Queue: 2 3

Circular Queues in JAVA

class CircularQueue {
    private static final int MAX_SIZE = 5;
    private int[] queue = new int[MAX_SIZE];
    private int front = -1, rear = -1;

    void enqueue(int value) {
        if ((rear + 1) % MAX_SIZE == front) {
            System.out.println("Queue is full");
            return;
        }
        if (front == -1) {
            front = 0;
        }
        rear = (rear + 1) % MAX_SIZE;
        queue[rear] = value;
    }

    int dequeue() {
        if (front == -1) {
            System.out.println("Queue is empty");
            return -1;
        }
        int value = queue[front];
        if (front == rear) {
            front = rear = -1;
        } else {
            front = (front + 1) % MAX_SIZE;
        }
        return value;
    }

    void display() {
        if (front == -1) {
            System.out.println("Queue is empty");
            return;
        }
        int i = front;
        System.out.print("Queue: ");
        do {
            System.out.print(queue[i] + " ");
            i = (i + 1) % MAX_SIZE;
        } while (i != (rear + 1) % MAX_SIZE);
        System.out.println();
    }

    public static void main(String[] args) {
        CircularQueue queue = new CircularQueue();
        queue.enqueue(1);
        queue.enqueue(2);
        queue.enqueue(3);
        queue.display();
        System.out.println("Dequeued element: " + queue.dequeue());
        queue.display();
    }
}

Output

Queue: 1 2 3
Dequeued element: 1
Queue: 2 3

Circular Queues in JavaScript

class CircularQueue {
    constructor() {
        this.MAX_SIZE = 5;
        this.queue = new Array(this.MAX_SIZE);
        this.front = -1;
        this.rear = -1;
    }

    enqueue(value) {
        if ((this.rear + 1) % this.MAX_SIZE === this.front) {
            console.log("Queue is full");
            return;
        }
        if (this.front === -1) {
            this.front = 0;
        }
        this.rear = (this.rear + 1) % this.MAX_SIZE;
        this.queue[this.rear] = value;
    }

    dequeue() {
        if (this.front === -1) {
            console.log("Queue is empty");
            return -1;
        }
        const value = this.queue[this.front];
        if (this.front === this.rear) {
            this.front = this.rear = -1;
        } else {
            this.front = (this.front + 1) % this.MAX_SIZE;
        }
        return value;
    }

    display() {
        if (this.front === -1) {
            console.log("Queue is empty");
            return;
        }
        let i = this.front;
        process.stdout.write("Queue: ");
        do {
            process.stdout.write(this.queue[i] + " ");
            i = (i + 1) % this.MAX_SIZE;
        } while (i !== (this.rear + 1) % this.MAX_SIZE);
        console.log();
    }
}

const queue = new CircularQueue();
queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
queue.display();
console.log("Dequeued element: " + queue.dequeue());
queue.display();

Output

Queue: 1 2 3
Dequeued element: 1
Queue: 2 3

These implementations demonstrate the functionality of the circular queue data structure in C#, PHP, Java, and JavaScript, with respective outputs for each language.

Conclusion

In conclusion, circular queues offer an efficient and versatile solution for managing sequential data processing with limited resources. By leveraging wrap-around behavior and a fixed-size buffer, circular queues provide seamless cyclic processing of data, making them suitable for real-time applications and resource-constrained environments. Despite some limitations such as fixed size and implementation complexity, the advantages of circular queues outweigh the disadvantages in many scenarios. By understanding the characteristics, advantages, and disadvantages of circular queues, programmers can harness the full potential of this powerful data structure to develop robust and scalable solutions, contributing to the advancement of technology and innovation in the digital age.

For more visit my website Codelikechamp.com

What is Data Structure

Types of data structure

what is Linked List

what is array

🤞 Don’t miss any latest posts!

Please subscribe by joining our community for free and stay updated!!!

IF YOU HAVE ALREADY SUBSCRIBED JUST CLOSE THIS FORM !

Leave a Comment

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

Scroll to Top