Topological Sort Operations
Node
Edge→
Run
100%
Ctrl + scroll to zoom
Order a directed acyclic graph - see nodes arranged so all edges point forward.
Time O(V + E) · Space O(V)
from typing import Dict, Set, List, Any
def toposort(graph: Dict[Any, Set[Any]]) -> List[Any]:
"""
Topological sort using DFS (reverse post-order).
Args:
graph: Adjacency list for directed graph {node: {successors}}
Returns:
List of nodes in topological order
Raises:
ValueError: If graph contains a cycle
"""
visited = set()
in_stack = set() # For cycle detection
result = []
def _dfs(node: Any) -> None:
if node in in_stack:
raise ValueError(f"Graph contains a cycle involving node '{node}'")
if node in visited:
return
in_stack.add(node)
for neighbor in graph.get(node, set()):
_dfs(neighbor)
in_stack.remove(node)
visited.add(node)
result.append(node) # Add after all descendants processed
for node in graph:
if node not in visited:
_dfs(node)
return result[::-1] # Reverse for correct order
# Example usage and demonstration
if __name__ == "__main__":
# Example DAG (course prerequisites)
#
# A ──→ B ──→ D
# │ │
# ↓ ↓
# C ──→ E
#
example_dag = {
"A": {"B", "C"},
"B": {"D", "E"},
"C": {"E"},
"D": set(),
"E": set(),
}
print("Topological Sort (DFS):", toposort(example_dag))
# Example with cycle
cyclic_graph = {
"A": {"B"},
"B": {"C"},
"C": {"A"},
}
try:
toposort(cyclic_graph)
except ValueError as e:
print(f"Cycle detected: {e}")
Topological sort produces a linear ordering of vertices in a directed acyclic graph (DAG) such that for every directed edge (u, v), vertex u comes before v. It is essential for dependency resolution and scheduling problems.
DFS approach: perform DFS and push each vertex onto a stack after all its descendants are processed; the reverse gives topological order. Kahn's approach: repeatedly remove vertices with no incoming edges (in-degree 0) and add them to the result.