Data Structure and AlgorithmsUnit 211 min read
Stack: Operations, Applications & Real-World Use
Unit 2 of Data Structure and Algorithms explores the stack—its definition, operations (push, pop, peek, isEmpty), implementations (array vs. linked list), and applications in parsing, undo mechanisms, and memory management. Includes real-world examples, visual traces, and exam-focused comparisons.
TAKEAWAYS:
- A stack follows Last-In-First-Out (LIFO)—the last element added is the first removed, like a stack of plates.
- Core operations are push (add), pop (remove), peek (view top), and isEmpty (check if empty).
- Stacks are implemented using arrays (fixed size) or linked lists (dynamic size), each with trade-offs.
- Applications include function call stacks (recursion), expression evaluation, undo/redo operations, and backtracking algorithms.
- Time complexity: O(1) for push/pop/peek (amortized for dynamic arrays), O(n) for resizing (rare).
- Overflow/underflow errors occur when pushing to a full stack or popping from an empty stack.
1. Definition and Characteristics
A stack is a linear data structure that stores elements in a Last-In-First-Out (LIFO) order. Think of a stack of plates:
- You can only add or remove plates from the top.
- The last plate placed is the first one taken.
Key Properties:
- Abstract Data Type (ADT): Defined by operations, not implementation.
- Dynamic size: Grows/shrinks as elements are added/removed.
- No random access: Only the top element is accessible directly.
2. Stack Operations
The stack supports four primary operations:
| Operation | Description | Time Complexity | Example (Array Implementation) |
|---|---|---|---|
push(x) |
Adds x to the top of the stack. |
O(1) | stack[top++] = x; |
pop() |
Removes and returns the top element. | O(1) | return stack[--top]; |
peek() |
Returns the top element without removal. | O(1) | return stack[top-1]; |
isEmpty() |
Checks if the stack is empty. | O(1) | return top == 0; |
Visual: Stack Operations
flowchart TD
A["Stack (Empty)"] -->|"push(5)"| B["Stack\n[5]"]
B -->|"push(3)"| C["Stack\n[5, 3]"]
C -->|"peek()"| D["Returns 3"]
C -->|"pop()"| E["Stack\n[5]"]
E -->|"pop()"| F["Stack (Empty)"]Trace of push(5), push(3), peek(), pop(), pop():
| Step | Stack State | Top Pointer | Action |
|---|---|---|---|
| Initial | [] | -1 | - |
| push(5) | [5] | 0 | top = 0 |
| push(3) | [5, 3] | 1 | top = 1 |
| peek() | [5, 3] | 1 | Returns 3 |
| pop() | [5] | 0 | top = 0 |
| pop() | [] | -1 | top = -1 |
3. Implementations
Stacks can be implemented using:
- Arrays (static size)
- Linked Lists (dynamic size)
Comparison Table
| Feature | Array Implementation | Linked List Implementation |
|---|---|---|
| Size | Fixed (predefined) | Dynamic (grows as needed) |
| Memory Overhead | Low (only array storage) | High (pointers per node) |
| Push/Pop Time | O(1) amortized* | O(1) |
| Resizing Cost | O(n) (when full) | None |
| Access to Elements | Random access possible | Sequential access only |
| Use Case | Known max size (e.g., parsing) | Unknown size (e.g., recursion) |
*Amortized O(1) due to occasional resizing (doubling the array size).
Visual: Array vs. Linked List Stack
graph LR
subgraph Array Stack
A["stack[0]"] --> B["stack[1]"] --> C["stack[2]"]
D["top = 2"] --> C
end
subgraph Linked List Stack
E["Node(5)"] --> F["Node(3)"] --> G["Node(1)"]
H["top → G"] --> G
end4. Applications in Real World
Stacks are ubiquitous in computing and everyday systems. Here’s how they power apps and services in Nepal and globally:
Example 1: Function Call Stack (Recursion)
- Where? Every programming language (C, Java, Python) uses a stack to manage function calls.
- How? When a function is called, its return address and local variables are pushed onto the stack. When it returns, these are popped.
- Nepali Example: In a bank loan calculator app, recursive functions might compute compound interest:
Trace fordef calculate_interest(principal, rate, years): if years == 0: return principal return calculate_interest(principal * (1 + rate), rate, years - 1)calculate_interest(1000, 0.05, 2):Call Stack (Top to Bottom) Action calculate_interest(1000, 0.05, 2)Pushes (1000, 0.05, 2) calculate_interest(1050, 0.05, 1)Pushes (1050, 0.05, 1) calculate_interest(1102.5, 0.05, 0)Base case: returns 1102.5 Pops and returns 1102.5 Unwinds stack
Example 2: Undo/Redo in Text Editors (e.g., Microsoft Word, Google Docs)
- Where? Every text editor or IDE (VS Code, Sublime Text).
- How? Each edit (typing, deleting) is pushed onto a stack. Pressing Ctrl+Z pops the last action.
- Nepali Example: In eSewa’s online form, if you accidentally fill wrong details, the undo button uses a stack to revert changes.
Example 3: Expression Evaluation (Postfix/Infix Notation)
- Where? Calculators (e.g., scientific calculators), compilers.
- How? Stacks evaluate expressions like
3 + 5 * 2by following operator precedence. - Nepali Example: Khalti’s transaction history might use stacks to parse and validate payment expressions (e.g.,
amount = 500 + tax(10%)).
Example 4: Backtracking Algorithms (e.g., Maze Solving)
- Where? Pathfinding (e.g., GPS navigation), game AI.
- How? Algorithms like Depth-First Search (DFS) use a stack to explore paths.
- Nepali Example: Pathao’s ride-matching system might use a stack to explore possible driver routes before selecting the fastest.
Example 5: Browser History (Back/Forward Buttons)
- Where? Web browsers (Chrome, Firefox), mobile apps (Facebook, Instagram).
- How? Two stacks manage back and forward navigation.
- Nepali Example: In Daraz’s product page, clicking "Back" uses a stack to return to previous pages.
5. Worked Example: Balanced Parentheses Checker
Problem: Given a string like "({[]})", determine if parentheses/brackets are balanced using a stack.
Algorithm Steps:
- Initialize an empty stack.
- For each character in the string:
- If it’s an opening bracket
(,{,[, push it onto the stack. - If it’s a closing bracket
),},], pop from the stack and check if it matches the top.
- If it’s an opening bracket
- If the stack is empty at the end, the string is balanced.
Mermaid Flowchart:
flowchart TD
A["Start"] --> B["Initialize empty stack"]
B --> C["For each char in string:"]
C --> D["If char is '(', '{', '[':"]
D --> E["Push onto stack"]
E --> F["Else if char is ')', '}', ']':"]
F --> G["Pop from stack"]
G --> H["If stack empty or top mismatch:"]
H --> I["Return False"]
I --> J["End"]
H --> K["Continue"]
K --> C
C --> L["If stack empty:"]
L --> M["Return True"]
M --> JCode Implementation (Python):
def is_balanced(s):
stack = []
mapping = {')': '(', '}': '{', ']': '['}
for char in s:
if char in mapping.values(): # Opening bracket
stack.append(char)
elif char in mapping: # Closing bracket
if not stack or stack.pop() != mapping[char]:
return False
return not stack # True if stack empty
Trace for "({[]})":
| Step | Character | Stack State | Action |
|---|---|---|---|
| 1 | '(' | ['('] | Push '(' |
| 2 | '{' | ['(', '{'] | Push '{' |
| 3 | '[' | ['(', '{', '['] | Push '[' |
| 4 | ']' | ['(', '{'] | Pop '[' (matches) |
| 5 | '}' | ['('] | Pop '{' (matches) |
| 6 | ')' | [] | Pop '(' (matches) |
| End | - | [] | Return True (balanced) |
Trace for "({[}])" (unbalanced):
| Step | Character | Stack State | Action |
|---|---|---|---|
| 1 | '(' | ['('] | Push '(' |
| 2 | '{' | ['(', '{'] | Push '{' |
| 3 | '[' | ['(', '{', '['] | Push '[' |
| 4 | '}' | ['(', '{', '['] | Pop fails (expected ']') |
| Result | - | - | Return False (unbalanced) |
6. Advantages and Disadvantages
| Advantages | Disadvantages |
|---|---|
| Simple to implement and use. | Limited to LIFO operations. |
| O(1) time complexity for push/pop. | No random access to elements. |
| Efficient for nested structures (e.g., parentheses). | Fixed-size arrays can cause overflow. |
| Used in system-level operations (e.g., function calls). | Not suitable for all data access patterns. |
7. Common Pitfalls and Errors
Stack Overflow:
- Occurs when pushing to a full stack (e.g., infinite recursion without a base case).
- Fix: Use dynamic resizing (linked list) or check stack size before pushing.
Stack Underflow:
- Occurs when popping from an empty stack.
- Fix: Always check
isEmpty()before popping.
Incorrect Matching (e.g., in parentheses):
- Example:
"([)]"is unbalanced because]does not match(. - Fix: Ensure the stack’s top element matches the closing bracket.
- Example:
Memory Leaks (Linked List Implementation):
- Forgetting to free memory when popping nodes.
- Fix: Always update pointers correctly.
8. Exam Tip
How This Unit is Examined:
Theory (20-30%):
- Define stack, LIFO, and operations (
push,pop,peek,isEmpty). - Compare array vs. linked list implementations (time/space complexity).
- Explain applications (e.g., recursion, undo mechanisms).
- Define stack, LIFO, and operations (
Practical (70-80%):
- Trace operations: Given a sequence of
push/pop, draw the stack state after each step. - Code implementation: Write a stack using arrays or linked lists (often in C or Python).
- Algorithm application: Solve problems like:
- Balanced parentheses.
- Infix to postfix conversion.
- Tower of Hanoi (uses recursion + stack).
- Debugging: Identify errors in given stack code (e.g., incorrect
toppointer updates).
- Trace operations: Given a sequence of
Common Exam Questions:
- "Implement a stack using a linked list in C. Show how
push(5),push(3),pop()affects the stack." - "Explain how a stack is used in evaluating the postfix expression
3 4 2 * 1 5 - / +." - "What happens if you
pop()from an empty stack? How would you handle this in code?" - "Compare the time complexity of
pushandpopin array vs. linked list implementations."
Pro Tip:
- Draw the stack visually in exams—even if not asked, it clarifies your understanding.
- Memorize the trace table format for operations (like the one above for
push/pop). - Practice recursion problems (they rely heavily on the call stack).
Final Note: Stacks are foundational to algorithms and system design. Mastering them will help you tackle graphs (DFS), expression parsing, and system-level programming in later units. Practice tracing operations and implementing them in code!
Based on the PU BE Computer (PU) syllabus for Data Structure and Algorithms (CMP160), unit 2.
Discussion
Loading…