Data Structure 📂 Simulators · 4 of 4 60 min read

Topological Sorting for DAGs — Kahn's Algorithm and DFS-Based Sort (Interactive Simulator)

Topological sorting puts the nodes of a DAG in an order where every arrow points forward, like putting on socks before shoes. Kahn's algorithm uses in-degrees and a queue. The DFS method pushes finished nodes on a stack and reverses it. Draw a graph, run each step, spot cycles, and build your own valid order.

Section 01

The Story — Getting Dressed in the Right Order

You Cannot Wear Shoes Before Socks
Every morning you solve a small puzzle. Socks must go on before shoes. Pants go on before the belt. The shirt goes on before the tie, and the tie before the jacket. Your watch can go on at any time.

Draw each item as a node. Draw an arrow A → B when A must come before B. Now find an order to put on every item so that every arrow points forward.

That order is a topological order. Finding it is called topological sorting.

Topological sorting works on a DAG: a Directed Acyclic Graph. "Directed" means edges have arrows. "Acyclic" means you can never follow arrows and come back to where you started. If there is a cycle (A before B, B before C, C before A), no valid order exists.

➡️
Edge = "must come before"
u → v
An edge from u to v means u must appear earlier than v in the final list.
📥
In-degree
arrows coming in
How many things must happen before this node. In-degree 0 means "no prerequisites, ready to go".
🔀
Many Correct Answers
not unique
A DAG often has many valid orders. Watch or socks first? Both are fine. The simulator can count them for you.
💡
Two Classic Methods

Kahn's algorithm (BFS-style): keep taking a node with in-degree 0. Remove it and its arrows. Repeat.
DFS-based: go deep. When a node has no more places to go, it is "finished". Push it on a stack. Reading the stack from top to bottom gives the order.


Section 02

Watch It Work — Animated Diagram

The getting-dressed graph. Pick Kahn to watch in-degree counters (the small badges) drop to zero. Pick DFS to watch nodes finish from the deepest one upwards. The order is built at the bottom.

🎬 Getting Dressed — Live Animation

Both answers are correct, even though they look different. Check any arrow: its start always comes earlier in the list.


Section 03

The Topological Sort Simulator — Build Your Own DAG

Draw tasks and the arrows between them. Run Kahn's or DFS one step at a time. Watch the queue and in-degree table, or the call stack and finish stack. You can also play My Order: click nodes in your own order, and the simulator stops you if you break a rule.

