Stack

A stack is a LIFO (Last In, First Out) data structure. Elements are added and removed from the same end — the top. Think of a stack of plates: you always add or take from the top.

Interactive Visualization

stack = [
[3]
5
← TOP
[2]
88
[1]
17
[0]
42
] ← bottom
stack.peek() 5. Reads stack[top] without modifying the stack. O(1) — no removal
Push
O(1)
Pop
O(1)
Peek / isEmpty
O(1)

How it Works

  • LIFO discipline: The last element pushed is always the first to be popped. Only the top element is ever directly accessible.
  • Top pointer: A single integer top tracks where the next push writes and where pop reads from. Empty stack → top = −1.
  • All core operations O(1): Push, pop, and peek never iterate — they all work solely through the top pointer and a single array access.
  • Fixed vs dynamic: Fixed stacks raise StackOverflowError when full. Dynamic stacks (backed by a resizable array) reallocate — same amortised O(1) cost as dynamic arrays.

Memory Layout

// Stack backed by a 32-bit int array, base_addr = 0x2000
stack[0] = 42 → address: 0x2000
stack[1] = 17 → address: 0x2004
stack[2] = 88 → address: 0x2008
stack[3] = 5 → address: 0x200C ← TOP (top = 3)
top = 3 // pointer to the topmost element

Operations — Full Summary

OperationConditionComplexityNotes
push(x)Has free spaceO(1)Increment top, write x — two ops total
push(x)Full (fixed-size)O(1) then errorTop at bound → StackOverflowError; no write
push(x)Full (dynamic)O(n) once, O(1) amortisedRealloc: copy n elements then write
pop()Non-emptyO(1)Read top value, decrement top, return value
pop()Empty stackO(1) then errortop === −1 → StackUnderflowError; no change
peek() / top()Non-emptyO(1)Read stack[top], no pointer change
peek() / top()Empty stackO(1) then errorReturns error — nothing to read
isEmpty()AlwaysO(1)Returns top === −1
size()AlwaysO(1)Returns top + 1
search(x)AnyO(n)Not a core op — scan from top to bottom

Common Use Cases

Function Call Stack

Every function call pushes a frame; return pops it. Stack overflow = too many nested calls (e.g. infinite recursion).

Undo / Redo

Each action is pushed onto an undo stack. Ctrl+Z pops and reverses it; redo pushes onto a separate redo stack.

Expression Parsing

Compilers use stacks to evaluate expressions, match parentheses, and convert between infix, prefix, and postfix.

DFS / Backtracking

Depth-first search and recursive backtracking algorithms use an explicit stack (or the call stack) to track the path.

Browser History

Back button pops the current page off the history stack, revealing the previous one.

Syntax Checking

Validate that brackets, braces, and tags are properly nested by pushing opens and popping on closes.

When NOT to Use a Stack

  • You need to access elements by index — use an Array; stacks only expose the top.
  • FIFO ordering (queue behaviour) — use a Queue or Deque; stacks are LIFO only.
  • Searching by value — stack search is O(n) with no structural advantage. Use a Hash Set for O(1) average lookup.
  • Priority-based removal — use a Priority Queue / Heap; stacks have no concept of element priority.
  • Very deep recursion / huge datasets — fixed-size stacks overflow. Use iterative approaches with an explicit dynamic stack or increase the stack limit.