Topological Sort - Theory


What is Topological Sorting?

A Topological Sort of a directed graph is a linear ordering of its vertices such that for every directed edge u → v, vertex u comes before v in the ordering.

It answers the question:

“Given a set of dependencies, what order should tasks be performed in?”


Applications of Topological Sorting


Why is Topological Sort Only for DAGs?

Topological Sort is only defined for Directed Acyclic Graphs (DAGs). Here's why:

DAG (Directed Acyclic Graph)

Cycles Cause a Contradiction

Suppose there's a cycle:
A → B → C → A

Topological sort would require:
A < B < C < A — which is a contradiction.

Hence, topological sorting is not possible if the graph contains cycles.


Two Main Algorithms for Topological Sort

Link : Topological sort


1. Kahn’s Algorithm (BFS-Based Topological Sort)


Intuition


Steps

  1. Calculate in-degrees of all vertices.

  2. Initialize a queue with all vertices having in-degree 0.

  3. While queue is not empty:

    • Pop a node u and add to the topoSort list.

    • For each neighbor v of u:

      • inDegree[v]--

      • If inDegree[v] == 0, enqueue v

  4. If the topoSort list contains all nodes, it is a valid ordering. Otherwise, a cycle exists.


Java Code (Kahn’s Algorithm)

public class Solution {
    public int[] topoSort(int V, ArrayList<ArrayList<Integer>> adj) {
        int[] inDegree = new int[V];
        
        // Step 1: Compute in-degrees
        for (int u = 0; u < V; u++) {
            for (int v : adj.get(u)) {
                inDegree[v]++;
            }
        }

        // Step 2: Add nodes with in-degree 0 to queue
        Queue<Integer> q = new LinkedList<>();
        for (int i = 0; i < V; i++) {
            if (inDegree[i] == 0) q.add(i);
        }

        // Step 3: Process queue
        ArrayList<Integer> topo = new ArrayList<>();
        while (!q.isEmpty()) {
            int u = q.poll();
            topo.add(u);

            for (int v : adj.get(u)) {
                inDegree[v]--;
                if (inDegree[v] == 0) {
                    q.add(v);
                }
            }
        }

        // Step 4: Check for cycle
        if (topo.size() != V) return new int[0]; // cycle exists
        return topo.stream().mapToInt(i -> i).toArray();
    }
}

Dry Run (Example)

Given graph:

0 → 1
0 → 2
1 → 3
2 → 3

Final result = [0, 1, 2, 3]


2. DFS-Based Topological Sort


Intuition


Steps

  1. Maintain a visited[] array.

  2. For every unvisited node, call DFS.

  3. In DFS:

    • Mark the current node as visited

    • For every neighbor, if not visited, recurse DFS

    • After recursion, add the current node to the stack

  4. Pop the stack for the topological sort order.


Java Code (DFS Topo Sort)

public class Solution {
    public void dfs(int node, boolean[] visited, Stack<Integer> stack, ArrayList<ArrayList<Integer>> adj) {
        visited[node] = true;

        for (int v : adj.get(node)) {
            if (!visited[v]) {
                dfs(v, visited, stack, adj);
            }
        }

        stack.push(node); // post-order
    }

    public int[] topoSort(int V, ArrayList<ArrayList<Integer>> adj) {
        boolean[] visited = new boolean[V];
        Stack<Integer> stack = new Stack<>();

        for (int i = 0; i < V; i++) {
            if (!visited[i]) {
                dfs(i, visited, stack, adj);
            }
        }

        int[] result = new int[V];
        int idx = 0;
        while (!stack.isEmpty()) {
            result[idx++] = stack.pop();
        }
        return result;
    }
}

Dry Run

Same graph:

0 → 1
0 → 2
1 → 3
2 → 3

DFS:

Stack = [3, 1, 2, 0]
Reverse = [0, 2, 1, 3]


Time and Space Complexity

Approach Time Complexity Space Complexity
Kahn’s Algorithm O(V + E) O(V)
DFS-Based O(V + E) O(V)

Cycle Detection Using Topological Sort


When to Use Which?

Scenario Recommended Approach
Need to detect cycle while sorting Kahn’s Algorithm (BFS)
Stack-based recursive processing preferred DFS
Simple dependency resolution Either works