Queues

First In, First Out (FIFO)

CS205 Data Structures

Arrow keys to navigate

What is a Queue?

A queue is a collection with First-In, First-Out (FIFO) access.

  • Elements added at the rear (back)
  • Elements removed from the front
  • No access to elements in the middle

Analogy: Coffee Shop Line

First person in line is served first. New arrivals join the back. No cutting!

Key Idea

FIFO = the element waiting the longest gets served first. Fair and orderly!

Interactive Queue

The Queue ADT

Core Operations

OperationDescriptionTime
enqueue(e)Insert at rearO(1)
dequeue()Remove & return frontO(1)
front()Return front (no remove)O(1)
isEmpty()Is the queue empty?O(1)
size()Number of elementsO(1)

Key Idea

All core operations are O(1) — constant time regardless of queue size.

Java Interface

public interface Queue<E> {
/** Insert element at the rear. */
void enqueue(E element);
/** Remove and return front element. */
E dequeue();
/** Return front without removing. */
E front();
int size();
boolean isEmpty();
}

Enqueue & Dequeue

Add at the rear, remove from the front — synced with code

Enqueue Code

public void enqueue(E element) {
if (size == data.length)
throw new IllegalStateException();
data[rear] = element;
rear = (rear + 1) % data.length;
size++;
}

Dequeue Code

public E dequeue() {
if (isEmpty()) throw ...;
E result = data[front];
data[front] = null;
front = (front + 1) % data.length;
size--;
return result;
}

Array Visualization

Stack vs Queue

Stack — LIFO

Last In, First Out

Insertpush(e)
Removepop()
Peektop()

Queue — FIFO

First In, First Out

Insertenqueue(e)
Removedequeue()
Peekfront()

Key Difference

Both are restricted-access. Stack: insert & remove from same end. Queue: insert & remove from opposite ends.

Array-Based Queue (Naive Approach)

Why simple arrays fail for queues

The Problem: Dequeue Shifts O(n)

If we dequeue from index 0, we must shift everything left.

O(n) Dequeue!

Every dequeue shifts all remaining elements one position left. For n elements, that's O(n) work per dequeue.

Solution: don't shift — just move the front pointer. But then we waste space... unless we wrap around!

Array Visualization

Circular Array Implementation

Wrap around using modulo — no wasted space, no shifting!

The Magic Formula

Advance front: f = (f + 1) % N
Advance rear: r = (r + 1) % N

Modulo Wraps Around

If N = 8 and rear = 7:
(7 + 1) % 8 = 0
The index wraps back to the beginning! Array treated as a ring.

Circular Ring View

Circular Array: Step-by-Step Trace

Trace operations on capacity N=5 — watch front & rear wrap around

Circular Array: Full vs Empty

When front == rear, is it empty or full?

The Ambiguity

EMPTY: front == rear == 0

Solution 1: Size Counter

// Maintain a separate size field
isEmpty(): return size == 0
isFull(): return size == N
// Cleanest approach!

Solution 2: Waste One Slot

// Max capacity = N - 1
isFull(): return (rear+1) % N == front
// One slot always empty

Classic Bug

Without either solution, you cannot distinguish full from empty. Both have front == rear.

Linked-List-Based Queue

Head for dequeue, tail for enqueue — both O(1)

How would you implement enqueue and dequeue with a linked list?

Hint: Which end for enqueue? Which for dequeue? Why?

Node Diagram

Why head AND tail?

head for O(1) dequeue. tail for O(1) enqueue. Without tail, enqueue traverses the whole list — O(n)!

Deque (Double-Ended Queue)

Pronounced "deck" — insert & remove at both ends

Operations

OperationDescription
addFirst(e)Insert at front
addLast(e)Insert at rear
removeFirst()Remove from front
removeLast()Remove from rear

Deque Subsumes Both

  • Stack = addFirst + removeFirst
  • Queue = addLast + removeFirst

Java: ArrayDeque and LinkedList both implement Deque.

Interactive Deque

Application: Print Job Queue

A shared printer processes jobs fairly — FIFO

Submit Print Jobs

Why a Queue?

Fairness: first come, first served. No starvation — every job eventually prints.

Printer Queue

Application: BFS (Breadth-First Search)

A queue drives level-by-level traversal

BFS Algorithm

queue.enqueue(start);
while (!queue.isEmpty()) {
node = queue.dequeue();
visit(node);
for (child : node.children)
queue.enqueue(child);
}
Queue: []
Visited:

Tree

Application: Hot Potato / Josephus Problem

Pass the potato k times, eliminate the holder. Last one wins!

Algorithm

while (queue.size() > 1) {
for (i = 1 to k)
queue.enqueue(queue.dequeue());
eliminated = queue.dequeue();
}
return queue.dequeue(); // winner

