Skip to main content

Topological Sort

Topological sort is a linear ordering of the vertices of a directed acyclic graph (DAG) such that for every directed edge uv from vertex u to vertex v, u comes before v in the ordering.

Every DAG has at least one topological order; cyclic graphs have none. Two standard algorithms compute it:

  • Kahn's algorithm (BFS-style). Repeatedly remove a vertex with in-degree zero.
  • DFS post-order. Run DFS from every unvisited vertex and push each vertex onto a stack after its recursion finishes. Reverse the stack.

Both run in linear time. Kahn's algorithm additionally detects cycles (if the queue empties before all vertices are emitted, the remaining vertices form at least one cycle).

Codes

This is a sample code for topological sort using DFS on a forward star graph.

public LinkedList<Integer> topologicalSortDFS(ForwardStar E, int start, int Vsize) {
/**
* Topological sort using DFS
* @param E: ForwardStar
* @param start: start vertex
* @param Vsize: size of the vertex
* @return: list of sorted vertices
*/
LinkedList<Integer> result = new LinkedList<Integer>();
Stack<Integer> stack = new Stack<Integer>();
stack.add(start);
boolean[] checked = new boolean[Vsize];
checked[start] = true;
while (!stack.isEmpty()) {
LinkedList<int[]> tempEdge = E.get(stack.peek());
boolean addnew = false;
for (int[] i : tempEdge) {
if (!checked[i[1]]) {
stack.add(i[1]);
checked[i[1]] = true;
addnew = true;
break;
}
if (!addnew) {
result.addFirst(stack.pop());
}
}
}
return result;
}

Example

Loading Python runner...

Description

Run time analysis

O(V+E)O(V + E). Building the adjacency list and the in-degree array is O(V+E)O(V + E). The main loop dequeues every vertex exactly once and relaxes every edge exactly once, so it is also O(V+E)O(V + E).

Space analysis

O(V+E)O(V + E) for the adjacency list, plus O(V)O(V) for the in-degree array and the queue. The DFS variant replaces the queue with the recursion stack, which is O(V)O(V) in the worst case.

Proof of correctness

Call a valid topological order a linear extension of the DAG's reachability partial order. We prove Kahn's algorithm produces one.

Claim. At the moment a vertex uu is enqueued, all of its in-neighbours have already been emitted.

Proof. A vertex is enqueued only when its in-degree has just dropped to zero. The in-degree drops only when we process one of uu's in-neighbours and decrement along the edge into uu. Since we initialise indeg[u] to the true in-degree of uu, it reaches zero exactly when every in-neighbour has been dequeued — and hence emitted — before uu.

Claim. Every vertex is eventually emitted, provided the graph is a DAG.

Proof. A DAG has at least one source (a vertex with in-degree zero): pick the smallest vertex in any topological ordering of what's left. So the initial queue is nonempty. After emitting a source, the induced subgraph is still a DAG, so it still has a source, which is exactly a neighbour whose in-degree has just been decremented to zero. By induction on V|V|, the process empties the graph.

Together, the two claims say the emission order respects every edge, and every vertex is emitted — i.e. the output is a valid topological order.

Extensions

Applications

References