Stack
A stack is a fundamental linear data structure that follows the Last-In-First-Out (LIFO) principle. Think of it like a stack of plates - you can only add or remove plates from the top, and the last plate you put on is the first one you'll take off.
Interactive Stack Visualization
Experience the LIFO principle in action! Watch how elements are pushed onto and popped off the stack, and see how the top indicator always points to the most recently added element.
Stack Operations (LIFO - Last In, First Out)
Push (Add to Top)
Add element to top of stack
Pop (Remove from Top)
Remove element from top
Top value: 30
Peek (View Top)
Highlight top element
Stack Visualization
Stack Height: 3 / 8
Status: 3 elements in stack
Stack Contents (bottom to top): [10, 20, 30]
How Stack Operations Work:
Add a new element to the top of the stack. The last element added becomes the new top.
Remove and return the top element from the stack. Follows Last-In-First-Out (LIFO) principle.
View the top element without removing it. Useful for checking what's on top without modifying the stack.
LIFO Principle:
Stacks follow the Last-In-First-Out principle, meaning the last element added (pushed) is the first one to be removed (popped). Think of a stack of plates - you add and remove plates from the top, not the bottom.
Understanding LIFO (Last-In-First-Out)
The Plate Stack Analogy
Imagine a stack of dinner plates in your kitchen:
- • Adding plates: You place new plates on top of the stack
- • Taking plates: You remove plates from the top, one at a time
- • Last plate in: The most recently added plate
- • First plate out: That same recent plate is removed first
- • Bottom plates: Can't be accessed until top plates are removed
LIFO in Programming
This principle applies to many programming scenarios:
- • Function calls: Most recent call executes first
- • Undo operations: Last action undone first
- • Expression evaluation: Nested operations resolved inside-out
- • Browser history: Back button follows LIFO order
- • Memory management: Local variables in nested scopes
Common Use Cases
Function Call Stack
When your program calls functions, each call is pushed onto a call stack:
Stack: [main, funcA, funcB] ← top
Functions complete in reverse order: funcB finishes first, then funcA, then main.
Undo/Redo Functionality
Text editors and applications use stacks to track user actions:
Undo Stack: [Type "Hello", Delete "o", Type "p"] ← top
Pressing Undo reverses the most recent action first.
Complexity Analysis
| Operation | Time Complexity | Space Complexity | Explanation |
|---|---|---|---|
| Push | O(1) | O(1) | Add element to top in constant time |
| Pop | O(1) | O(1) | Remove top element in constant time |
| Peek | O(1) | O(1) | Access top element without removal |
Why O(1)? All stack operations only interact with the top element, regardless of how many elements are in the stack. No iteration or searching required!
Stack Class Implementation
Complete stack implementations with push, pop, and peek methods. Each example includes the plate stack analogy in comments and demonstrates both basic operations and practical applications.
class Stack:
"""
A Stack implementation using Python list
Demonstrates LIFO (Last-In-First-Out) principle
"""
def __init__(self):
"""Initialize an empty stack"""
self.items = []
def push(self, item):
"""
Add an item to the top of the stack
Like placing a plate on top of a stack of plates
Time Complexity: O(1)
Space Complexity: O(1)
"""
self.items.append(item)
print(f"Pushed {item} onto stack")
def pop(self):
"""
Remove and return the top item from the stack
Like taking the top plate from a stack of plates
Time Complexity: O(1)
Space Complexity: O(1)
Raises:
IndexError: If stack is empty
"""
if self.is_empty():
raise IndexError("Cannot pop from empty stack")
item = self.items.pop()
print(f"Popped {item} from stack")
return item
def peek(self):
"""
Return the top item without removing it
Like looking at the top plate without taking it
Time Complexity: O(1)
Space Complexity: O(1)
Raises:
IndexError: If stack is empty
"""
if self.is_empty():
raise IndexError("Cannot peek at empty stack")
return self.items[-1]
def is_empty(self):
"""Check if the stack is empty"""
return len(self.items) == 0
def size(self):
"""Return the number of items in the stack"""
return len(self.items)
def display(self):
"""Display stack contents from top to bottom"""
if self.is_empty():
return "Empty Stack"
print("Stack (top to bottom):")
for i in range(len(self.items) - 1, -1, -1):
print(f" [{i}] {self.items[i]}")
# Example usage demonstrating LIFO principle
def demonstrate_lifo():
"""Demonstrate how stack follows LIFO principle"""
stack = Stack()
print("=== Demonstrating LIFO Principle ===")
print("Think of this like stacking plates...")
# Push items (like stacking plates)
print("\nStacking plates:")
stack.push("Plate 1 (first)")
stack.push("Plate 2 (second)")
stack.push("Plate 3 (third)")
print(f"\nTop plate is: {stack.peek()}")
print(f"Stack size: {stack.size()}")
# Pop items (like taking plates off)
print("\nTaking plates off (LIFO order):")
while not stack.is_empty():
plate = stack.pop()
print(f"Took: {plate}")
print(f"\nStack is now empty: {stack.is_empty()}")
# Function call stack simulation
def recursive_function_demo(n):
"""Demonstrate how function calls use a stack"""
print(f"Calling function with n = {n}")
if n <= 1:
print(f"Base case reached with n = {n}")
return 1
else:
result = n * recursive_function_demo(n - 1)
print(f"Returning {result} for n = {n}")
return result
if __name__ == "__main__":
# Basic stack operations
demonstrate_lifo()
print("\n" + "="*50 + "\n")
# Function call stack example
print("=== Function Call Stack Example ===")
print("Computing factorial of 4:")
factorial_4 = recursive_function_demo(4)
print(f"\nFinal result: {factorial_4}") Key Takeaways
Stack Advantages
- • Simple & Efficient: All operations are O(1)
- • Memory Efficient: No complex pointer management
- • Natural LIFO: Perfect for recursive and nested scenarios
- • Easy to Implement: Can use arrays or linked lists
- • Safe Access: Only top element is accessible
When to Use Stacks
- • Function Call Management: Automatic by programming languages
- • Expression Parsing: Mathematical expressions, parentheses matching
- • Undo Operations: Text editors, drawing applications
- • Backtracking Algorithms: Maze solving, depth-first search
- • Memory Management: Local variable scoping