AlgoMaster Logo

Introduction to Topological Sort

High Priority8 min readUpdated July 4, 2026
Listen to this chapter
Unlock Audio

Topological Sort is a graph algorithm that arranges elements of a Directed Acyclic Graph (DAG) in a linear order that respects dependencies between them. If task A must be completed before task B, A appears before B in the output.

This chapter covers:

  • What topological sort is
  • How it works
  • When to use it
  • Two ways to implement it (DFS and Kahn's algorithm)

What is Topological Sort?

Topological sort answers a single question: In what order should we process a set of elements when some of them depend on others?

It applies to problems that can be modeled as a Directed Acyclic Graph (DAG): a graph with directed edges and no cycles. The "no cycles" requirement matters because a cycle means two elements each depend on the other, so neither can come first, and no valid linear order exists.

The goal is to produce a linear ordering of vertices such that: for every directed edge u → v, vertex u appears before vertex v in the final sequence.

For example, consider this dependency graph:

  • A depends on B
  • B depends on C
  • D has no dependencies

A valid topological ordering would be: C→B→A→D.

Two properties are worth stating:

  • Topological sort works only on DAGs. If the graph has even one cycle, a valid ordering cannot exist.
  • There may be more than one valid topological order for the same graph. In the example above, D has no dependencies, so it can appear anywhere in the sequence.

When to use Topological Sorting?

Topological sort is used whenever items must be processed in an order that respects dependencies.

Common examples include:

  • Task Scheduling - When some tasks cannot start until others are finished.
  • Course planning - where you need to determine a valid order to take courses when some of them have prerequisites.
  • Compilers - Compilers use topological sorting to analyze dependencies between functions, modules, and files to determine execution order.
  • Package Managers: Libraries like NPM and pip use topological sorting to install dependencies in the correct order.

How to Implement Topological Sorting

There are two common ways to implement topological sort:

  • Using Depth-First Search (DFS)
  • Using Breadth-First Search (Kahn's Algorithm)

METHOD 1: DFS Approach

DFS explores each path to its deepest point before backtracking. This guarantees that all dependencies of a node are fully processed before the node itself. We record each node after its DFS call finishes, then reverse the order at the end.

We use a stack to collect finished nodes:

  • We run DFS from each unvisited node.
  • After exploring all children of a node, we push it onto the stack.
  • The correct topological order is the reverse of the order DFS finishes nodes in. Since a stack is LIFO, popping elements gives us the correct order directly.

DFS-based topological sort can be implemented recursively or iteratively with an explicit stack. We will use the recursive form here.

For this graph, the DFS traversal might visit nodes in the order A → B → C → D. The ordering depends on two details of the algorithm:

  • Nodes are pushed to the stack during backtracking, not during the first visit. This gives the reversed finish order.
  • Popping from the stack then yields a valid topological sequence.

The time complexity is O(V + E), since each vertex is visited once and each edge is examined once during the traversal. The space complexity is O(V) for the visited array, the stack of finished nodes, and the recursion stack.

The second approach uses BFS instead of DFS. It is called Kahn's Algorithm.

METHOD 2: BFS Approach - Kahn’s Algorithm

Kahn’s Algorithm is an iterative, queue-based method for topological sorting.

It repeatedly removes nodes with no incoming edges (no unmet dependencies), building a valid order as it goes.

Kahn’s Algorithm is based on the following idea:

If a node has no incoming edges (or prerequisites), it can be processed first. Removing it reduces the indegree of its neighbors; any neighbor for which indegree drops to 0 is processed in the next iteration.

Here’s how it works step-by-step:

Step 1: Compute in-degree for each node

The indegree of a node is the number of incoming edges (or dependencies) pointing to it. A node with indegree 0 has no unmet dependencies, so it is safe to process immediately.

For example, in this graph:

  • The indegree of node 0 is 0
  • For node 1 it’s 1, since it depends on node 0
  • For node 2 it’s 1, since it depends on node 1
  • For node 3 it’s 2, since it depends on both node 1 and node 2

Step 2: Identify Nodes with 0 Indegree

Any node with 0 indegree can be processed first, since it has no dependencies.

Add these ready-to-process nodes to a queue.

Step 3: Process Nodes using BFS

While the queue isn't empty:

  • Remove a node from the queue and add it to our result list
  • For each of its neighbors:
    • Reduce their indegree by 1 (since we've processed one of their dependencies)
    • If any neighbor's indegree becomes 0, add it to the queue

This ensures each node is only processed after all its prerequisites have been handled.

At the end, if the result contains fewer than V nodes, the graph isn’t a DAG (there’s a cycle), so no topological order exists.

Loading simulation...

Here’s how to implement it in code:

The time complexity is O(V + E), as each vertex and edge is processed exactly once during the traversal.

The space complexity is O(V), required for storing the indegree array, result list, and BFS queue.

If all nodes are processed, the result is a valid topological order.

If some nodes remain unprocessed, the graph contains a cycle and no topological order exists.

Kahn's algorithm has two practical differences from the DFS-based approach:

  1. It is iterative, so it avoids the recursion-stack depth limit. On very deep graphs (long chains of dependencies), recursive DFS can hit the runtime stack limit and crash. The asymptotic memory is the same: both approaches use O(V) auxiliary space (queue and indegree array vs. visited array and recursion stack).
  2. It detects cycles as a natural byproduct: if the final result contains fewer than V nodes, a cycle exists. DFS-based topological sort can also detect cycles with one extra boolean array (onPath or three-color WHITE/GRAY/BLACK marking), but it is not automatic the way Kahn's is.

Complexity Analysis

Time Complexity

Both the DFS approach and Kahn's algorithm run in O(V + E). Each vertex is processed exactly once and each edge is examined exactly once. The DFS approach visits every adjacency entry as it traverses the graph, and Kahn's algorithm decrements an in-degree once per edge while draining the queue. Computing the in-degrees in Kahn's algorithm also takes O(V + E), since it initializes V counters and scans every edge once, so this preprocessing step does not change the overall bound.

Space Complexity

Both approaches need O(V + E) space to store the graph as an adjacency list, plus O(V) auxiliary space. The auxiliary space holds the visited array or the in-degree array, the queue or the recursion stack, and the output ordering, each of which grows with the number of vertices. If the input graph storage is excluded from the count, the auxiliary space is O(V).

Key Takeaways

  • A topological sort produces a linear ordering of a directed graph's vertices so that for every directed edge u → v, vertex u appears before vertex v in the sequence.
  • Topological sort applies only to a Directed Acyclic Graph, because a cycle creates a circular dependency for which no valid linear order exists.
  • The DFS approach pushes each node onto a stack after exploring all of its neighbors, then pops the stack to read off a valid order, which is the reverse of the order in which DFS finishes nodes.
  • Kahn's algorithm computes the indegree of every node, enqueues all nodes with indegree 0, and repeatedly removes a node while decrementing its neighbors' indegrees, enqueuing any neighbor whose indegree reaches 0.
  • Kahn's algorithm detects a cycle when the result contains fewer than V nodes, while the DFS approach needs extra marking to catch cycles.
  • Both approaches run in O(V + E) time and O(V) space, and a single graph can have more than one valid topological ordering.

Quiz

Introduction Quiz

10 quizzes