Stacks

IB Syllabus: B2.2.3 – Explain the concept of a stack as a “last in, first out” (LIFO) data structure: push, pop, peek, isEmpty.

Table of Contents

  1. Key Concepts
    1. What is a Stack?
    2. Stack Operations
  2. Using Stacks in Java
  3. Visualising Stack Operations
  4. Real-World Applications
    1. Undo/Redo
    2. Browser Back Button
    3. Method Call Stack
    4. Expression Evaluation
  5. Worked Examples
    1. Example 1: Reversing a String
    2. Example 2: Bracket Matching
  6. Quick Check
  7. Trace Exercise
  8. Code Completion
  9. Spot the Error
  10. Predict the Output
  11. Practice Exercises
    1. Core
    2. Extension
    3. Challenge
  12. Connections

Key Concepts

What is a Stack?

A stack is an abstract data structure that follows the Last In, First Out (LIFO) rule: the last item added is the first item removed. You can only access the top element.

Think of a stack of plates in a cafeteria: you add plates to the top and take plates from the top. You cannot pull a plate from the middle.

Stack Operations

Operation Description Java Method
Push Add an item to the top stack.push(value)
Pop Remove and return the top item stack.pop()
Peek Look at the top item without removing it stack.peek()
isEmpty Check if the stack has no elements stack.isEmpty()
Size Get the number of elements stack.size()

Pop and peek on an empty stack throw an EmptyStackException. Always check isEmpty() before calling pop() or peek().


Using Stacks in Java

import java.util.Stack;

Stack<Integer> stack = new Stack<>();

// Push elements onto the stack
stack.push(10);   // stack: [10]         top = 10
stack.push(20);   // stack: [10, 20]     top = 20
stack.push(30);   // stack: [10, 20, 30] top = 30

// Peek at the top (does not remove)
System.out.println(stack.peek());   // 30

// Pop the top element (removes and returns)
System.out.println(stack.pop());    // 30  stack: [10, 20]
System.out.println(stack.pop());    // 20  stack: [10]

// Check state
System.out.println(stack.isEmpty()); // false (10 is still there)
System.out.println(stack.size());    // 1

Remember: Stack<Integer> not Stack<int>. Like ArrayList, stacks store objects, not primitives.


Visualising Stack Operations

Push 10:   Push 20:   Push 30:   Pop:       Pop:
┌────┐     ┌────┐     ┌────┐     ┌────┐     ┌────┐
│    │     │    │     │ 30 │ ←   │    │     │    │
├────┤     ├────┤     ├────┤     ├────┤     ├────┤
│    │     │ 20 │ ←   │ 20 │     │ 20 │ ←   │    │
├────┤     ├────┤     ├────┤     ├────┤     ├────┤
│ 10 │ ←   │ 10 │     │ 10 │     │ 10 │     │ 10 │ ←
└────┘     └────┘     └────┘     └────┘     └────┘
top=10     top=20     top=30     top=20     top=10

The arrow (←) marks the top of the stack. Push adds above the arrow; pop removes at the arrow.


Real-World Applications

Undo/Redo

Every time you make an edit, the action is pushed onto the undo stack. Pressing Ctrl+Z pops the most recent action and undoes it. The undone action is pushed onto a redo stack.

Browser Back Button

Each page you visit is pushed onto a history stack. Clicking “Back” pops the current page and displays the previous one.

Method Call Stack

When a method calls another method, the calling method’s state is pushed onto the call stack. When the called method returns, its frame is popped and the calling method resumes.

public static void main(String[] args) {
    System.out.println(add(3, multiply(4, 5)));
}
// Call stack when multiply runs: [main, add, multiply]
// multiply returns 20, popped: [main, add]
// add returns 23, popped: [main]

Expression Evaluation

Calculators use stacks to evaluate expressions with brackets. Opening brackets are pushed; when a closing bracket is found, operations are popped and evaluated.

When you see LIFO in an exam question, think stack.


Worked Examples

Example 1: Reversing a String

A stack naturally reverses order: push all characters, then pop them.

public static String reverse(String text) {
    Stack<Character> stack = new Stack<>();

    // Push each character
    for (int i = 0; i < text.length(); i++) {
        stack.push(text.charAt(i));
    }

    // Pop to build reversed string
    String reversed = "";
    while (!stack.isEmpty()) {
        reversed += stack.pop();
    }
    return reversed;
}
System.out.println(reverse("hello"));  // "olleh"

