Stack (LIFO)

Stack (LIFO)

Press Enter to run

TOP
17
10
28
17
18
26
[0]
[1]
[2]
[3]
[4]
[5]
6
Step 0 of 0
Speed:
Ready — press Enter to run

Stack (LIFO) Visualization — Step by Step

Last In, First Out data structure. Push adds to the top, pop removes from the top.

Data StructuresbeginnerUpdated

// quick answer

Stack (LIFO) is a data structures structure that runs in O(1) time on average with O(n) space. Last In, First Out data structure. Push adds to the top, pop removes from the top.

How Stack (LIFO) Works

A Stack is a linear data structure that follows LIFO (Last In, First Out) ordering. The last element pushed is the first to be popped. Common uses include function call stacks, undo operations, expression evaluation, and DFS traversal. O(1) push, pop, and peek.

Stack (LIFO) Step by Step

One open end

A stack is a list you are only allowed to touch at one end, called the top. That single restriction creates the LIFO invariant: whatever went in last must come out first, because it is sitting on top of everything else. Picture a stack of plates — you add to the top and take from the top, and the plate at the bottom stays put until every plate above it is gone. Internally all you need is a container plus a top pointer (or, with an array backing, just the array length), which is why every stack operation runs in O(1).

Push and pop, traced

Start empty and push(5), push(2), push(8). The stack is now [5, 2, 8] with 8 on top — index 2 in the visualizer. Call pop() and you get 8 back, not 5: last in, first out. Pop again and you get 2, leaving [5]. Notice that pop both *returns* the top value and *removes* it — the two are one atomic operation. The demo in the visualizer above runs the full lifecycle: it pushes every value, then pops until the stack is empty, so you can watch the exit order exactly mirror the entry order.

Peek and underflow

Sometimes you want to look without touching. peek() (also called *top*) returns the top element but leaves the stack unchanged — useful when the next action depends on what is on top, like checking whether the operator on the stack has higher precedence before deciding to pop it. The failure mode to guard against is underflow: calling pop or peek on an empty stack. Real implementations either throw an error or return a sentinel like undefined; either way, checking isEmpty() first is the idiom. There is no way to read the bottom or middle without popping everything above it — that is the contract.

The call stack: the stack you use every day

Every running program uses a stack constantly. When a function is called, the runtime pushes a frame holding its local variables and return address; when the function returns, that frame is popped and execution resumes underneath. Nested calls stack up frames; recursion stacks up one frame per level. This is why unbounded recursion crashes with a *stack overflow* — the frames exhaust the memory reserved for the call stack — and why a recursive algorithm can always be rewritten iteratively by managing an explicit stack yourself.

Where stacks show up

Stacks appear anywhere the most recent thing matters most. Undo history pushes each edit and pops to revert. The browser back button pops the page you most recently visited. Compilers evaluate expressions and match brackets with stacks: push every (, pop on every ), and a clean empty stack at the end means the string is balanced. And depth-first search is literally "graph traversal with a stack" — replace the stack with a queue and the exact same code becomes breadth-first search.

Time & Space Complexity

Best CaseAverage CaseWorst CaseSpace
O(1)O(1)O(1)O(n)

Stack (LIFO) Pseudocode

Stack operations:
  push(value):
    add value to top
  pop():
    remove and return top
  peek():
    return top without removing

Press play in the visualizer above to watch each line execute with live highlighting.

Stack (LIFO)Code in JavaScript, Python & Java

JavaScript

class Stack {
  #items = [];

  push(value) {
    this.#items.push(value);
  }

  pop() {
    if (this.isEmpty()) throw new Error('Stack underflow');
    return this.#items.pop();
  }

  peek() {
    return this.#items[this.#items.length - 1];
  }

  isEmpty() {
    return this.#items.length === 0;
  }

  get size() {
    return this.#items.length;
  }
}

Python

class Stack:
    def __init__(self):
        self._items = []

    def push(self, value):
        self._items.append(value)

    def pop(self):
        if self.is_empty():
            raise IndexError("stack underflow")
        return self._items.pop()

    def peek(self):
        return self._items[-1] if self._items else None

    def is_empty(self):
        return len(self._items) == 0

    def __len__(self):
        return len(self._items)

Java

import java.util.ArrayList;

public class Stack<T> {
    private final ArrayList<T> items = new ArrayList<>();

    public void push(T value) {
        items.add(value);
    }

    public T pop() {
        if (isEmpty()) throw new IllegalStateException("Stack underflow");
        return items.remove(items.size() - 1);
    }

    public T peek() {
        if (isEmpty()) throw new IllegalStateException("Stack is empty");
        return items.get(items.size() - 1);
    }

    public boolean isEmpty() {
        return items.isEmpty();
    }
}

When to Use Stack (LIFO)

  • Reversal and nesting problems — matching brackets, validating HTML tags, parsing expressions — where the most recently opened thing must be closed first.
  • Undo/redo, navigation history, and any "restore the previous state" feature: push snapshots, pop to go back.
  • Backtracking algorithms (maze solving, puzzle search) and iterative DFS, where you explore deep and unwind to the last decision point.
  • Converting recursion to iteration: an explicit stack replaces the call stack when recursion depth would overflow.
  • Not the right tool when you need first-come-first-served processing — that is a queue — or random access to middle elements, where a plain array wins.
  • In practice, back a stack with a dynamic array (JavaScript array, Python list, Java ArrayDeque) rather than linked nodes — same O(1) operations, far better cache behavior.

Stack (LIFO) — Frequently Asked Questions

What is a stack used for in real life?

The most visible examples are undo (Ctrl+Z) in editors, the browser back button, and the call stack that tracks which function your program is currently inside. Compilers use stacks to evaluate expressions and match brackets, and depth-first search uses one to remember which paths still need exploring. Any situation where the most recent item must be handled first is a stack.

What does LIFO mean?

LIFO stands for Last In, First Out: the element added most recently is the first one removed. It is the defining property of a stack, enforced by allowing access only at one end. Its mirror image is FIFO (First In, First Out), the ordering a queue enforces, where the oldest element is served first.

What causes a stack overflow error?

Every function call pushes a frame onto the call stack, and that stack has a fixed memory limit. Recursion that never reaches its base case, or recurses deeper than the limit allows, keeps pushing frames until the space runs out — that is a stack overflow. The fix is a correct base case, or rewriting the recursion as a loop with an explicit stack.

Are push, pop, and peek really O(1)?

Yes. All three touch only the top element, so the work never depends on how many elements the stack holds. With an array backing, push is amortized O(1): occasionally the array must grow and copy, but averaged over many pushes each one is constant time. Pop and peek are always constant because nothing needs to move.

What is the difference between a stack and a queue?

A stack removes the newest element (LIFO); a queue removes the oldest (FIFO). Structurally, a stack adds and removes at the same end, while a queue adds at the rear and removes from the front. The choice changes algorithm behavior completely: graph traversal with a stack is depth-first search, and the same traversal with a queue is breadth-first search.

Compare Stack (LIFO)

Related Algorithms

References & Further Reading