Topics
When we enqueue
(add an element), we add it at the rear and increment the rear pointer. But if we reach the end of our array while enqueueing, instead of declaring an Overflow, we wrap around and continue from the front of the array, as long as there is space.
Similarly, when we dequeue
(remove an element), we remove it from the front and increment the front pointer. But if we reach the end of the array while dequeuing, we wrap around and continue from the start of the array.
Tip
Keep in mind, we always add items to the rear and remove them from the front
class CircularQueue:
def __init__(self, capacity: int):
"""
Initialize the circular queue with a given capacity.
:param capacity: Maximum number of elements the queue can hold
"""
if capacity <= 0:
raise ValueError("Queue capacity must be a positive integer")
self._max_size = capacity
self._elements = [None] * capacity
self._reset_queue()
def _reset_queue(self):
"""
Reset the queue to its initial empty state.
"""
self._head_index = -1
self._tail_index = -1
self._current_size = 0
def enqueue(self, value: int) -> bool:
"""
Add an element to the queue.
:param value: Element to be added
:return: True if successful, False if queue is full
"""
if self.is_full():
return False
if self.is_empty():
# First element case
self._head_index = self._tail_index = 0
else:
# Move tail to next position circularly
self._tail_index = (self._tail_index + 1) % self._max_size
# Add the element
self._elements[self._tail_index] = value
self._current_size += 1
return True
def dequeue(self) -> bool:
"""
Remove the front element from the queue.
:return: True if successful, False if queue is empty
"""
if self.is_empty():
return False
if self._current_size == 1:
# Last element being removed
self._reset_queue()
else:
# Move head to next position circularly
self._head_index = (self._head_index + 1) % self._max_size
self._current_size -= 1
return True
def get_front(self) -> int:
return -1 if self.is_empty() else self._elements[self._head_index]
def get_rear(self) -> int:
return -1 if self.is_empty() else self._elements[self._tail_index]
def is_empty(self) -> bool:
return self._current_size == 0
def is_full(self) -> bool:
return self._current_size == self._max_size
def size(self) -> int:
return self._current_size