Imagine a line at an ice cream cart. Each new customer joins at the back, while the customer at the front is served next. A queue works the same way: `enqueue(value)` adds a value at the rear, and `dequeue()` removes the value at the front. Adding at one end and removing from the other preserves first-in, first-out (FIFO) order. section 9.3 section 9.18
Enqueue describes what the queue must do, not how its elements must be stored. A linked-list queue can add at the tail; a circular-array queue writes into an available array cell. In either case, a new element goes behind those already waiting. section 9.3 section 9.6 section 9.11
For a fixed-capacity circular-array queue, enqueuing follows a short sequence:
- Check whether the queue is full. If it is, reject the insertion. section 9.11
- Write the value at `rear`, the index of the next available cell. section 9.10 section 9.11
- Advance `rear`, wrapping back to index 0 after the last cell, then increase `size`. Tracking size also distinguishes an empty queue from a full one when `front` and `rear` match. section 9.10 section 9.11
def enqueue(self, value):
if self.is_full():
raise ValueError('The queue is already full!')
self._data[self._rear] = value
self._rear = (self._rear + 1) % self._max_size
self._size += 1
The Python method puts those steps together. The modulo expression keeps `rear` within the array bounds, including when an insertion reaches the last cell. section 9.11
Storage choice matters when planning for growth. A linked-list queue can grow without a fixed capacity, and its enqueue operation takes O(1) worst-case time. A fixed-capacity circular array reuses cells freed by dequeue, but enqueue must fail once every cell is occupied. Expanding an array-backed circular queue is possible, though resizing requires realigning the stored elements and complicates the implementation. section 9.18 section 9.13
