Data Structure and AlgorithmsUnit 1014 min read
Advanced Data Structures & Applications: Heaps, Tries, Disjoint Sets, and Graph Algorithms
Unit 10 of Data Structure and Algorithms explores priority queues (heaps), string search (Tries), disjoint-set forests (Union-Find), and advanced graph algorithms (Kruskal’s, Prim’s, Dijkstra’s, and topological sorting). Learn their real-world uses, time complexities, and implementation details with step-by-step traces
TAKEAWAYS:
- Heaps (min-heap/max-heap) enable efficient priority queues with insert/delete, used in scheduling and Dijkstra’s algorithm.
- Tries (prefix trees) optimize string searches (autocomplete, dictionaries) with lookup time per word of length .
- Disjoint-set forests (Union-Find) manage dynamic connectivity problems (e.g., network redundancy, social network friend groups) with near-constant-time operations.
- Graph algorithms (Kruskal’s, Prim’s, Dijkstra’s) solve minimum spanning trees and shortest paths, critical for routing (NTC networks, Pathao deliveries) and dependency resolution (software builds).
- Topological sorting linearizes directed acyclic graphs (DAGs), used in task scheduling (e.g., course prerequisites, dependency resolution in software).
- Trade-offs between time/space complexity and real-world constraints (e.g., memory vs. speed in heaps vs. balanced BSTs) dictate choice of data structure.
1. Priority Queues and Heaps
1.1 Definition and Properties
A heap is a complete binary tree where each node satisfies the heap property:
- Min-heap: Parent ≤ children (smallest element at root).
- Max-heap: Parent ≥ children (largest element at root).
Key operations:
insert(key):extract-min/max():get-min/max():
1.2 Array Representation
Heaps are stored in arrays for efficiency:
- For a node at index
i:- Left child:
2i + 1 - Right child:
2i + 2 - Parent:
- Left child:
graph TD
A["Root (i=0)"] --> B["Left (i=1)"]
A --> C["Right (i=2)"]
B --> D["Left (i=3)"]
B --> E["Right (i=4)"]
C --> F["Left (i=5)"]
C --> G["Right (i=6)"]Example: Min-heap for [3, 9, 2, 1, 4] (array indices 0–4):
[1, 3, 2, 9, 4]
Visualization:
**1.3 Operations: Insert and Extract-Min
Insertion:
- Add the new element at the end of the array.
- Bubble-up (heapify-up) to restore the heap property.
Extract-Min:
- Remove the root (min element).
- Replace it with the last element in the array.
- Bubble-down (heapify-down) to restore the heap property.
Trace: Insert 5 into [1, 3, 2, 9, 4] (min-heap)
| Step | Array | Action |
|---|---|---|
| Initial | [1, 3, 2, 9, 4] |
|
| After add | [1, 3, 2, 9, 4, 5] |
Add 5 at index 5 |
| Bubble-up | [1, 3, 2, 5, 4, 9] |
Swap 5 with 9 |
Trace: Extract-Min from [1, 3, 2, 5, 4]
| Step | Array | Action |
|---|---|---|
| Initial | [1, 3, 2, 5, 4] |
Remove 1 (root) |
| Replace | [4, 3, 2, 5] |
Move 4 to root |
| Bubble-down | [2, 3, 4, 5] |
Swap 4 with 2 |
1.4 Applications
- Dijkstra’s algorithm: Priority queue for selecting the next node to explore.
- Job scheduling: Highest-priority tasks executed first (e.g., Pathao’s ride allocation).
- Merge K sorted lists: Heap merges lists in time.
In the real world:
- Pathao’s ride allocation: Uses a max-heap to prioritize drivers with the highest availability score (distance, response time) for nearby passengers.
- NTC’s network routing: Dijkstra’s algorithm (with a min-heap) finds the shortest path for data packets between routers.
- WhatsApp’s message delivery: Priority queues ensure urgent messages (e.g., calls, alerts) are processed before regular chats.
2. Tries (Prefix Trees)
2.1 Definition
A Trie (pronounced "try") is a tree-like data structure for storing strings, where:
- Each node represents a character.
- The root is empty.
- A null marker (
*) denotes the end of a word.
Time complexity:
- Insertion: (where = length of the string).
- Search: .
- Space: (worst case, where = number of words).
**2.2 Structure
Example: Words ["PATHO", "PSYCHO", "PATH"] stored in a Trie.
**2.3 Operations: Insert and Search
Insert("PATHO"):
- Start at root, traverse
P → A → T → H → O. - Add
*atOto mark the end of the word.
Search("PSY"):
- Traverse
P → S → Y. - No
*atY→ word not found.
Trace: Insert "PATH" into the Trie above
| Step | Node Path | Action |
|---|---|---|
| Start | Root | |
| After P | P | Create node P |
| After A | P → A | Create node A |
| After T | P → A → T | Create node T |
| After H | P → A → T → H | Create node H |
| After * | P → A → T → H → * | Add * (end of "PATH") |
2.4 Applications
- Autocomplete: Google Search, eSewa’s transaction suggestions.
- Spell checkers: Dictionary lookups (e.g., Microsoft Word).
- IP routing: Longest prefix matching in networks (e.g., NTC’s routing tables).
In the real world:
- eSewa’s transaction autocomplete: As you type "electricity," the Trie quickly suggests "electricity bill payment" from stored transactions.
- Google Search: Uses Tries to rank and suggest search queries in milliseconds.
- Ncell’s USSD menu: The
*123#menu system uses Tries to navigate options like "Balance Check" or "Data Plan."
3. Disjoint-Set Forests (Union-Find)
3.1 Definition
A disjoint-set data structure (Union-Find) manages a partition of elements into disjoint sets with two operations:
- Find(x): Determine which subset
xbelongs to. - Union(x, y): Merge the subsets of
xandy.
Optimizations:
- Path compression (Find): Flatten the structure for future queries.
- Union by rank: Attach the shorter tree to the root of the taller tree.
Time complexity:
- Near- per operation (amortized, with optimizations).
**3.2 Structure
Example: Sets {2, 3}, {4, 5}, {6, 7}.
**3.3 Operations: Find and Union
Find(3):
- Traverse
3 → 1(root). - Path compression: Update
3to point directly to1.
Union(3, 4):
- Find roots:
3 → 1,4 → 2. - Union by rank: Attach
1to2(assuming rank of2> rank of1).
Trace: Union-Find with Path Compression
| Operation | Action | Structure After |
|---|---|---|
| Find(3) | 3 → 1 (path compression) | {1: {2, 3}}, {2: {4, 5}} |
| Union(3,4) | Attach 1 to 2 (by rank) |
{2: {1, 2, 3, 4, 5}} |
3.4 Applications
- Network connectivity: Detect cycles in graphs (e.g., NTC’s redundant fiber links).
- Social networks: Friend groups (e.g., Facebook’s friend suggestions).
- Kruskal’s algorithm: Builds MST by checking for cycles.
In the real world:
- NTC’s network redundancy: Union-Find ensures no loops are created when adding new fiber links between cities.
- Khalti’s fraud detection: Detects if two transactions are from the same "group" (e.g., linked accounts) to flag suspicious activity.
- Daraz’s inventory management: Groups products by supplier to optimize bulk orders.
4. Advanced Graph Algorithms
4.1 Minimum Spanning Tree (MST)
Kruskal’s Algorithm:
- Sort all edges by weight.
- Add edges one by one, skipping those that form cycles (checked with Union-Find).
Prim’s Algorithm:
- Start with an arbitrary node.
- Greedily add the cheapest edge from the current MST to a vertex outside it.
Comparison:
| Algorithm | Time Complexity | Use Case |
|---|---|---|
| Kruskal’s | Sparse graphs (few edges) | |
| Prim’s | Dense graphs (many edges) |
Trace: Kruskal’s on Graph with Edges (A-B:1), (B-C:2), (A-C:3), (C-D:4)
| Step | Edge Added | Union-Find Check | MST Edges |
|---|---|---|---|
| 1 | A-B (1) | No cycle | {A-B} |
| 2 | B-C (2) | No cycle | {A-B, B-C} |
| 3 | A-C (3) | Cycle (A-B-C) | {A-B, B-C} |
| 4 | C-D (4) | No cycle | {A-B, B-C, C-D} |
4.2 Shortest Path: Dijkstra’s Algorithm
Steps:
- Initialize distances:
dist[source] = 0, others∞. - Use a priority queue (min-heap) to pick the next node.
- Relax edges: Update distances if a shorter path is found.
Trace: Dijkstra’s from A to D (weights: A-B:1, B-C:2, A-C:3, C-D:4)
| Step | Node Processed | Distances | Priority Queue |
|---|---|---|---|
| 1 | A | A:0, B:1, C:3 | B(1), C(3) |
| 2 | B | A:0, B:1, C:3 | C(3) |
| 3 | C | A:0, B:1, C:3, D:7 | D(7) |
| 4 | D | A:0, B:1, C:3, D:7 | Empty |
In the real world:
- Pathao’s route optimization: Dijkstra’s finds the fastest path from pickup to destination, avoiding traffic (e.g., Kathmandu’s busy Thapathali route).
- NTC’s internet routing: Shortest-path algorithms ensure data packets take the least time between servers.
- NEPSE’s stock dependency: Topological sorting resolves buy/sell dependencies between stocks (e.g., "Buy X after Y rises").
5. Topological Sorting
5.1 Definition
A linear ordering of vertices in a DAG such that for every directed edge (u → v), u comes before v.
Applications:
- Task scheduling (e.g., course prerequisites).
- Dependency resolution (e.g., software builds).
**5.2 Algorithm: Kahn’s Method
- Compute in-degree (number of incoming edges) for each node.
- Enqueue nodes with
in-degree = 0. - For each node
udequeued, reduce in-degree of its neighbors. If a neighbor’s in-degree becomes0, enqueue it.
Trace: Topological Sort for DAG (A→B, A→C, B→D, C→D)
| Step | In-Degree | Queue | Sorted Order |
|---|---|---|---|
| 1 | A:0, B:1, C:1, D:2 | A | [A] |
| 2 | B:0, C:0, D:2 | B, C | [A, B] |
| 3 | C:0, D:1 | C | [A, B, C] |
| 4 | D:0 | D | [A, B, C, D] |
5.3 Applications
- Course scheduling: TU’s BIM course prerequisites (e.g., "Take Data Structures before Algorithms").
- Software builds: Compile dependencies in the correct order (e.g.,
gccfor C programs). - Project management: Task ordering in Trello or Asana.
In the real world:
- TU’s exam schedule: Topological sorting ensures no student writes an exam before its prerequisites are cleared.
- Daraz’s order fulfillment: Tasks like "pack → ship → deliver" must follow this order.
- Ncell’s app updates: Dependency resolution ensures new features rely on existing code.
Exam Tip
Heaps:
- Memorize array indices for children/parent.
- Practice insert/extract traces (show bubble-up/down steps).
- Common pitfall: Forgetting to heapify after insertion/deletion.
Tries:
- Draw the Trie structure for given words (e.g.,
["CAT", "DOG", "CAR"]). - Explain autocomplete using prefix traversal.
- Exam question: "How would you implement a spell checker using a Trie?"
- Draw the Trie structure for given words (e.g.,
Union-Find:
- Path compression and union by rank are key optimizations—explain why they reduce time complexity.
- Real-world link: NTC’s network redundancy or Khalti’s fraud detection.
Graph Algorithms:
- Kruskal’s vs. Prim’s: Know when to use each (sparse vs. dense graphs).
- Dijkstra’s: Always use a priority queue (min-heap). Trace the distance updates.
- Topological sort: Kahn’s method is safer than DFS for cycles (but DFS is also acceptable if the graph is guaranteed to be a DAG).
Comparison Tables:
- The exam often asks to compare data structures (e.g., "Heaps vs. BSTs for priority queues").
- Key points:
- Heaps: Faster insert/delete (), but no efficient search by key.
- BSTs: for all operations (if balanced), but slower insertions in worst case.
Pseudocode:
- Write clear pseudocode for algorithms (e.g., Dijkstra’s with a priority queue).
- Example:
def dijkstra(graph, source): dist = {node: ∞ for node in graph} dist[source] = 0 heap = [(0, source)] while heap: current_dist, u = heappop(heap) for v, weight in graph[u]: if dist[v] > dist[u] + weight: dist[v] = dist[u] + weight heappush(heap, (dist[v], v)) return dist
Real-World Scenarios:
- Always relate to Nepalese examples (e.g., "How would Pathao use a min-heap?" or "How does NTC avoid network loops?").
- Avoid vague answers: Instead of "used in databases," say "eSewa uses Tries for transaction autocomplete."
Final Advice:
- Draw diagrams for every algorithm (especially heap operations and graph traversals).
- Time complexity is critical—know vs. trade-offs.
- Practice coding: Implement a heap or Trie in code (even pseudocode) to solidify understanding.
Based on the TU BIM syllabus for Data Structure and Algorithms (IT238), unit 10.
Discussion
Loading…