Topological Sort
Definition
Topological Sort is a linear ordering of vertices in a Directed Acyclic Graph (DAG). The rule is simple: For every directed edge from vertex U to vertex V, vertex U must come before vertex V in the ordering.

Note: This only works if the graph has NO cycles. If there is a cycle (A needs B, B needs A), you cannot sort them.
How it Works
Think of this as a To-Do List with Prerequisites.
- Find a task that has zero prerequisites (no arrows pointing to it).
- “Do” that task (add to sorted list).
- Cross it off. Now, look at the tasks that were waiting for it. If any of them now have zero remaining prerequisites, they are ready to be done next.
- Repeat.
Real-World Analogy
University Course Prerequisites:
- You cannot take Calculus II until you pass Calculus I.
- You cannot take Physics until you pass Calculus I.
- Topological Sort: Calculus I $\rightarrow$ Physics $\rightarrow$ Calculus II. (This is a valid valid order because dependencies are respected).
Example
Dependencies:
- A rightarrow C
- B rightarrow C
- C rightarrow D
Valid Sort: A, B, C, D OR B, A, C, D. (A and B have no dependencies, so either can go first. But C must wait for both, and D must wait for C).
Code Example (Kahn’s Algorithm – BFS Approach)
PythonJavaCC++
from collections import deque
# Topological Sort using Kahn's Algorithm
def topological_sort(vertices, edges):
# Create graph and indegree array
graph = {i: [] for i in range(vertices)}
indegree = {i: 0 for i in range(vertices)}
for u, v in edges:
graph[u].append(v)
indegree[v] += 1
# Queue for nodes with indegree 0
queue = deque([node for node in indegree if indegree[node] == 0])
result = []
while queue:
node = queue.popleft()
result.append(node)
for neighbor in graph[node]:
indegree[neighbor] -= 1
if indegree[neighbor] == 0:
queue.append(neighbor)
# Cycle detection
if len(result) != vertices:
return "Graph has a cycle! Cannot Sort."
return result
# Example
edges = [(0,2), (1,2), (2,3)]
print("Topological Sort:", topological_sort(4, edges))
import java.util.*;
public class TopologicalSort {
static List<Integer> topoSort(int vertices, int[][] edges) {
List<List<Integer>> graph = new ArrayList<>();
int[] indegree = new int[vertices];
for (int i = 0; i < vertices; i++)
graph.add(new ArrayList<>());
for (int[] e : edges) {
graph.get(e[0]).add(e[1]);
indegree[e[1]]++;
}
Queue<Integer> q = new LinkedList<>();
for (int i = 0; i < vertices; i++)
if (indegree[i] == 0)
q.add(i);
List<Integer> result = new ArrayList<>();
while (!q.isEmpty()) {
int node = q.poll();
result.add(node);
for (int neighbor : graph.get(node)) {
indegree[neighbor]--;
if (indegree[neighbor] == 0)
q.add(neighbor);
}
}
if (result.size() != vertices)
System.out.println("Graph has a cycle!");
return result;
}
public static void main(String[] args) {
int[][] edges = {{0,2},{1,2},{2,3}};
System.out.println("Topological Sort: " +
topoSort(4, edges));
}
}
#include <stdio.h>
#define V 4
int graph[V][V] = {0};
void addEdge(int u, int v) {
graph[u][v] = 1;
}
void topologicalSort() {
int indegree[V] = {0};
for (int i = 0; i < V; i++)
for (int j = 0; j < V; j++)
if (graph[i][j])
indegree[j]++;
int queue[V], front = 0, rear = 0;
for (int i = 0; i < V; i++)
if (indegree[i] == 0)
queue[rear++] = i;
while (front < rear) {
int node = queue[front++];
printf("%d ", node);
for (int i = 0; i < V; i++) {
if (graph[node][i]) {
indegree[i]--;
if (indegree[i] == 0)
queue[rear++] = i;
}
}
}
}
int main() {
addEdge(0,2);
addEdge(1,2);
addEdge(2,3);
printf("Topological Sort:\n");
topologicalSort();
return 0;
}
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
vector<int> topoSort(int V, vector<pair<int,int>> edges) {
vector<vector<int>> graph(V);
vector<int> indegree(V,0);
for (auto e : edges) {
graph[e.first].push_back(e.second);
indegree[e.second]++;
}
queue<int> q;
for (int i = 0; i < V; i++)
if (indegree[i] == 0)
q.push(i);
vector<int> result;
while (!q.empty()) {
int node = q.front();
q.pop();
result.push_back(node);
for (int neighbor : graph[node]) {
indegree[neighbor]--;
if (indegree[neighbor] == 0)
q.push(neighbor);
}
}
return result;
}
int main() {
vector<pair<int,int>> edges = {
{0,2},{1,2},{2,3}
};
vector<int> result = topoSort(4, edges);
cout << "Topological Sort: ";
for (int x : result)
cout << x << " ";
return 0;
}
Complexity Analysis
- Time Complexity: O(V + E). We process every node and every edge exactly once.
- Space Complexity: O(V). We need an array for Indegrees and a Queue.
Use Cases & Interview Relevance
- Build Systems (Makefiles/Maven/Gradle): Determining which files to compile first. If File B imports File A, A must be compiled first.
- Task Scheduling: Operating systems scheduling jobs that depend on each other.
- React/Frontend Initialization: Deciding the order to load components or scripts.
- Interview Tip: If a question mentions “prerequisites,” “dependencies,” or “ordering tasks,” it is almost 100% a Topological Sort question.