Article written by Kuldeep Pant, under the guidance of Neeraj Jhawar, a Senior Software Development Manager and Engineering Leader. Reviewed by Manish Chawla, a problem-solver, ML enthusiast, and an Engineering Leader with 20+ years of experience.
Topological Sort is an algorithm that orders the vertices of a directed acyclic graph (DAG) into a linear sequence so that every directed edge u→v means u appears before v in the order.
In practice, this sorting resolves dependencies in graphs. For example, scheduling tasks with prerequisites, arranging course requirements, or determining build order for software modules. Because it considers edge directions, topological sort finds a valid sequence that respects all constraints in the DAG.
In the following sections, we will see how to compute a topological ordering using algorithmic methods. Specifically, we will examine both the Depth-First based and Kahn’s Breadth-first Search (BFS) approaches for topological sort, along with their pseudocode and complexity.
These methods will show how each vertex is placed only after all its prerequisites, ensuring the dependency graph is correctly linearised.
Topological sort of a directed acyclic graph (DAG) is a linear ordering of its vertices such that for every directed edge (u → v), vertex u comes before v in the ordering. This definition implies a strict dependency order:
If there is an edge indicating “u must come before v,” then in the topologically sorted list, u precedes v.
In concise terms, topological sort arranges all nodes so that each node appears after all nodes that have edges pointing to it. Topological ordering is only possible when the graph has no cycles. In fact, a valid topological order exists if and only if the graph is acyclic.
If any directed cycle is present, then no linear ordering can satisfy all edge directions. For example, u→v→w→u.
Thus, topological sort requires a DAG and immediately detects impossible cases. If the graph is acyclic, there is guaranteed to be at least one topological ordering. When a graph is a DAG, there may be multiple valid topological orders. In other words, the ordering is not necessarily unique.
Any arrangement that respects all edge directions is acceptable. For example, if two nodes have no path between them, they can appear in either order. All such valid sequences are considered topological sorts of the graph.
A topological sort operates on a directed acyclic graph (DAG). Here, vertices can represent tasks or entities, and directed edges encode precedence constraints. The goal is to list all vertices so that every edge (dependency) points from an earlier vertex to a later one.
By definition, a topological ordering exists if and only if the graph has no directed cycles. Each cycle would create a mutual dependency loop that cannot be linearly ordered.
To illustrate, imagine a simple DAG with edges A→B and A→C. Valid topological orders include [A, B, C] and [A, C, B] – in both, A comes before B and C. However, if there were an edge back from B to A (forming a cycle A→B→A), no ordering would satisfy both constraints, so that topological sort would fail. In general, topological sort is widely used in dependency resolution problems.
For example, building software modules where some modules depend on others, scheduling university courses with prerequisites, or ordering tasks in project management are all modeled as topological sorts on a graph. In each case, performing the topological sort ensures that a task (vertex) appears only after all its prerequisites.
Topological Sort is especially useful whenever one task must be completed before another. It helps convert a dependency-based graph into a clear execution order, making it highly practical in real-world systems where sequencing matters.
Some of the most common applications of the topological sort algorithm include:
Determines the correct order of tasks when some tasks depend on others. It also helps identify which tasks can run in parallel and which must wait.
Ensures that source files, libraries, or modules are compiled only after all their dependencies are resolved, preventing build-time errors.
Organizes courses so that foundational subjects are completed before advanced ones, maintaining a valid academic progression.
Used in package managers and data pipelines to resolve dependencies and execute processes in the correct sequence.
Helps structure complex workflows in areas like data engineering, CI/CD pipelines, and project planning.
Topological Sort works by arranging the vertices of a Directed Acyclic Graph (DAG) so that every directed edge goes from an earlier vertex to a later one. In practice, that means the algorithm always respects dependencies.
A node is placed in the ordering only after the nodes it depends on have been handled. A graph can be topologically sorted only if it has no directed cycles.
There are two standard ways to build the ordering. The topological sort DFS approach uses depth-first traversal and records a node after all of its outgoing neighbors have been processed; the topological sort BFS approach uses Kahn’s algorithm, which repeatedly removes nodes with in-degree 0 and updates their neighbors. Both methods produce a valid ordering for a DAG.
Kahn’s Algorithm is the BFS-based method for topological sort. It begins by counting the number of incoming edges for each node, then repeatedly selects nodes that have no prerequisites. This is the most direct way to build a valid order because every removed node is guaranteed to be safe to place next.
Here’s a step-by-step breakdown of Kahn’s Algorithm.
Topological Sort fails on cyclic graphs because a cycle creates a circular dependency. If one node must come before the next node in the cycle, and the last node must come before the first, no linear order can satisfy all constraints at once. In other words, a topological ordering exists only for DAGs, not for graphs with directed cycles.
For Kahn’s Algorithm, the failure is visible immediately. Every node in a directed cycle has at least one incoming edge from another node in the same cycle, so no node in the cycle can start with an in-degree of 0.
If the graph contains only cyclic dependencies, the queue never gets a starting node, and the algorithm stops before producing a full ordering.
Example cycle: A → B → C → A
| Node | Incoming edges | In-degree |
| A | C → A | 1 |
| B | A → B | 1 |
| C | B → C | 1 |
Since no node has an in-degree of 0, Kahn’s Algorithm cannot begin. That is exactly why cyclic graphs do not have a valid topological order.
Consider this DAG:
This graph has no cycles, so Topological Sort is possible. Using Kahn’s Algorithm, we first calculate in-degrees, then process nodes with in-degree 0. The order is not always unique, but it must always respect every dependency edge.
| Node | Incoming edges | In-degree |
| A | none | 0 |
| B | none | 0 |
| C | A, B | 2 |
| D | C | 1 |
| E | D | 1 |
Now apply Kahn’s Algorithm step by step:
Also Read: Find the Order of Characters From an Alien Dictionary Problem
Topological Sort is a dependency-ordering algorithm for a directed acyclic graph (DAG). It produces a linear ordering of vertices such that for every directed edge u → v, vertex u appears before vertex v. A valid topological order exists only when the graph has no directed cycles.
At a high level, the logic is simple.
Find a way to place all nodes so that every prerequisite comes before the node that depends on it. The two standard approaches are topological sort DFS, which pushes a node after exploring all of its outgoing neighbors, and topological sort BFS, which uses Kahn’s algorithm to repeatedly remove nodes with in-degree 0.
Both approaches run in linear time, O(V + E), because each vertex and edge is processed a constant number of times.
Before looking at implementation details, it helps to understand the structure of the topological sort pseudocode itself. Process every node in a way that respects its dependencies, then place it in the ordering only when its prerequisites have already been handled.
The DFS version builds the order in reverse finishing-time order, while the BFS version follows Kahn’s algorithm and removes zero-in-degree vertices one by one.
TopologicalSort_DFS(graph):
visited = set()
stack = empty stack
for each vertex v in the graph:
if v not in visited:
DFS(v)
return stack reversed
DFS(v):
Mark v as visited
for each neighbor n of v:
if n not in visited:
DFS(n)
push v onto stack
TopologicalSort_Kahn(graph):
inDegree = array of size V initialized to 0
queue = empty queue
order = empty list
for each edge u -> v in graph:
inDegree[v]++
for each vertex v:
if inDegree[v] == 0:
enqueue(queue, v)
while queue is not empty:
u = dequeue(queue)
append u to order
for each neighbor n of u:
inDegree[n]--
if inDegree[n] == 0:
enqueue(queue, n)
if length(order) != V:
report "graph has a cycle."
else:
return order
To better understand how the topological sort algorithm works in practice, it is useful to look at a concrete implementation. Writing code helps translate the conceptual steps, like managing degrees and processing dependencies, into an executable form.
The following examples demonstrate how topological sorting can be implemented using a queue-based approach, making the dependency resolution process explicit and easy to follow.
import java.util.*;
public class TopologicalSortKahn {
public static List<Integer> topologicalSort(int vertices, int[][] edges) {
List<List<Integer>> graph = new ArrayList<>();
for (int i = 0; i < vertices; i++) {
graph.add(new ArrayList<>());
}
int[] indegree = new int[vertices];
for (int[] edge : edges) {
int u = edge[0];
int v = edge[1];
graph.get(u).add(v);
indegree[v]++;
}
Queue<Integer> queue = new ArrayDeque<>();
for (int i = 0; i < vertices; i++) {
if (indegree[i] == 0) {
queue.offer(i);
}
}
List<Integer> order = new ArrayList<>();
while (!queue.isEmpty()) {
int node = queue.poll();
order.add(node);
for (int neighbor : graph.get(node)) {
indegree[neighbor]--;
if (indegree[neighbor] == 0) {
queue.offer(neighbor);
}
}
}
if (order.size() != vertices) {
throw new IllegalArgumentException("Graph contains a cycle; topological sort is not possible.");
}
return order;
}
public static void main(String[] args) {
int vertices = 6;
int[][] edges = {
{5, 2}, {5, 0}, {4, 0}, {4, 1}, {2, 3}, {3, 1}
};
List<Integer> result = topologicalSort(vertices, edges);
System.out.println(result);
}
from collections import deque
def topological_sort(vertices, edges):
graph = [[] for _ in range(vertices)]
indegree = [0] * vertices
for u, v in edges:
graph[u].append(v)
indegree[v] += 1
queue = deque()
for node in range(vertices):
if indegree[node] == 0:
queue.append(node)
order = []
while queue:
node = queue.popleft()
order.append(node)
for neighbor in graph[node]:
indegree[neighbor] -= 1
if indegree[neighbor] == 0:
queue.append(neighbor)
if len(order) != vertices:
raise ValueError("Graph contains a cycle; topological sort is not possible.")
return order
if __name__ == "__main__":
vertices = 6
edges = [(5, 2), (5, 0), (4, 0), (4, 1), (2, 3), (3, 1)]
print(topological_sort(vertices, edges))
For the sample graph above, one valid output is:
[4, 5, 2, 0, 3, 1]
Another valid ordering may also exist, because a DAG can have more than one correct topological order. The only rule is that every directed edge must still go from left to right in the final sequence.
Topological Sort complexity describes how the algorithm’s running time and extra memory use grow as the graph gets larger. For the standard implementations on a Directed Acyclic Graph (DAG), the key result is that both DFS-based topological sort and Kahn’s BFS-based topological sort process each vertex and each edge a constant number of times.
So, the overall time complexity is linear in the size of the graph.
The time complexity of Topological Sort is O(V + E), where V is the number of vertices and E is the number of edges. In a DFS-based approach, each vertex is visited once, and each directed edge is explored once during traversal.
In Kahn’s algorithm, you first compute in-degrees, then repeatedly remove zero in-degree nodes and update their neighbors, which still touches each vertex and edge a constant number of times.
A simple real-world example is a course prerequisite graph. If a curriculum has 100 courses and 250 prerequisite links, the algorithm does not compare every course with every other course. It only processes the 100 courses and the 250 prerequisite relationships, which is exactly why the runtime scales as O(V + E), not O(V²).
| Approach | Time Complexity | Why |
| DFS-based Topological Sort | O(V + E) | Visits each vertex once and each edge once during recursive traversal. |
| BFS-based Topological Sort (Kahn’s Algorithm) | O(V + E) | Computes in-degrees, then processes each node and edge once as dependencies are removed. |
The space complexity of Topological Sort is typically O(V) for the algorithm’s extra working memory. In DFS-based topological sort, this comes from the visited structure and the recursion stack.
In Kahn’s algorithm, this comes from the queue, the in-degree array, and the output list. If you also count the adjacency-list graph storage itself, the full representation of the graph uses O(V + E) space, but that is the graph’s storage cost, not the algorithm’s extra auxiliary memory.
A practical way to picture this is with a build system. The graph stores modules and dependency links, while the algorithm keeps only the currently relevant modules in memory. The recursion path for DFS or the zero-in-degree queue for Kahn’s algorithm.
That is why space usage stays linear in the number of vertices rather than exploding with the number of possible node pairs.
| Approach | Auxiliary Space | Main Contributors |
| DFS-based Topological Sort | O(V) | visited array + recursion stack + output structure. |
| BFS-based Topological Sort (Kahn’s Algorithm) | O(V) | in-degree array + queue + output list. |
Topological Sort is strongest when a problem can be modeled as dependencies in a Directed Acyclic Graph (DAG). It gives a valid linear order for tasks, builds, courses, and other prerequisite-driven workflows, and it does so efficiently in O(V + E) time for standard DFS- and BFS-based implementations.
It is also practical in build systems and dependency-resolution tools, including Make-like workflows, because it helps ensure prerequisites are processed before dependent items.
Its main limitation is that it only works on DAGs. If the graph contains a directed cycle, no valid topological ordering exists because the dependencies become circular.
Topological Sort also does not always return a unique order; when multiple vertices have no incoming edges, several valid sequences may exist. For very large graphs, the algorithm is still linear, but the graph storage and traversal overhead can become heavy in practice because the adjacency structure itself uses memory proportional to the graph size.
| Pros | Cons |
| Produces a valid dependency order for DAGs, so prerequisite tasks appear before dependent tasks. This is why it works well for task scheduling, course ordering, build order, and dependency resolution. | Cannot be applied to cyclic graphs, because a cycle creates circular dependencies that no linear order can satisfy. |
| Runs in linear time, O(V + E), which is efficient for sparse dependency graphs and standard workflow pipelines. | For very large graphs, the algorithm can still feel costly in practice because it must store and traverse the graph structure, which adds memory and processing overhead. |
| Fits real-world systems such as software build pipelines, task schedulers, and Makefile-style dependency resolution. | The result is not always unique, so different traversal choices can produce different valid orders. That can make reproducibility more nuanced in scheduling and building workflows. |
| Kahn’s algorithm also makes cycle detection straightforward: if not all vertices can be processed, the graph contains a cycle. | It is less suitable when dependencies change frequently, because the ordering may need to be recomputed after graph updates. |
Understanding Topological Sort is just one part of mastering graph algorithms and dependency-based problem solving. To truly apply concepts like the topological sort algorithm, topological sort DFS, and topological sort BFS in real scenarios, you need structured practice, expert guidance, and real-world problem exposure.
The Software Engineering Interview Prep course by Interview Kickstart is designed to help you build exactly that level of confidence and depth.
If you’re serious about mastering algorithms and applying them effectively, consider this as your next step.
Topological Sort is a core graph technique for turning dependency-heavy problems into a valid linear order. It works only on directed acyclic graphs (DAGs), and it is especially useful in task scheduling, software build order, course prerequisite ordering, and other dependency-resolution workflows.
In practice, the two standard implementations are the DFS-based approach and Kahn’s BFS-based algorithm, both of which run in linear time relative to the graph size. If a cycle exists, no valid topological ordering is possible.
For practical use, think of Topological Sort as the method you reach for when one step must happen before another. That is why it fits build systems, package dependency resolution, and scheduled pipelines so well.
A topological sort can be performed using both DFS and BFS. The DFS-based method adds nodes after exploring their descendants, while the BFS-based method uses Kahn’s algorithm to remove nodes with in-degree 0 repeatedly.
Not in the classic sense. Topological Sort is mainly a graph ordering algorithm. Kahn’s algorithm makes locally valid choices by picking nodes with no incoming edges, but it is usually described as a dependency-resolution method rather than a standard greedy algorithm.
BFS, through Kahn’s algorithm, is often preferred when you want an iterative approach that is easier to trace and naturally detects cycles using in-degree counts. It is especially useful when you want to process nodes level by level as dependencies become available.
Topological Sort is useful for problems with prerequisites and dependency chains, such as task scheduling, build order, course prerequisite ordering, and dependency resolution in software systems. It helps ensure every item appears only after the items it depends on.
Yes, Topological Sort can produce multiple valid orderings. If at any step there are multiple nodes with no incoming edges (in-degree 0), the algorithm can choose any of them next. As long as all dependency constraints are satisfied, each resulting sequence is a correct topological ordering.
Related Articles:
Time Zone:
100% Free — No credit card needed.
Time Zone:
Master AI tools and techniques customized to your job roles that you can immediately start using for professional excellence.
Master ML, Deep Learning, and AI Agents with hands-on projects, live mentorship—plus FAANG+ interview prep.
Master Agentic AI, LangChain, RAG, and ML with FAANG+ mentorship, real-world projects, and interview preparation.
Learn to scale with LLMs and Generative AI that drive the most advanced applications and features.
Learn the latest in AI tech, integrations, and tools—applied GenAI skills that Tech Product Managers need to stay relevant.
Dive deep into cutting-edge NLP techniques and technologies and get hands-on experience on end-to-end projects.
Get your enrollment process started by registering for a Pre-enrollment Webinar with one of our Founders.
Time Zone:
Join 25,000+ tech professionals who’ve accelerated their careers with cutting-edge AI skills
25,000+ Professionals Trained
₹23 LPA Average Hike 60% Average Hike
600+ MAANG+ Instructors
Webinar Slot Blocked
Register for our webinar
Learn about hiring processes, interview strategies. Find the best course for you.
ⓘ Used to send reminder for webinar
Time Zone: Asia/Kolkata
Time Zone: Asia/Kolkata
Hands-on AI/ML learning + interview prep to help you win
Explore your personalized path to AI/ML/Gen AI success
The 11 Neural “Power Patterns” For Solving Any FAANG Interview Problem 12.5X Faster Than 99.8% OF Applicants
The 2 “Magic Questions” That Reveal Whether You’re Good Enough To Receive A Lucrative Big Tech Offer
The “Instant Income Multiplier” That 2-3X’s Your Current Tech Salary