Back to Data Structures & Algorithms
2026-04-178 min read

Circular Queue (Data Structures & Algorithms)

Learn Circular Queue (Data Structures & Algorithms) step by step with clear examples and exercises.

Title: Circular Queue (Data Structures & Algorithms) Using Python Examples

Why This Matters

Circular queues are a crucial data structure in computer science, particularly for real-time systems, computer networks, and operating system design. They efficiently manage finite-size data sets by using a ring buffer, allowing elements to be added and removed cyclically without wasting space. Understanding circular queues can help you solve complex problems in competitive programming and interview scenarios.

Importance of Circular Queues

Circular queues are essential for handling data streams where the order of processing is important but the data size may exceed the available memory. They provide a more efficient solution than linear queues by minimizing the need for dynamic memory allocation and deallocation, reducing overhead and improving performance.

Prerequisites

To follow this tutorial, you should have a good understanding of the following topics:

  • Basic Python syntax (variables, data types, operators)
  • Control structures (loops, conditionals)
  • Functions and function definitions
  • Exception handling
  • Data structures (lists, tuples)
  • List slicing and manipulation
  • Understanding the concept of a queue data structure

Importance of Queue Data Structure

A queue is a fundamental linear data structure that follows the First-In-First-Out (FIFO) principle. It is widely used in various applications, such as operating system processes, network traffic management, and job scheduling.

Core Concept

A circular queue is a linear data structure that uses a ring buffer to simulate a queue. It has the following properties:

  1. Fixed capacity: The size of the buffer is fixed, and it cannot be changed during runtime.
  2. First and last pointers: The first pointer (head) points to the front element in the queue, while the last pointer (tail) indicates the next position where an element can be added.
  3. Wraparound: When the tail reaches the end of the buffer, it wraps around to the beginning, allowing elements to be added cyclically.
  4. Circular nature: The circular queue behaves as if it were a circle, with the first and last pointers meeting after a certain number of elements.

Here's an illustration of a circular queue with capacity 5:

!Circular Queue

In this example, the queue starts empty. As elements are added (enqueue), the tail moves clockwise, and when it reaches the end of the buffer, it wraps around to the beginning. When elements are removed (dequeue), the head moves counterclockwise.

Ring Buffer

A ring buffer is a data structure that provides a circular array with read and write pointers. It allows efficient handling of data streams by reusing memory once it has been processed, thus minimizing the need for dynamic memory allocation and deallocation.

Worked Example

Let's implement a circular queue in Python:

class CircularQueue:
def __init__(self, capacity):
self.capacity = capacity
self.queue = [None] * self.capacity
self.head = 0
self.tail = 0
self.size = 0

def is_full(self):
return (self.size == self.capacity)

def is_empty(self):
return (self.size == 0)

def enqueue(self, data):
if not self.is_full():
self.queue[self.tail] = data
self.tail += 1
self.size += 1
if self.tail == self.capacity:
self.tail = 0
else:
raise Exception("Circular Queue is full")

def dequeue(self):
if not self.is_empty():
data = self.queue[self.head]
self.head += 1
self.size -= 1
if self.head == self.capacity:
self.head = 0
return data
else:
raise Exception("Circular Queue is empty")

def print_queue(self):
if not self.is_empty():
for i in range(self.head, self.tail):
print(self.queue[i], end=" ")
if self.tail < self.head:
for i in range(self.head, self.capacity):
print(self.queue[i], end=" ")
print()

Test the circular queue implementation

cq = CircularQueue(5)

cq.enqueue(1)

cq.enqueue(2)

cq.enqueue(3)

cq.print_queue() # Output: 1 2 3

cq.enqueue(4)

cq.enqueue(5)

cq.print_queue() # Output: 1 2 3 4 5

cq.dequeue()

cq.print_queue() # Output: 2 3 4 5

cq.dequeue()

cq.dequeue()

cq.dequeue()

cq.dequeue()

cq.enqueue(6)

cq.enqueue(7)

cq.print_queue() # Output: 6 7 (wraparound occurs)

