Circular queue in Data Structures Theory - Time & Space Complexity
Analyzing time complexity helps us understand how fast operations run in a circular queue as it grows.
We want to know how the time to add or remove items changes when the queue size changes.
Analyze the time complexity of the enqueue and dequeue operations in a circular queue.
class CircularQueue:
def __init__(self, size):
self.queue = [None] * (size + 1)
self.head = 0
self.tail = 0
self.size = size + 1
def enqueue(self, item):
if (self.tail + 1) % self.size == self.head:
return False # Queue is full
self.queue[self.tail] = item
self.tail = (self.tail + 1) % self.size
return True
def dequeue(self):
if self.head == self.tail:
return None # Queue is empty
item = self.queue[self.head]
self.head = (self.head + 1) % self.size
return item
This code adds (enqueue) and removes (dequeue) items in a circular queue using fixed-size storage.
Look for loops or repeated steps inside enqueue and dequeue.
- Primary operation: Single-step index update and assignment.
- How many times: Each enqueue or dequeue runs once per call, no loops inside.
Each enqueue or dequeue does a fixed number of steps regardless of queue size.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 5-6 steps |
| 100 | 5-6 steps |
| 1000 | 5-6 steps |
Pattern observation: The number of steps stays the same no matter how big the queue is.
Time Complexity: O(1)
This means adding or removing an item takes the same short time no matter the queue size.
[X] Wrong: "Enqueue or dequeue takes longer as the queue grows because it has to move many items."
[OK] Correct: Circular queue uses fixed positions and index updates, so it never shifts items and always works in constant time.
Understanding constant time operations in circular queues shows you know how to efficiently manage fixed-size buffers, a useful skill in many real-world systems.
"What if we changed the circular queue to a dynamic array that resizes when full? How would the time complexity of enqueue change then?"
Practice
circular queue compared to a regular linear queue?Solution
Step 1: Understand the structure of a circular queue
A circular queue connects the last position back to the first, forming a circle.Step 2: Identify the advantage over a linear queue
This connection allows the queue to reuse spaces freed by dequeued elements without shifting.Final Answer:
It efficiently reuses empty space by connecting the end to the start. -> Option BQuick Check:
Circular queue = space reuse [OK]
- Thinking it sorts elements automatically
- Believing it stores multiple data types
- Assuming it shifts elements after dequeue
Solution
Step 1: Recall how circular queue pointers move
In a circular queue, pointers wrap around using modulo arithmetic to stay within bounds.Step 2: Apply modulo to update rear pointer
After enqueue, rear moves to (rear + 1) modulo the queue size to wrap if needed.Final Answer:
rear = (rear + 1) % size -> Option AQuick Check:
Rear update uses modulo [OK]
- Incrementing rear without modulo
- Decrementing rear after enqueue
- Using subtraction instead of modulo
front = 3 and rear = 1. Which of the following statements is true about the queue state?Solution
Step 1: Understand front and rear positions in circular queue
Front at 3 and rear at 1 means rear has wrapped around past front.Step 2: Calculate number of elements using formula
Number of elements = (rear - front + size) % size = (1 - 3 + 5) % 5 = 3 % 5 = 3.Final Answer:
The queue has 3 elements. -> Option CQuick Check:
Elements count = 3 [OK]
- Confusing full and empty conditions
- Ignoring modulo in calculation
- Assuming rear < front means empty
if front == -1:
print("Queue is empty")
else:
data = queue[front]
if front == rear:
front = rear = -1
else:
front = (front + 1) % size
Solution
Step 1: Analyze the dequeue operation steps
The code checks if queue is empty, retrieves data, updates pointers correctly.Step 2: Identify missing usage of dequeued data
Though data is assigned, it is neither returned nor used, so the operation loses the dequeued value.Final Answer:
The code does not return or use the dequeued data. -> Option AQuick Check:
Dequeue must return data [OK]
- Not returning dequeued value
- Incorrect pointer updates
- Incrementing rear on dequeue
front = 0 and rear = 4. You perform two dequeue operations followed by three enqueue operations. What will be the final positions of front and rear?Solution
Step 1: Update front after two dequeues
Each dequeue moves front by 1 modulo size: front = (0 + 2) % 6 = 2.Step 2: Update rear after three enqueues
Each enqueue moves rear by 1 modulo size: rear = (4 + 3) % 6 = 7 % 6 = 1.Final Answer:
front = 2, rear = 1 -> Option DQuick Check:
Front and rear updated with modulo [OK]
- Not using modulo for pointer wrap-around
- Mixing front and rear updates
- Forgetting to update pointers after each operation
Ready to prove it?
Pass the test and this pattern moves unknown
