Back to the journalNOTES BY FAJAR
Data Structures2 min read

Introduction to Stacks

A stack removes the most recently added item first, which helps with matching, reversal, and nested operations.

Stacks appear in function calls, undo and redo histories, and expression evaluation. The useful rule is LIFO, or Last In, First Out: the most recently added item is removed first.

LIFO in practice

A stack exposes operations at one end. The stack removes the last item added first. This order is useful when the newest state must take priority over older state. When I first implemented a stack, I kept it simple:

javascript
class Stack {
  constructor() {
    this.items = [];
  }

  push(element) {
    this.items.push(element);
  }

  pop() {
    if (this.isEmpty()) {
      return "Stack is empty";
    }
    return this.items.pop();
  }

  peek() {
    if (this.isEmpty()) {
      return "Stack is empty";
    }
    return this.items[this.items.length - 1];
  }

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

I find stacks useful when the newest item determines the next action. Matching brackets is one example:

javascript
function isValidParentheses(s) {
  const stack = [];
  const pairs = { "(": ")", "[": "]", "{": "}" };

  for (let char of s) {
    if (pairs[char]) {
      stack.push(char); // Opening bracket
    } else {
      if (stack.length === 0) return false;
      const last = stack.pop();
      if (pairs[last] !== char) return false;
    }
  }

  return stack.length === 0;
}

To reverse an order, I push each item and pop them later:

javascript
function reverseString(str) {
  const stack = [];
  for (let char of str) {
    stack.push(char);
  }

  let reversed = "";
  while (stack.length > 0) {
    reversed += stack.pop();
  }
  return reversed;
}

For undo behavior, I store previous states in a stack:

javascript
class Editor {
  constructor() {
    this.content = "";
    this.undoStack = [];
  }

  type(text) {
    this.undoStack.push(this.content); // Save state
    this.content += text;
  }

  undo() {
    if (this.undoStack.length > 0) {
      this.content = this.undoStack.pop();
    }
  }
}

When I first learned about stack overflow errors, I thought they were related to the website. The programming error occurs when a stack runs out of space, often because recursion goes too deep. The website name is a programming joke.

Complexity and fit

Stacks have become one of my favorite data structures because the LIFO rule handles nested structures and "most recent" state without extra ordering logic. For a stack that uses a dynamic array, push is amortized O(1) and pop is O(1).

When a problem asks for the latest item, nested matching, reversal, or undo behavior, a stack is a natural candidate. The data structure is small, but its ordering rule removes a lot of bookkeeping.

FILED UNDER

THANKS FOR READING

Did this resonate?

A reaction or a conversation is always welcome.

Loading reactions…

Pass it along

Loading comments...

Related posts

All writing