intermediate8 min read·Updated October 1, 2026
Topological Sort Explained: Valid vs Cyclic Course Schedules
Master topological sort by tracing Kahn's algorithm on valid course prerequisites versus a 2-cycle. Get mental models, dry runs, and edge cases.
By Learnisim AI·Published October 1, 2026
LEARNING ARCSetup → Model in the example → Full trace → Twist → Edge cases → Apply
PREREQUISITES
- Directed graphs and adjacency lists
- Queue data structure basics
- In-degree concept
Why
Why Course Schedules Fall Apart Without Topological Sort
Phase 1: The Scheduling Nightmare
Imagine you are an academic advisor trying to register a student for a set of four required classes (
numCourses = 4). The university catalog gives you a strict list of prerequisites represented as pairs where means you must take course before course . Your prerequisite list is [[1,0], [2,0], [3,1], [3,2]].If you try to build a schedule by guessing or picking courses at random, you will quickly hit walls. Course
1 needs course 0 first. Course 2 also needs course 0 first. Course 3 needs both course 1 and course 2 finished before it can begin. Without a systematic method, you might accidentally schedule course 3 too early, violating the rules and leaving the student stranded.Now consider a worse scenario: a minor catalog typo introduces a circular dependency between two courses, resulting in the 2-cycle
[[1,0], [0,1]]. Course 1 requires course 0, but course 0 requires course 1. A naive scheduler would loop infinitely trying to find a starting point that can never exist. We need a principled way to detect whether a valid linear ordering exists at all, and if so, how to find it.Model
Mapping Dependencies to Directed Acyclic Graphs
Phase 2: The Core Mental Model
To figure out if our
numCourses = 4 with prerequisites [[1,0],[2,0],[3,1],[3,2]] can actually be completed, we must stop thinking about them as a messy list and start visualizing them as a Directed Acyclic Graph (DAG). In this model, every course is a node (or vertex), and every prerequisite pair [a, b] becomes a directed edge pointing from b to a. This arrow means: b must be finished before a can start.Let us map our locked example to this graph structure:
- Course
- Course
- Course
- Course
- Course
0 has no incoming edges.- Course
1 depends on 0 (edge ).- Course
2 depends on 0 (edge ).- Course
3 depends on both 1 and 2 (edges and ).Now, contrast this cleanly organized tree-like dependency flow with our second scenario:
numCourses = 2 with prerequisites [[1,0],[0,1]]. Here, course 1 requires course 0 (), but course 0 simultaneously requires course 1 (). This creates a closed loop, or a cycle, making it mathematically impossible to satisfy everyone first.In-Degrees and Dependency Counting
Another vital piece of our model is the in-degree of a node: a count of how many incoming arrows point directly at it. A course with an in-degree of
0 has zero unsatisfied prerequisites. It is immediately ready to take right now. As we complete courses, we cross them off and reduce the in-degree of their neighboring downstream courses.Worked example
Tracing Kahn's Algorithm on a Valid Graph Versus a Cycle
Phase 3: Walking the Nodes
Now that we have modeled our courses as a directed graph, let's run Kahn's algorithm on our locked working example:
numCourses = 4 with prerequisites [[1,0], [2,0], [3,1], [3,2]]. We will also trace what happens when a dependency cycle is introduced via [[1,0], [0,1]].Given
- Graph A (DAG):numCourses = 4, edges [[1,0], [2,0], [3,1], [3,2]]- Graph B (Cycle):
numCourses = 2, edges [[1,0], [0,1]]Steps for Graph A (DAG)
1.Build Adjacency List & Indegree Array:
- Adjacency list:
0: [1, 2], 1: [3], 2: [3], 3: []- Indegree counts (incoming edges):
indegree = [0, 1, 1, 2]2.Initialize Queue:
- Find all nodes with
indegree == 0. Queue = [0]. Order = [].3.Process Queue (Iteration 1):
- Pop
0. Order becomes [0]. Neighbors of 0 are 1 and 2.- Decrement indegrees:
indegree[1] becomes 0, indegree[2] becomes 0.- Push newly zeroed nodes to queue: Queue =
[1, 2].4.Process Queue (Iteration 2 & 3):
- Pop
1. Order becomes [0, 1]. Decrement neighbor 3's indegree (indegree[3] drops from 2 to 1). Queue = [2].- Pop
2. Order becomes [0, 1, 2] (or [0, 2, 1] depending on queue pop order). Decrement neighbor 3's indegree (indegree[3] drops from 1 to 0). Push 3 to queue: Queue = [3].- Pop
3. Order becomes [0, 1, 2, 3]. Queue = [].5.Completion Check:
- Total processed nodes = 4, which equals
numCourses. Steps for Graph B (Cycle)
1.Build Adjacency List & Indegree Array:
- Adjacency list:
0: [1], 1: [0]- Indegree counts:
indegree = [1, 1]2.Initialize Queue:
- No node has
indegree == 0. Queue = []. Order = [].3.Completion Check:
- Queue is empty immediately, but total processed nodes = . The algorithm terminates early and reports failure.
Result
- Graph A succeeds, returning a valid topological order like[0, 1, 2, 3].- Graph B fails because the cycle traps all nodes at
indegree = 1, leaving the queue permanently empty.Try this: Given numCourses = 3 and prerequisites = [[1,0],[2,1],[0,2]], trace the initial indegree array and explain why Kahn's algorithm will fail to produce a valid course schedule.
Practice
Predicting Kahn's Algorithm on a Disconnected DAG Plus a Cycle
Phase 4: Practice
Now that you have seen how Kahn's algorithm processes our standard DAG , and detects the failure of a pure 2-cycle , , it is time to test your understanding on a hybrid graph.
Imagine we modify our setup to with the prerequisite list:
[[1,0], [3,2], [4,3], [3,4]]. Notice that courses 0 and 1 form a valid independent dependency chain, while courses 2, 3, and 4 contain a sub-cycle between 3 and 4.Work through the queue initialization, the indegree decrement steps, and the final processed count to determine what Kahn's algorithm will output for this graph.
Apply
Applying Topological Sort to Task Pipelines and Build Systems
Phase 5: Build System Compilation Order
Now that we have mastered how Kahn's algorithm processes dependencies like versus a cyclic trap like , let's transfer this exact mental model to a different domain: software compilation pipelines.
Imagine you are building a package manager or a Makefile generator. A complex project has multiple source files and libraries that depend on each other. If library
libB requires header files from libA, then libA must compile before libB. This is identical to our course schedule: libB has an incoming dependency from libA, mirroring edge [libB, libA] where libA must complete first.When a developer adds a circular dependency between two modules (e.g., module imports module and imports ), the build system fails with a circular dependency error. Under the hood, the compiler is running our exact topological sort logic: building an adjacency list, computing indegrees, pushing zero-indegree entry points to a queue, and checking if the total processed count matches the total number of modules.
Practical Generalization
Any time you encounter a set of items with directional precedence constraints, you are dealing with a Directed Acyclic Graph. Whether scheduling university courses, ordering database migrations, or resolving package versions in
npm or pip, the core invariants remain invariant: sources with zero prerequisites act as your initial queue, and any cycle leaves stranded nodes with indegrees greater than zero.FAQ
How does Kahn's algorithm determine if the course schedule [[1,0],[2,0],[3,1],[3,2]] is valid?
It computes in-degrees for all 4 courses, queues nodes with 0 in-degree (course 0), and iteratively removes them while decrementing neighbor in-degrees, successfully ordering all 4 courses.
What happens when Kahn's algorithm encounters the 2-cycle [[1,0],[0,1]]?
Courses 0 and 1 will both have an in-degree of 1 and never enter the zero-in-degree queue. The algorithm finishes with fewer processed nodes than total courses, signaling a cycle and returning false.
What is the time and space complexity of topological sorting using Kahn's algorithm?
The time complexity is O(V + E) where V is the number of courses and E is the prerequisites, because we visit every vertex and edge. Space complexity is O(V + E) to store the adjacency list and in-degree array.
Can topological sort be performed on a graph with cycles?
No. A topological sort requires a Directed Acyclic Graph (DAG). If a cycle exists, there is no linear ordering where every directed edge goes from a preceding node to a succeeding node.