Web Analytics

šŸ“š Stack Basics

Beginner to Intermediate ~20 min read ⭐ Essential

Imagine a stack of plates - you can only add or remove from the top! That's exactly how a Stack works. It's a LIFO (Last In, First Out) data structure where the last element added is the first one removed. Stacks power function calls, undo/redo, browser history, and expression evaluation!

šŸŽÆ Why Stacks Matter!

Stacks are EVERYWHERE:

  • āœ… Function calls - Every function call uses a stack!
  • āœ… Undo/Redo - Text editors, Photoshop, browsers
  • āœ… Expression evaluation - Calculators, compilers
  • āœ… Backtracking - Maze solving, Sudoku, DFS
  • āœ… Browser history - Back button navigation

All operations are O(1) - super efficient!

The LIFO Principle

Last In, First Out

Think of a stack of plates:

Push (add) plates:
  [Plate 3] ← Last in (on top)
  [Plate 2]
  [Plate 1] ← First in (at bottom)

Pop (remove) plates:
  Remove Plate 3 first (last in, first out!)
  Then Plate 2
  Finally Plate 1

Key insight: You can only access the TOP element!

See It in Action

Watch LIFO in action:

Stack Operations

Three Core Operations

1. Push - Add to Top
stack.push(10)  # Add 10 to top
stack.push(20)  # Add 20 to top (now top is 20)

Time: O(1), Space: O(1)

2. Pop - Remove from Top
value = stack.pop()  # Remove and return top (20)
# Now top is 10

Time: O(1), Space: O(1)

3. Peek - View Top (without removing)
top = stack.peek()  # View top without removing
# Stack unchanged

Time: O(1), Space: O(1)

Implementation 1: Array-based Stack

Using Dynamic Array

class StackArray:
    def __init__(self):
        self.items = []  # Python list (dynamic array)
    
    def push(self, item):
        self.items.append(item)  # O(1) amortized
    
    def pop(self):
        if self.is_empty():
            return None
        return self.items.pop()  # O(1)
    
    def peek(self):
        if self.is_empty():
            return None
        return self.items[-1]  # O(1)
    
    def is_empty(self):
        return len(self.items) == 0  # O(1)
    
    def size(self):
        return len(self.items)  # O(1)

Pros: Simple, cache-friendly, less memory overhead

Cons: May need resizing (amortized O(1))

Implementation 2: Linked List-based Stack

Using Linked List

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

class StackLinkedList:
    def __init__(self):
        self.top = None
        self._size = 0
    
    def push(self, item):
        new_node = Node(item)
        new_node.next = self.top
        self.top = new_node
        self._size += 1  # O(1)
    
    def pop(self):
        if self.is_empty():
            return None
        item = self.top.data
        self.top = self.top.next
        self._size -= 1
        return item  # O(1)
    
    def peek(self):
        if self.is_empty():
            return None
        return self.top.data  # O(1)
    
    def is_empty(self):
        return self.top is None  # O(1)
    
    def size(self):
        return self._size  # O(1)

Pros: No resizing, truly O(1) push

Cons: More memory (pointers), worse cache performance

The Complete Code

Output
Click Run to execute your code

Array vs Linked List Comparison

Aspect Array Linked List Winner
Push O(1) amortized O(1) āœ“ Linked List
Pop O(1) O(1) Tie
Peek O(1) O(1) Tie
Memory Less āœ“ More (pointers) Array
Cache Better āœ“ Worse Array
Resizing Needed Not needed āœ“ Linked List

Real-World Applications

Where Stacks Are Used

1. Function Call Stack
main() {
    processData();  // Push main
}

processData() {
    validate();     // Push processData
}

validate() {
    return;         // Pop validate
                    // Pop processData
                    // Pop main
}
2. Undo/Redo
  • Undo stack: Push each action
  • Ctrl+Z: Pop from undo stack
  • Redo: Use second stack
3. Expression Evaluation
  • Infix to postfix conversion
  • Evaluate postfix expressions
  • Check balanced parentheses
4. Browser History
  • Back button: Pop from history stack
  • Visit new page: Push to stack

Common Mistakes

āŒ Mistake #1: Not Checking Empty

# WRONG - crashes if empty!
value = stack.pop()

# RIGHT - check first
if not stack.is_empty():
    value = stack.pop()
else:
    print("Stack is empty!")

āŒ Mistake #2: Confusing Peek and Pop

# Peek - view without removing
top = stack.peek()  # Stack unchanged

# Pop - remove and return
top = stack.pop()   # Stack changed!

Interview Tips

šŸ’” How to Ace Stack Questions

  • āœ… Always mention LIFO! Show you understand the principle
  • āœ… All operations are O(1) - emphasize efficiency
  • āœ… Know both implementations - array and linked list
  • āœ… Discuss trade-offs - memory vs cache performance
  • āœ… Check for empty - before pop/peek
  • āœ… Know applications - function calls, undo/redo, expression eval

Summary

Stack Basics Mastery

  1. LIFO Principle: Last In, First Out
  2. Three Operations: Push, Pop, Peek (all O(1))
  3. Two Implementations: Array (cache-friendly) and Linked List (no resizing)
  4. Applications: Function calls, undo/redo, expression evaluation, backtracking
  5. Key Advantage: All operations are O(1) - super efficient!

Interview tip: Stacks are simple but powerful! Always check for empty before pop/peek. Know the difference between array and linked list implementations!

What's Next?

You've mastered stack basics! Next: Stack Applications - expression evaluation, balanced parentheses, and more!

Practice: Implement both array and linked list versions. Try the LIFO demo!