Topological Sort
Last updated
A topological sort of a directed acyclic graph (DAG) is a linear ordering of its nodes such that for every edge u → v, u comes before v. It answers questions like "in what order can I run these tasks so every prerequisite finishes first?" Press play above to watch Kahn's algorithm peel nodes off in a valid order.
Kahn's algorithm repeatedly takes a node with no remaining incoming edges (indegree 0), appends it to the order, and removes its outgoing edges - which may free up new indegree-0 nodes. It only works on a DAG: if a cycle exists, some nodes never reach indegree 0 and no valid order exists. It runs in O(V + E) time.
Time & space complexity
| Measure | Complexity | Notes |
|---|---|---|
| Time | O(V + E) | Each node emitted once, each edge removed once |
| Space | O(V) | Indegree counts + ready set + order |
| Requires | A DAG | Cycles have no topological ordering |
| Result | Not unique | Many valid orders can exist |
Step by step (Kahn's algorithm)
| Step | What happens |
|---|---|
| 1 | Compute the indegree (incoming edge count) of every node. |
| 2 | Collect all nodes with indegree 0 into a ready set. |
| 3 | Take a ready node, append it to the output order. |
| 4 | Decrement the indegree of each of its successors. |
| 5 | Any successor that reaches indegree 0 joins the ready set. |
| 6 | Repeat until the ready set is empty. |
Worked example
Sorting the DAG with edges A→C, B→C, C→D, C→E, D→F, E→F (starting indegrees A:0 B:0 C:2 D:1 E:1 F:2):
| Step | Ready set | Order | Action |
|---|---|---|---|
| 0 | {A, B} | [] | A and B start with indegree 0, so both are ready. |
| 1 | {B} | [A] | Emit A; its edge A→C drops C's indegree 2 → 1. |
| 2 | {C} | [A, B] | Emit B; its edge B→C drops C 1 → 0, so C becomes ready. |
| 3 | {D, E} | [A, B, C] | Emit C; edges C→D and C→E drop D and E to 0, both become ready. |
| 4 | {E} | [A, B, C, D] | Emit D; its edge D→F drops F's indegree 2 → 1. |
| 5 | {F} | [A, B, C, D, E] | Emit E; its edge E→F drops F 1 → 0, so F becomes ready. |
| 6 | {} | [A, B, C, D, E, F] | Emit F; ready set is empty and all 6 nodes are ordered - done. |
When to use topological sort
| Use it when | Avoid it when |
|---|---|
| You need an order that respects dependencies (build steps, package installs, course prerequisites). | The graph is undirected - topological order is only defined for directed graphs. |
| The graph is a DAG and you want any one valid linear ordering. | The graph may contain cycles and you need a total order anyway (there is none). |
| You want to detect cycles cheaply - a failed topological sort proves one exists. | You need the shortest or optimal ordering by some weight; plain topological sort ignores weights. |
You will process the ordering once in O(V + E). | Edges change constantly and you must re-sort on every update, where an incremental structure fits better. |
Topological Sort code
A clean, runnable Topological Sort implementation in Python, JavaScript, Java, C++, C. Pick a language, copy the code, or open it pre-loaded in the Coddy Playground.
Topological Sort code in Python
1from collections import deque2
3
4def topological_sort(graph):5 # Kahn's algorithm: repeatedly remove nodes with no incoming edges6 in_degree = {node: 0 for node in graph}7 for node in graph:8 for neighbor in graph[node]:9 in_degree[neighbor] += 110 queue = deque(node for node in graph if in_degree[node] == 0)11 order = []12 while queue:13 node = queue.popleft()14 order.append(node)15 for neighbor in graph[node]:16 in_degree[neighbor] -= 117 if in_degree[neighbor] == 0:18 queue.append(neighbor)19 if len(order) != len(graph):20 raise ValueError("Graph has a cycle, no topological order")21 return order22
23
24graph = {25 "shirt": ["tie", "jacket"],26 "tie": ["jacket"],27 "pants": ["shoes", "jacket"],28 "socks": ["shoes"],29 "shoes": [],30 "jacket": [],31}32
33print(" -> ".join(topological_sort(graph)))Topological Sort code in JavaScript
1const graph = {2 A: ["C"],3 B: ["C", "D"],4 C: ["E"],5 D: ["F"],6 E: ["F"],7 F: [],8};9
10// Kahn algorithm: repeatedly take a node with no incoming edges11function topologicalSort() {12 const inDegree = {};13 for (const node in graph) inDegree[node] = 0;14 for (const node in graph) {15 for (const next of graph[node]) inDegree[next]++;16 }17 const queue = Object.keys(inDegree).filter((n) => inDegree[n] === 0);18 const order = [];19 while (queue.length > 0) {20 const node = queue.shift();21 order.push(node);22 for (const next of graph[node]) {23 if (--inDegree[next] === 0) queue.push(next);24 }25 }26 if (order.length !== Object.keys(graph).length) {27 throw new Error("Graph has a cycle");28 }29 return order;30}31
32console.log("Topological order:", topologicalSort().join(" -> "));Topological Sort code in Java
1import java.util.ArrayDeque;2import java.util.List;3import java.util.Queue;4
5public class Main {6 public static void main(String[] args) {7 int n = 6;8 // DAG: an edge u -> v means u must come before v9 List<List<Integer>> adj = List.of(10 List.of(2),11 List.of(2, 3),12 List.of(4),13 List.of(4),14 List.of(5),15 List.of()16 );17 int[] inDegree = new int[n];18 for (List<Integer> next : adj) {19 for (int v : next) inDegree[v]++;20 }21
22 // Kahn: start from every node with no prerequisites23 Queue<Integer> queue = new ArrayDeque<>();24 for (int i = 0; i < n; i++) {25 if (inDegree[i] == 0) queue.add(i);26 }27
28 StringBuilder order = new StringBuilder("Topological order:");29 while (!queue.isEmpty()) {30 int node = queue.poll();31 order.append(" ").append(node);32 for (int next : adj.get(node)) {33 if (--inDegree[next] == 0) queue.add(next);34 }35 }36 System.out.println(order);37 }38}Topological Sort code in C++
1#include <iostream>2#include <queue>3#include <vector>4
5int main() {6 // Directed acyclic graph: adj[u] lists nodes that depend on u7 std::vector<std::vector<int>> adj = {8 {}, // 09 {}, // 110 {3}, // 2 -> 311 {1}, // 3 -> 112 {0, 1}, // 4 -> 0, 113 {0, 2}, // 5 -> 0, 214 };15 int n = static_cast<int>(adj.size());16 std::vector<int> inDegree(n, 0);17 for (const auto& neighbors : adj) {18 for (int v : neighbors) ++inDegree[v];19 }20 // Kahn's algorithm: start from nodes with no incoming edges21 std::queue<int> ready;22 for (int u = 0; u < n; ++u) {23 if (inDegree[u] == 0) ready.push(u);24 }25 std::cout << "Topological order: ";26 while (!ready.empty()) {27 int u = ready.front();28 ready.pop();29 std::cout << u << " ";30 // Removing u unlocks neighbors whose in-degree drops to 031 for (int v : adj[u]) {32 if (--inDegree[v] == 0) ready.push(v);33 }34 }35 std::cout << "\n";36 return 0;37}Topological Sort code in C
1#include <stdio.h>2
3#define N 64
5int main(void) {6 // Directed acyclic graph: adj[u][v] = 1 means an edge u -> v7 int adj[N][N] = {0};8 adj[2][3] = 1;9 adj[3][1] = 1;10 adj[4][0] = 1;11 adj[4][1] = 1;12 adj[5][0] = 1;13 adj[5][2] = 1;14 int inDegree[N] = {0};15 for (int u = 0; u < N; u++) {16 for (int v = 0; v < N; v++) inDegree[v] += adj[u][v];17 }18 // Kahn's algorithm: start from nodes with no incoming edges19 int queue[N];20 int head = 0, tail = 0;21 for (int u = 0; u < N; u++) {22 if (inDegree[u] == 0) queue[tail++] = u;23 }24 printf("Topological order: ");25 while (head < tail) {26 int u = queue[head++];27 printf("%d ", u);28 // Removing u unlocks neighbors whose in-degree drops to 029 for (int v = 0; v < N; v++) {30 if (adj[u][v] && --inDegree[v] == 0) queue[tail++] = v;31 }32 }33 printf("\n");34 return 0;35}Topological Sort FAQ
What is a topological sort used for?
It orders tasks so every dependency comes before the thing that needs it. Real uses include build systems and package managers (compile dependencies first), course scheduling with prerequisites, and spreadsheet formula evaluation order.
What is the time complexity of topological sort?
O(V + E) time, since each node is processed once and each edge is examined once. They use O(V) extra space.Why does topological sort require a DAG?
a must come before b and b must come before a, no linear order satisfies both. So a topological ordering exists if and only if the graph is a directed acyclic graph. Kahn's algorithm detects a cycle when it finishes before emitting every node.What is the difference between Kahn's algorithm and DFS topological sort?
O(V + E); Kahn's avoids deep recursion and reports the ready set naturally, while DFS is often shorter to write.When should I use topological sort instead of a regular sort?
O(n log n) mergesort orders by value; topological sort orders by "must come before" edges, and unlike a comparison sort it can produce many valid answers for the same input.Is the result of a topological sort unique?
Usually not. Whenever two or more nodes are ready (indegree 0) at the same time, you may emit them in any order, so most DAGs admit several valid topological orderings. The order is unique only when there is exactly one ready node at every step, which happens when the DAG forms a single chain (a Hamiltonian path).