The Story — Getting Dressed in the Right Order
Draw each item as a node. Draw an arrow
A → B when A must come before B.
Now find an order to put on every item so that every arrow points forward.That order is a topological order. Finding it is called topological sorting.
Topological sorting works on a DAG: a Directed Acyclic Graph. "Directed" means edges have arrows. "Acyclic" means you can never follow arrows and come back to where you started. If there is a cycle (A before B, B before C, C before A), no valid order exists.
Kahn's algorithm (BFS-style): keep taking a node with in-degree 0. Remove it and its arrows. Repeat.
DFS-based: go deep. When a node has no more places to go, it is "finished". Push it on a stack.
Reading the stack from top to bottom gives the order.
Watch It Work — Animated Diagram
The getting-dressed graph. Pick Kahn to watch in-degree counters (the small badges) drop to zero. Pick DFS to watch nodes finish from the deepest one upwards. The order is built at the bottom.
Both answers are correct, even though they look different. Check any arrow: its start always comes earlier in the list.
The Topological Sort Simulator — Build Your Own DAG
Draw tasks and the arrows between them. Run Kahn's or DFS one step at a time. Watch the queue and in-degree table, or the call stack and finish stack. You can also play My Order: click nodes in your own order, and the simulator stops you if you break a rule.
1. Classic 6 Nodes: type your guess for Kahn's output first, then check. Do the same for DFS.
2. Press Count Valid Orders. The classic graph has 13 valid orders. Kahn and DFS each find just one of them.
3. Course Plan + Kahn: the last step shows the levels. These are the fewest semesters needed.
4. Has a Cycle: Kahn gets stuck with nodes left over. DFS finds a back edge to a GRAY node.
5. My Order mode: try to put Shoes before Socks. The simulator will stop you.
Kahn's Algorithm — Step by Step
Graph: 5→2, 5→0, 4→0, 4→1, 2→3, 3→1. Starting in-degrees: 0:2, 1:2, 2:1, 3:1, 4:0, 5:0.
| Step | Dequeue | In-degree Changes | Queue After | Order So Far |
|---|---|---|---|---|
| 0 | — | Nodes with in-degree 0: 4, 5 | [4, 5] | — |
| 1 | 4 | 0: 2→1 · 1: 2→1 | [5] | 4 |
| 2 | 5 | 0: 1→0 (enqueue) · 2: 1→0 (enqueue) | [0, 2] | 4, 5 |
| 3 | 0 | no outgoing edges | [2] | 4, 5, 0 |
| 4 | 2 | 3: 1→0 (enqueue) | [3] | 4, 5, 0, 2 |
| 5 | 3 | 1: 1→0 (enqueue) | [1] | 4, 5, 0, 2, 3 |
| 6 | 1 | no outgoing edges | [ ] | 4, 5, 0, 2, 3, 1 |
Nodes in a cycle wait for each other forever. Their in-degree never reaches 0, so they never enter the queue. When the queue is empty, check: if the order has fewer than V nodes, the graph has a cycle.
DFS-Based Sort — Step by Step (same graph)
| Visit From | Path Walked (GRAY) | Finished (pushed to stack) | Stack (bottom → top) |
|---|---|---|---|
| 0 | 0 | 0 (no out-edges) | [0] |
| 1 | 1 | 1 | [0, 1] |
| 2 | 2 → 3 (1 is already BLACK) | 3, then 2 | [0, 1, 3, 2] |
| 3 | already BLACK — skip | — | [0, 1, 3, 2] |
| 4 | 4 (0 and 1 are BLACK) | 4 | [0, 1, 3, 2, 4] |
| 5 | 5 (0 and 2 are BLACK) | 5 | [0, 1, 3, 2, 4, 5] |
| Pop from top to bottom | 5, 4, 2, 3, 1, 0 | ||
A node finishes only after everything it points to has finished. So for any edge u → v, v finishes before u. Reverse the finish list and u comes before v. That is exactly the rule we need.
| Feature | Detail |
|---|---|
| Container | Queue of ready nodes |
| Key idea | In-degree reaches 0 → ready |
| Builds order | Front to back |
| Cycle check | Fewer than V nodes placed |
| Feature | Detail |
|---|---|
| Container | Call stack + result stack |
| Key idea | Node finishes after its children |
| Builds order | Back to front (reverse) |
| Cycle check | Edge to a GRAY node (back edge) |
Python Implementation
1. Kahn's Algorithm
from collections import deque
graph = {5: [2, 0], 4: [0, 1], 2: [3], 3: [1], 0: [], 1: []}
def kahn(graph):
indeg = {u: 0 for u in graph}
for u in graph: # count incoming arrows
for v in graph[u]:
indeg[v] += 1
queue = deque(sorted(u for u in graph if indeg[u] == 0))
order = []
while queue:
u = queue.popleft()
order.append(u)
for v in sorted(graph[u]): # "remove" u's arrows
indeg[v] -= 1
if indeg[v] == 0:
queue.append(v) # v is now ready
if len(order) < len(graph):
raise ValueError("Cycle found! No topological order.")
return order
print("Kahn order:", kahn(graph))
2. DFS-Based Topological Sort (with cycle check)
WHITE, GRAY, BLACK = 0, 1, 2 # not seen, on path, finished
def dfs_topo(graph):
color = {u: WHITE for u in graph}
stack = []
def visit(u):
color[u] = GRAY
for v in sorted(graph[u]):
if color[v] == GRAY: # back edge
raise ValueError(f"Cycle found at edge {u} -> {v}")
if color[v] == WHITE:
visit(v)
color[u] = BLACK
stack.append(u) # u is finished
for u in sorted(graph):
if color[u] == WHITE:
visit(u)
print("Finish order:", stack)
return stack[::-1] # reverse
print("DFS order:", dfs_topo(graph))
try:
dfs_topo({'A': ['B'], 'B': ['C'], 'C': ['A']})
except ValueError as e:
print("Error:", e)
3. Bonus — Minimum Number of Semesters (Kahn by levels)
def semesters(graph):
indeg = {u: 0 for u in graph}
for u in graph:
for v in graph[u]:
indeg[v] += 1
level = sorted(u for u in graph if indeg[u] == 0)
result = []
while level:
result.append(level) # everything ready now
nxt = []
for u in level:
for v in graph[u]:
indeg[v] -= 1
if indeg[v] == 0:
nxt.append(v)
level = sorted(nxt)
return result
courses = {
'Python': ['DS', 'Web'], 'Math': ['DS', 'ML'], 'DS': ['Algo', 'DBMS'],
'Algo': ['ML'], 'DBMS': ['Project'], 'Web': ['Project'],
'ML': ['Project'], 'Project': [],
}
for i, lv in enumerate(semesters(courses), 1):
print(f"Semester {i}: {lv}")
Replace the deque in Kahn's algorithm with a min-heap (heapq).
At every step you then take the smallest ready node. The simulator's "min-heap" option shows this.
Cost: O((V + E) log V) instead of O(V + E).
Complexity
| Method | Time | Extra Space | Finds Cycles? | Nice Extra |
|---|---|---|---|---|
| Kahn's (queue) | O(V + E) | O(V) for in-degree + queue | Yes — leftover nodes | Gives levels (parallel steps) |
| Kahn's (min-heap) | O((V + E) log V) | O(V) | Yes | Smallest-first (lexicographic) order |
| DFS-based | O(V + E) | O(V) for colours + stack | Yes — back edge | Shows the exact cycle edge |
Where Topological Sorting Is Used
Golden Rules
RecursionError.