Players Circle

Priority Queue Preview

What if some elements are more urgent?

Regular Queue (FIFO)

Arrival order determines service.

Priority Queue

Priority determines service — NOT FIFO.

Key Idea

A Priority Queue is NOT a queue. The element with the highest priority (often minimum key) is removed first, regardless of arrival order.

Real-World Examples

  • Emergency Room — critical patients first
  • OS Scheduling — high-priority processes preempt others
  • Dijkstra's Algorithm — expand nearest unvisited node

Analogy

Regular queue = deli counter with numbered tickets.
Priority queue = ER triage: sickest patient goes first, even if they just walked in.

Coming up: heaps — the efficient way to implement priority queues!

Common Pitfalls

Mistakes to avoid when working with queues

1. Forgetting Wrap-Around

Writing rear++ instead of rear = (rear+1) % NArrayIndexOutOfBounds!

// WRONG
rear++;
// CORRECT
rear = (rear + 1) % data.length;

2. Dequeuing When Empty

Always check isEmpty() before dequeue().

// WRONG
E item = queue.dequeue();
// CORRECT
if (!queue.isEmpty())
E item = queue.dequeue();

3. Confusing Front & Rear

Enqueue → rear. Dequeue → front. Mixing them up gives stack-like behavior.

4. Full vs Empty Confusion

Without a size counter, front==rear is ambiguous. Always use a count or waste-one-slot.

5. Forgetting to Null

After dequeue, set data[front] = null to avoid memory leaks (loitering references prevent GC).

E result = data[front];
data[front] = null; // help GC!

Summary & Cheat Sheet

Queue at a Glance

PropertyValue
Access PolicyFIFO
enqueueO(1)
dequeueO(1)
front / peekO(1)
isEmpty / sizeO(1)

Implementations

Circular ArrayLinked List
enqueueO(1) amortizedO(1)
dequeueO(1)O(1)
MemoryCompact, cache-friendlyPointer overhead
ResizeO(n) when fullNever needed

Key Formulas (Circular Array)

Advance front: f = (f + 1) % N
Advance rear: r = (r + 1) % N
Is empty: size == 0
Is full: size == N

Queue Family

Applications

  • BFS — level-order traversal
  • Print spooling — fair job scheduling
  • Hot Potato — circular elimination
  • Buffering — producer-consumer
  • OS scheduling — round-robin CPU

Challenge A: Circular Array Trace

Capacity N=4, starting with front=0, rear=0. After: enqueue(A), enqueue(B), dequeue(), enqueue(C), enqueue(D), enqueue(E) — what are front and rear?

Work it out:

  1. enqueue(A): data[0]=A, rear=1, size=1
  2. enqueue(B): data[1]=B, rear=2, size=2
  3. dequeue()→A: front=1, size=1
  4. enqueue(C): data[2]=C, rear=3, size=2
  5. enqueue(D): data[3]=D, rear=?, size=3
  6. enqueue(E): data[?]=E, rear=?, size=4

Challenge B: Fix the Bug

This linked-list dequeue has a bug. Find it!

Buggy Code

public E dequeue() {
if (isEmpty())
throw new NoSuchElementException();
E result = head.data;
head = head.next;
size--;
return result;
}

Bug: after dequeuing the last element, tail still points to the removed node. Next enqueue appends to a ghost!

What's missing?

Think About It

The code correctly advances head and decrements size. But what about tail? When does tail need updating during a dequeue?

Challenge C: FIFO vs LIFO

You enqueue 1, 2, 3, 4, 5 into a queue, then dequeue all. What's the output?

Operations:

queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
queue.enqueue(4);
queue.enqueue(5);
while (!queue.isEmpty())
print(queue.dequeue());

Think: FIFO

First In, First Out. Which element was enqueued first? That one comes out first when you dequeue.

Bonus: If this were a stack instead, the output would be the reverse: 5, 4, 3, 2, 1 (LIFO).

Quiz: Queue Fundamentals

3 quick questions

Q1: What does FIFO stand for?

Q2: In a circular array of size 8, if rear=7, what is rear after enqueue?

Q3: Which pointer does a linked-list queue need for O(1) enqueue?

Challenge: BFS Visit Order

What order does BFS visit this tree?

Tree:

Starting from node 1, children are visited left-to-right.

Challenge: Predict the Winner

Players: [A, B, C, D], k=2. Who wins?

Trace it yourself:

Start: queue = [A, B, C, D]
Each round: pass k=2 times (dequeue+re-enqueue), then eliminate.

Hint

Dequeue+re-enqueue k times = rotate the queue k positions. Then the front person is eliminated. Trace carefully!