Stacks and Queues
Stacks and queues are linear ADTs that restrict how elements are added and removed. Their constraints make them the right tool for a specific class of problems.
Stack
A stack is a LIFO (Last In First Out) data structure. The element most recently added is the first to be removed.
Operations:
push(x): add element to top. $O(1)$.pop(): remove and return top element. $O(1)$.peek() / top(): return top element without removing. $O(1)$.isEmpty(): return true if empty. $O(1)$.
Implementations:
- Array: maintain a top index.
push= increment and assign;pop= return and decrement. - Linked list: push/pop at head. $O(1)$ both.
Applications
Function call stack: the OS/runtime maintains a call stack. Each function call pushes a frame; return pops it. Stack overflow = too many nested calls.
Expression evaluation and parsing:
- Balanced parentheses check.
- Infix-to-postfix conversion (shunting-yard algorithm).
- Postfix expression evaluation.
Depth-First Search (DFS): iterative DFS uses an explicit stack instead of recursion.
Undo/redo: push operations onto a stack; undo pops and reverses.
Monotonic stack: a stack maintaining a monotone (increasing or decreasing) sequence. Used to find next greater element, largest rectangle in histogram, daily temperatures.
Monotonic Stack: Next Greater Element
For each element, find the next greater element to its right.
def next_greater(arr):
n = len(arr)
result = [-1] * n
stack = [] # indices; stack[bottom] to stack[top] = decreasing values
for i in range(n):
while stack and arr[stack[-1]] < arr[i]:
idx = stack.pop()
result[idx] = arr[i]
stack.append(i)
return result
Time: $O(n)$. Each element is pushed and popped at most once.
Queue
A queue is a FIFO (First In First Out) data structure. The element added first is the first to be removed.
Operations:
enqueue(x): add to the rear. $O(1)$.dequeue(): remove from the front. $O(1)$.peek() / front(): inspect front without removing. $O(1)$.isEmpty(): $O(1)$.
Implementations:
- Circular array: use
headandtailindices wrapping modulo capacity. Efficient fixed-size queue. - Linked list: enqueue at tail, dequeue from head. $O(1)$ both. Python’s
collections.deque. - Two stacks: one for enqueue, one for dequeue. Amortized $O(1)$ per operation.
Two-Stack Queue
class Queue:
def __init__(self):
self.inbox = []
self.outbox = []
def enqueue(self, x):
self.inbox.append(x)
def dequeue(self):
if not self.outbox:
while self.inbox:
self.outbox.append(self.inbox.pop())
return self.outbox.pop()
Each element is moved at most once: $O(1)$ amortized.
Applications
Breadth-First Search (BFS): use a queue to process nodes level by level.
Level-order tree traversal: enqueue root; for each dequeued node, enqueue its children.
Producer-consumer: a queue buffers work between threads.
Sliding window maximum: maintain a deque of candidate maximum indices.
Deque (Double-Ended Queue)
Supports insertion and removal at both ends in $O(1)$.
Python: collections.deque. C++: std::deque. Java: ArrayDeque.
Sliding window maximum (monotonic deque):
Maintain a deque of indices; the front holds the index of the maximum in the current window.
from collections import deque
def max_sliding_window(arr, k):
dq = deque()
result = []
for i, x in enumerate(arr):
# Remove elements outside the window
while dq and dq[0] < i - k + 1:
dq.popleft()
# Remove elements smaller than x (they can't be max)
while dq and arr[dq[-1]] < x:
dq.pop()
dq.append(i)
if i >= k - 1:
result.append(arr[dq[0]])
return result
Time: $O(n)$.
Priority Queue (Heap)
Not strictly a stack or queue, but a close relative. Elements are dequeued in priority order (smallest or largest first) rather than insertion order.
heapq (Python): min-heap. heappush, heappop. $O(\log n)$.
Applications: Dijkstra’s algorithm, task scheduling, median maintenance, top-$k$ elements.
Stack vs. Queue Summary
| Property | Stack (LIFO) | Queue (FIFO) |
|---|---|---|
| Insert | push (top) | enqueue (rear) |
| Remove | pop (top) | dequeue (front) |
| Peek | top | front |
| Use: DFS | Yes | No |
| Use: BFS | No | Yes |
| Use: Undo | Yes | No |
| Use: Scheduling | No | Yes |