👉 How to Use the Simulator
Draw
Add Node: click an empty spot. Drag to move. Double-click to rename (up to 8 characters).
Arrow
Add Edge: click the node that comes first, then the node that comes after.
Run
Pick an algorithm. Press Step, Play or End. Use Back to rewind.
Game
My Order mode: click nodes one by one to build your own valid order.
🔄 Topological Sort Simulator Not started
Draw
Load
Algorithm
Speed
Queue
In-degree Table
Algorithm — Current Line
What Is Happening
    🎯 Predict
    ● Blue = current node ● Amber = in queue / on DFS path (GRAY) ● Green = placed / finished (BLACK) ● Red = part of a cycle ■ Badge = current in-degree → Faded arrow = already removed (Kahn)
    🧪
    Try These Experiments

    1. Classic 6 Nodes: type your guess for Kahn's output first, then check. Do the same for DFS.
    2. Press Count Valid Orders. The classic graph has 13 valid orders. Kahn and DFS each find just one of them.
    3. Course Plan + Kahn: the last step shows the levels. These are the fewest semesters needed.
    4. Has a Cycle: Kahn gets stuck with nodes left over. DFS finds a back edge to a GRAY node.
    5. My Order mode: try to put Shoes before Socks. The simulator will stop you.


    Section 04

    Kahn's Algorithm — Step by Step

    Graph: 5→2, 5→0, 4→0, 4→1, 2→3, 3→1. Starting in-degrees: 0:2, 1:2, 2:1, 3:1, 4:0, 5:0.

    StepDequeueIn-degree ChangesQueue AfterOrder So Far
    0—Nodes with in-degree 0: 4, 5[4, 5]—
    140: 2→1 · 1: 2→1[5]4
    250: 1→0 (enqueue) · 2: 1→0 (enqueue)[0, 2]4, 5
    30no outgoing edges[2]4, 5, 0
    423: 1→0 (enqueue)[3]4, 5, 0, 2
    531: 1→0 (enqueue)[1]4, 5, 0, 2, 3
    61no outgoing edges[ ]4, 5, 0, 2, 3, 1
    ⚠️
    How Kahn Detects a Cycle

    Nodes in a cycle wait for each other forever. Their in-degree never reaches 0, so they never enter the queue. When the queue is empty, check: if the order has fewer than V nodes, the graph has a cycle.

    DFS-Based Sort — Step by Step (same graph)

    Visit FromPath Walked (GRAY)Finished (pushed to stack)Stack (bottom → top)
    000 (no out-edges)[0]
    111[0, 1]
    22 → 3 (1 is already BLACK)3, then 2[0, 1, 3, 2]
    3already BLACK — skip—[0, 1, 3, 2]
    44 (0 and 1 are BLACK)4[0, 1, 3, 2, 4]
    55 (0 and 2 are BLACK)5[0, 1, 3, 2, 4, 5]
    Pop from top to bottom5, 4, 2, 3, 1, 0
    🧠
    Why Reversing the Finish Order Works

    A node finishes only after everything it points to has finished. So for any edge u → v, v finishes before u. Reverse the finish list and u comes before v. That is exactly the rule we need.

    🌊 Kahn's (BFS-style)
    FeatureDetail
    ContainerQueue of ready nodes
    Key ideaIn-degree reaches 0 → ready
    Builds orderFront to back
    Cycle checkFewer than V nodes placed
    🧳 DFS-based
    FeatureDetail
    ContainerCall stack + result stack
    Key ideaNode finishes after its children
    Builds orderBack to front (reverse)
    Cycle checkEdge to a GRAY node (back edge)

    Section 05

    Python Implementation

    1. Kahn's Algorithm

    from collections import deque
    
    graph = {5: [2, 0], 4: [0, 1], 2: [3], 3: [1], 0: [], 1: []}
    
    def kahn(graph):
        indeg = {u: 0 for u in graph}
        for u in graph:                        # count incoming arrows
            for v in graph[u]:
                indeg[v] += 1
        queue = deque(sorted(u for u in graph if indeg[u] == 0))
        order = []
        while queue:
            u = queue.popleft()
            order.append(u)
            for v in sorted(graph[u]):       # "remove" u's arrows
                indeg[v] -= 1
                if indeg[v] == 0:
                    queue.append(v)          # v is now ready
        if len(order) < len(graph):
            raise ValueError("Cycle found! No topological order.")
        return order
    
    print("Kahn order:", kahn(graph))
    OUTPUT
    Kahn order: [4, 5, 0, 2, 3, 1]

    2. DFS-Based Topological Sort (with cycle check)

    WHITE, GRAY, BLACK = 0, 1, 2        # not seen, on path, finished
    
    def dfs_topo(graph):
        color = {u: WHITE for u in graph}
        stack = []
    
        def visit(u):
            color[u] = GRAY
            for v in sorted(graph[u]):
                if color[v] == GRAY:           # back edge
                    raise ValueError(f"Cycle found at edge {u} -> {v}")
                if color[v] == WHITE:
                    visit(v)
            color[u] = BLACK
            stack.append(u)                    # u is finished
    
        for u in sorted(graph):
            if color[u] == WHITE:
                visit(u)
        print("Finish order:", stack)
        return stack[::-1]                       # reverse
    
    print("DFS order:", dfs_topo(graph))
    
    try:
        dfs_topo({'A': ['B'], 'B': ['C'], 'C': ['A']})
    except ValueError as e:
        print("Error:", e)
    OUTPUT
    Finish order: [0, 1, 3, 2, 4, 5] DFS order: [5, 4, 2, 3, 1, 0] Error: Cycle found at edge C -> A

    3. Bonus — Minimum Number of Semesters (Kahn by levels)

    def semesters(graph):
        indeg = {u: 0 for u in graph}
        for u in graph:
            for v in graph[u]:
                indeg[v] += 1
        level = sorted(u for u in graph if indeg[u] == 0)
        result = []
        while level:
            result.append(level)                 # everything ready now
            nxt = []
            for u in level:
                for v in graph[u]:
                    indeg[v] -= 1
                    if indeg[v] == 0:
                        nxt.append(v)
            level = sorted(nxt)
        return result
    
    courses = {
        'Python': ['DS', 'Web'], 'Math': ['DS', 'ML'], 'DS': ['Algo', 'DBMS'],
        'Algo': ['ML'], 'DBMS': ['Project'], 'Web': ['Project'],
        'ML': ['Project'], 'Project': [],
    }
    for i, lv in enumerate(semesters(courses), 1):
        print(f"Semester {i}: {lv}")
    OUTPUT
    Semester 1: ['Math', 'Python'] Semester 2: ['DS', 'Web'] Semester 3: ['Algo', 'DBMS'] Semester 4: ['ML'] Semester 5: ['Project']
    ⚡
    Want the Alphabetically Smallest Order?

    Replace the deque in Kahn's algorithm with a min-heap (heapq). At every step you then take the smallest ready node. The simulator's "min-heap" option shows this. Cost: O((V + E) log V) instead of O(V + E).


    Section 06

    Complexity

    MethodTimeExtra SpaceFinds Cycles?Nice Extra
    Kahn's (queue)O(V + E)O(V) for in-degree + queueYes — leftover nodesGives levels (parallel steps)
    Kahn's (min-heap)O((V + E) log V)O(V)YesSmallest-first (lexicographic) order
    DFS-basedO(V + E)O(V) for colours + stackYes — back edgeShows the exact cycle edge
    Why V + E?
    each node once, each edge once
    Every node is dequeued (or visited) one time. Every arrow is looked at one time.
    Sum of In-degrees
    Σ indeg(v) = E
    Each arrow adds 1 to exactly one node's in-degree. So Kahn does exactly E decrements in total.

    Section 07

    Where Topological Sorting Is Used

    📦
    Package Managers
    pip, npm and apt install the dependencies first, then the package that needs them.
    dependency resolution
    🔨
    Build Systems
    Make, Maven and Gradle compile files in an order where every import is built first.
    compile order
    🎓
    Course Planning
    Take every prerequisite before the course that needs it. Kahn by levels gives the fewest semesters.
    university timetables
    📊
    Spreadsheets
    When a cell changes, Excel recalculates dependent cells in topological order. A cycle shows a "circular reference" warning.
    formula evaluation
    🧠
    Deep Learning
    TensorFlow and PyTorch run the layers of a computation graph in topological order. Backprop runs it in reverse.
    computation graphs
    🚧
    Project Scheduling
    Task A must finish before task B starts. Topological order plus durations gives the critical path.
    PERT / CPM, Airflow DAGs

    Section 08

    Golden Rules

    🏆 Topological Sort — Rules to Remember
    1
    Topological order exists only for DAGs. Any cycle makes it impossible.
    2
    For every edge u → v, u must appear before v. Use this rule to check any answer by hand.
    3
    Kahn: start with all in-degree-0 nodes. Each time a node's in-degree hits 0, add it to the queue.
    4
    Kahn cycle check: if fewer than V nodes come out, a cycle exists.
    5
    DFS: push a node after all its neighbours finish. Then reverse the finish list.
    6
    DFS cycle check: use three colours. An edge to a GRAY node (still on the path) means a cycle. An edge to a BLACK node is fine.
    7
    The answer is usually not unique. Different tie-breaks give different, equally correct orders.
    8
    Both methods run in O(V + E). For very deep graphs in Python, prefer Kahn to avoid RecursionError.
    You have completed Simulators. View all sections →