Example 2: Bracket Matching

Check if brackets in an expression are balanced: every ( must have a matching ).

public static boolean isBalanced(String expression) {
    Stack<Character> stack = new Stack<>();

    for (int i = 0; i < expression.length(); i++) {
        char c = expression.charAt(i);
        if (c == '(') {
            stack.push(c);
        } else if (c == ')') {
            if (stack.isEmpty()) {
                return false;  // closing bracket with no opening
            }
            stack.pop();
        }
    }
    return stack.isEmpty();  // true if all brackets matched
}
System.out.println(isBalanced("(a + b) * (c - d)"));  // true
System.out.println(isBalanced("((a + b)"));             // false
System.out.println(isBalanced("a + b)"));               // false

Quick Check

Q1. What does LIFO stand for and what does it mean?

Q2. You push A, B, C (in that order). Then pop(), then peek(). What does peek() return?

Q3. What happens if you call pop() on an empty stack?

Q4. Which real-world application uses a stack?

Q5. What is the difference between peek() and pop()?


Trace Exercise

Trace the stack contents after each operation.

Trace: Track the stack contents and the return value of each operation.

Stack<String> stack = new Stack<>();
stack.push("Red");      // Op 1
stack.push("Blue");     // Op 2
stack.push("Green");    // Op 3
stack.pop();            // Op 4
stack.push("Yellow");   // Op 5
stack.peek();           // Op 6
stack.pop();            // Op 7
After OpStack (bottom to top)Return Value
1 [Red] --
2 [Red, Blue] --
3 [Red, Blue, Green] --
4
5 --
6
7

Code Completion

Complete the method that uses a stack to check if a string is a palindrome.

Fill in the blanks: Push all characters, then pop and compare.

public static boolean isPalindrome(String text) {
    Stack<Character> stack = new Stack<>();
    for (int i = 0; i < text.length(); i++) {
        stack.(text.charAt(i));
    }
    for (int i = 0; i < text.length(); i++) {
        if (text.charAt(i) != stack.) {
            return ;
        }
    }
    return true;
}

Spot the Error

This code should reverse the numbers, but it crashes.

Bug Hunt: This code should print all numbers in reverse, but it misses the last one.

1Stack<Integer> stack = new Stack<>(); 2stack.push(1); stack.push(2); stack.push(3); 3// Should print: 3 2 1 4while (stack.size() > 1) { 5 System.out.println(stack.pop()); 6}

Pick the correct fix for line 4:


Predict the Output

Predict: What does this code print?

Stack<Integer> s = new Stack<>();
s.push(5);
s.push(10);
s.push(15);
System.out.println(s.pop());
s.push(20);
System.out.println(s.pop());
System.out.println(s.peek());

Practice Exercises

Core

  1. Stack trace – Starting with an empty stack, perform these operations and write the stack contents after each: push(5), push(10), push(15), pop(), push(20), pop(), pop(), peek().

  2. Reverse an array – Write a method that takes an int[] array and uses a Stack<Integer> to return a new array with the elements in reverse order.

  3. Stack applications – For each of the following, explain whether a stack is appropriate and why:

    • (a) Managing browser history (back button)
    • (b) A queue at a supermarket checkout
    • (c) Evaluating nested brackets in a math expression

Extension

  1. Undo system – Create a simple text editor model: an ArrayList<String> of lines and a Stack<String> for undo. Implement addLine(String line) (adds to the list and pushes to undo stack) and undo() (removes the last line added).

  2. Two-stack sort – Given a stack of integers in random order, use one additional stack to sort the elements so the smallest is on top. You may only use push, pop, peek, and isEmpty.

Challenge

  1. Postfix evaluator – Implement a calculator that evaluates postfix (Reverse Polish Notation) expressions. For example, "3 4 + 2 *" means (3 + 4) * 2 = 14. Use a stack: push numbers, and when you encounter an operator, pop two numbers, apply the operator, and push the result.

Connections

  • Prerequisites: 1D Arrays – understanding indexed collections
  • Prerequisites: ArrayList – dynamic collections using Java generics
  • Related: Queues – FIFO counterpart to stacks
  • Forward: Recursion (HL) – the call stack is a stack
  • Forward: ADTs: Stacks from Scratch (HL) – implementing your own stack

© EduCS.me — A resource hub for IB Computer Science

This site uses Just the Docs, a documentation theme for Jekyll.