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
Front: Points to the first element in the queue.
Rear: Points to the last element in the queue.
MaxSize: The total capacity of the queue.
Wrap-around: When the rear moves to the start after reaching the end.
Important Conditions:
Steps to Implement a Circular Queue
1. Define the Queue Class
Create a class CircularQueue with required variables.
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)
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)
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
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
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:
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
Efficient use of memory — no wasted space.
Prevents overflow if elements are removed and space becomes available.
Simplifies resource scheduling tasks (like CPU scheduling or buffering).
Limitations
Real-World Use Cases
CPU Scheduling (Round Robin Algorithm)
Memory Buffers (Circular Buffers)
Streaming Services (Handling Continuous Data)
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.