Common Mistakes

  1. Forgetting to handle the wraparound when adding elements to a circular queue can lead to overflow errors.
  2. Not checking for an empty queue before dequeuing can cause IndexError exceptions.
  3. Not checking for a full queue before enqueueing can also lead to IndexError exceptions or memory overflows.
  4. Implementing circular queues without using classes and methods can result in messy, hard-to-maintain code.
  5. Failing to initialize the head and tail pointers properly can cause incorrect behavior.
  6. When checking for a full queue, ensure that the last element added is not considered when calculating the size.
  7. When dequeuing, update the size of the queue before updating the head pointer.
  8. Not handling the case where the tail wraps around to the head and there are no elements in between (i.e., the queue is empty).
  9. Not considering the possibility of a single element in the circular queue when checking for an empty or full state.

Common Mistakes - Subheadings

  • Handling Wraparound Correctly
  • Checking for Empty and Full States
  • Proper Initialization of Head and Tail Pointers
  • Maintaining Efficient Code Structure

Practice Questions

  1. Implement a circular queue that supports multiple dequeues (removing elements from any position).
  2. Write a Python function to check if a given array is a valid representation of a circular queue.
  3. Implement a circular queue using doubly-linked lists instead of arrays.
  4. Given a circular queue and an element, write a function to find the index of that element in the queue (if it exists).
  5. Write a Python script to simulate a producer-consumer problem using a circular queue.
  6. Implement a method to check if a given element is present in the circular queue without dequeuing.
  7. Implement a method to find the first occurrence of an element in the circular queue (if it exists).
  8. Implement a method to find the last occurrence of an element in the circular queue (if it exists).
  9. Implement a method to remove all instances of a given element from the circular queue.
  10. Implement a method to sort the elements in the circular queue using an external sorting algorithm.

FAQ

What is the difference between a linear queue and a circular queue?

A linear queue has a fixed size, but when it reaches its capacity, new elements cannot be added without removing existing ones. In contrast, a circular queue wraps around to the beginning when it reaches the end, allowing new elements to be added even if the queue is full.

How can I implement a priority queue using a circular queue?

A priority queue can be implemented using a circular queue by maintaining an additional array to store the priorities of each element. When dequeuing, always pick the element with the highest priority.

Can I use a list instead of an array to create a circular queue in Python?

Yes, you can use a list as a dynamic array and implement circular queues using lists. However, Note that that this approach may not be as efficient as using a fixed-size array for certain operations like checking the capacity or handling wraparound.

Is there a way to optimize the circular queue implementation in Python?

One optimization could be to use a circular buffer instead of an array, which would reduce memory usage when the queue is nearly empty. Another approach is to use a sentinel value (e.g., -1) for the empty state, which avoids the need for separate checks for an empty and full queue.

How can I implement a circular buffer in Python?

A circular buffer can be implemented by setting the head and tail pointers to point to the same index when the queue is empty or nearly empty. When adding elements, increment the tail pointer, and when removing elements, increment the head pointer. If the tail pointer wraps around to the beginning and the head pointer has not yet caught up, set the head pointer to the new tail position.

How can I implement a method to check if a given element is present in the circular queue without dequeuing?

Create a helper function that calculates the index of the next occurrence of the given element by iterating through the circular queue starting from the current head position. If the element is found, return its index; otherwise, return None.

How can I implement a method to find the first occurrence of an element in the circular queue (if it exists)?

Create a helper function that calculates the index of the next occurrence of the given element by iterating through the circular queue starting from the current head position. If the element is found, return its index; otherwise, continue iterating until the end of the queue or the given element is found.

How can I implement a method to find the last occurrence of an element in the circular queue (if it exists)?

Create a helper function that calculates the index of the previous occurrence of the given element by iterating through the circular queue starting from the current tail position and moving towards the head. If the element is found, return its index; otherwise, continue iterating until the head or the given element is reached.

How can I implement a method to remove all instances of a given element from the circular queue?

Create a helper function that searches for the next occurrence of the given element and removes it by shifting elements forward in the circular queue. Repeat this process until no more instances of the given element are found.

How can I implement a method to sort the elements in the circular queue using an external sorting algorithm?

Create a helper function that copies the elements from the circular queue into a sorted list using an external sorting algorithm, such as merge sort or quicksort. Once the list is sorted, copy the elements back into the circular queue in sorted order.

Circular Queue (Data Structures & Algorithms) | Data Structures & Algorithms | XQA Learn