š Stack Basics
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
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
- LIFO Principle: Last In, First Out
- Three Operations: Push, Pop, Peek (all O(1))
- Two Implementations: Array (cache-friendly) and Linked List (no resizing)
- Applications: Function calls, undo/redo, expression evaluation, backtracking
- 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!
Enjoying these tutorials?