When you have tasks with dependencies — like building software modules, scheduling jobs, or determining course prerequisites — you need to process tasks in a valid order. This is where Topological Sorting comes in.
🔹 What is Topological Sort?
A Topological Sort of a Directed Acyclic Graph (DAG) is a linear ordering of vertices such that for every directed edge u → v
, vertex u
comes before v
in the order.
- Only valid for DAGs (Directed Acyclic Graphs).
- Multiple valid orders may exist.
🔹 Applications
- Course scheduling (
Course Schedule
problem on LeetCode). - Task scheduling in Operating Systems.
- Build systems (Maven, Gradle, Makefiles).
- Dependency resolution in package managers (npm, pip, apt).
🔹 Approaches to Topological Sort
1. DFS-based Topological Sort
- Perform a DFS, push nodes into a stack after visiting all children.
- Pop stack to get topological order.
Java Code:
import java.util.*;
class DFSTopoSort {
private int V;
private List<List<Integer>> adj;
DFSTopoSort(int V) {
this.V = V;
adj = new ArrayList<>();
for (int i = 0; i < V; i++) adj.add(new ArrayList<>());
}
void addEdge(int u, int v) {
adj.get(u).add(v);
}
void topoSort() {
boolean[] visited = new boolean[V];
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < V; i++) {
if (!visited[i]) dfs(i, visited, stack);
}
while (!stack.isEmpty()) {
System.out.print(stack.pop() + " ");
}
}
void dfs(int v, boolean[] visited, Stack<Integer> stack) {
visited[v] = true;
for (int nei : adj.get(v)) {
if (!visited[nei]) dfs(nei, visited, stack);
}
stack.push(v);
}
public static void main(String[] args) {
DFSTopoSort g = new DFSTopoSort(6);
g.addEdge(5, 2);
g.addEdge(5, 0);
g.addEdge(4, 0);
g.addEdge(4, 1);
g.addEdge(2, 3);
g.addEdge(3, 1);
System.out.println("Topological Sort (DFS):");
g.topoSort();
}
}
Output Example:
5 4 2 3 1 0
2. Kahn’s Algorithm (BFS-based)
- Count in-degree (number of incoming edges) for each node.
- Start with nodes having
in-degree = 0
. - Repeatedly remove nodes and reduce in-degree of neighbors.
Java Code:
import java.util.*;
class KahnsAlgorithm {
private int V;
private List<List<Integer>> adj;
KahnsAlgorithm(int V) {
this.V = V;
adj = new ArrayList<>();
for (int i = 0; i < V; i++) adj.add(new ArrayList<>());
}
void addEdge(int u, int v) {
adj.get(u).add(v);
}
void topoSort() {
int[] indegree = new int[V];
for (int u = 0; u < V; u++) {
for (int v : adj.get(u)) {
indegree[v]++;
}
}
Queue<Integer> q = new LinkedList<>();
for (int i = 0; i < V; i++) {
if (indegree[i] == 0) q.offer(i);
}
List<Integer> topoOrder = new ArrayList<>();
while (!q.isEmpty()) {
int node = q.poll();
topoOrder.add(node);
for (int nei : adj.get(node)) {
indegree[nei]--;
if (indegree[nei] == 0) q.offer(nei);
}
}
if (topoOrder.size() != V) {
System.out.println("Graph has a cycle! No Topological Order exists.");
} else {
System.out.println("Topological Sort (Kahn’s): " + topoOrder);
}
}
public static void main(String[] args) {
KahnsAlgorithm g = new KahnsAlgorithm(6);
g.addEdge(5, 2);
g.addEdge(5, 0);
g.addEdge(4, 0);
g.addEdge(4, 1);
g.addEdge(2, 3);
g.addEdge(3, 1);
g.topoSort();
}
}
Output Example:
Topological Sort (Kahn’s): [4, 5, 2, 3, 1, 0]
🔹 Key Differences (DFS vs Kahn’s)
Aspect | DFS-based | Kahn’s Algorithm (BFS) |
---|---|---|
Method | Uses recursion + stack | Uses queue + in-degree |
Detect cycle | Indirect (via visited + recursion stack) | Direct (if nodes remain unprocessed) |
Space | O(V) | O(V) |
Use case | Recursive backtracking style problems | Dependency scheduling, course schedule |
🔹 Real-World Example: Course Scheduling
LeetCode #207, #210 use Kahn’s Algorithm directly.
- Courses = Nodes
- Prerequisites = Directed Edges
- If cycle → impossible schedule.
✅ Key Takeaways
- Topological Sort works only for DAGs.
- DFS method is intuitive, good for recursion lovers.
- Kahn’s Algorithm is practical for dependency resolution and cycle detection.
👉 Next in this series (Blog 3) we’ll go to Pattern 17: Segment Tree & Fenwick Tree (BIT) — mastering range queries and updates.
Top comments (0)