The Queue ADT
- Queue stores arbitrary objects using FIFO (first-in, first-out)
- Stack = LIFO
- Queue = FIFO
- Insertions at the rear, removals at the front
Operations:
enqueue(e)→ insert at reardequeue()→ remove + return from frontfirst()→ peek front (no removal)len()→ return number of elementsis_empty()→ return Boolean to indicate if queue is empty
Exceptions:
- Throws
EmptyQueueExceptionif dequeue/first on empty queue
Array-Based Implementation
Uses circular array of size with modulo arithmetic:
- Variables: (front index), (index past rear) is kept empty
Circular Arrays
- Shifting every item left when you dequeue → slow and inefficient
- Instead, just move the front (
f) pointer forward- When your
forrpointer hit the end of the array, they wrap back around to index 0
Operation Implementation:
size() = (N - f + r) mod Nenqueue: place atQ[r], thenr = (r + 1) mod Ndequeue: grabQ[f], thenf = (f + 1) mod N
Doubles capacity when full → amortized
Python Queue Implementation
Use of ArrayQueue class with three instance variables:
_data(the underlying list)_size(how many elements are in it)_front(index of the first element)
When the array is full → double capacity using the same doubling strategy as dynamic arrays seen in lecture 8
Note: no need for dedicated rear pointer, next available space is given by:
r = (self._front + self.size) % len(self._data)All operations are amortized
Round-Robin Scheduler
- Each process gets a turn, then re-joins the back of the queue:
e = Q.dequeue()- Service
e Q.enqueue(e)
- Each process gets a fair turn, cycling indefinitely