Introduction

A Circular Queue is a linear data structure that follows the FIFO (First In, First Out) principle but connects the end of the queue back to the front, forming a circle. Unlike a regular queue, when the rear reaches the end of the array, it wraps around to the beginning (if space is available). This prevents wasted space and makes queue operations more efficient.

What Is a Circular Queue?

A Circular Queue is an enhanced version of a linear queue that efficiently utilizes space. In a linear queue, once the queue becomes full and elements are dequeued, the empty spaces at the beginning remain unused. The circular queue solves this problem by connecting the rear to the front.

Real-World Example

Think of a Ferris wheel — as each cabin goes off the top, it comes back around to the bottom for reuse. Similarly, in a circular queue, positions are reused when elements are removed.

Key Concepts

Important Conditions:

Steps to Implement a Circular Queue

1. Define the Queue Class

Create a class CircularQueue with required variables.

C#
using System;

public class CircularQueue
{
    private int[] queue;
    private int front;
    private int rear;
    private int maxSize;

    public CircularQueue(int size)
    {
        queue = new int[size];
        maxSize = size;
        front = -1;
        rear = -1;
    }
}

2. Enqueue Operation (Insert Element)

C#
public void Enqueue(int item)
{
    if ((rear + 1) % maxSize == front)
    {
        Console.WriteLine("Queue is full. Cannot insert.");
        return;
    }

    if (front == -1) // Queue is empty
        front = 0;

    rear = (rear + 1) % maxSize;
    queue[rear] = item;

    Console.WriteLine($"Inserted {item} into the queue.");
}

3. Dequeue Operation (Remove Element)

C#
public int Dequeue()
{
    if (front == -1)
    {
        Console.WriteLine("Queue is empty. Nothing to dequeue.");
        return -1;
    }

    int item = queue[front];

    if (front == rear)
    {
        front = rear = -1; // Queue becomes empty
    }
    else
    {
        front = (front + 1) % maxSize;
    }

    Console.WriteLine($"Removed {item} from the queue.");
    return item;
}

4. Display Queue Elements

C#
public void Display()
{
    if (front == -1)
    {
        Console.WriteLine("Queue is empty.");
        return;
    }

    Console.WriteLine("Queue elements are:");
    int i = front;
    while (true)
    {
        Console.Write(queue[i] + " ");
        if (i == rear)
            break;
        i = (i + 1) % maxSize;
    }
    Console.WriteLine();
}

5. Full Working Example

C#
class Program
{
    static void Main()
    {
        CircularQueue cq = new CircularQueue(5);

        cq.Enqueue(10);
        cq.Enqueue(20);
        cq.Enqueue(30);
        cq.Enqueue(40);

        cq.Display();

        cq.Dequeue();
        cq.Display();

        cq.Enqueue(50);
        cq.Enqueue(60); // Wrap-around insertion

        cq.Display();
    }
}

Output:

Code
Inserted 10 into the queue.
Inserted 20 into the queue.
Inserted 30 into the queue.
Inserted 40 into the queue.
Queue elements are:
10 20 30 40
Removed 10 from the queue.
Queue elements are:
20 30 40
Inserted 50 into the queue.
Inserted 60 into the queue.
Queue elements are:
20 30 40 50 60

Advantages of Circular Queue

Limitations

Real-World Use Cases

Summary

A Circular Queue in C# efficiently utilizes space by connecting the end of the queue to the front, allowing elements to wrap around. Using simple arithmetic with modulo %, you can manage front and rear pointers effectively. By implementing operations like enqueue, dequeue, and display, you can manage data efficiently for scheduling, buffering, and real-time data applications.