Data Structure 📂 Simulators · 1 of 1 45 min read

BFS and DFS Graph Traversal — Interactive Learning Simulator

Learn how BFS and DFS visit every node of a graph. BFS moves level by level with a queue. DFS goes deep first with a stack or recursion. Draw your own graph, run the algorithm one step at a time, and watch the queue or stack fill and empty. Python code included.

Section 01

The Story — Two Ways to Search a Building

Looking for a Lost Phone in a Hostel
You lost your phone in a big hostel. You and your friend both start at the main gate.

You check every room close to the gate first. Then you check the rooms one step further. Then the next ring. You spread out like ripples in water. This is BFS — Breadth-First Search.

Your friend picks one corridor and walks to the very end. Only when there is nowhere left to go, they come back and try the next corridor. This is DFS — Depth-First Search.

Both of you will check every room. You just check them in a different order.

Traversal means visiting every node of a graph (or tree) one time. A graph is a set of nodes (circles) joined by edges (lines). To traverse it, we need two things: a rule for "which node next?" and a way to remember which nodes we have already seen.

💡
The One Big Idea

BFS and DFS are almost the same code. The only real difference is the waiting line. BFS uses a queue (first in, first out). DFS uses a stack (last in, first out). Change the container, and you change the whole search.


Section 02

BFS vs DFS at a Glance

🌊
BFS — Breadth-First
Queue · FIFO
Visits the start node, then all its neighbours, then their neighbours. It moves level by level. It finds the shortest path (fewest edges) in an unweighted graph.
🧳
DFS — Depth-First
Stack or Recursion · LIFO
Goes as deep as possible along one path. When it gets stuck, it backtracks and tries the next path. Good for cycles, mazes and ordering tasks.
✅
What Both Need
visited set
A graph can have cycles (loops). Without a visited set, you would go round and round forever. Both algorithms mark nodes so each is visited once.

Section 03

Watch Them Race — Animated Diagram

Same tree, same start node 1. Watch the order in which each algorithm lights up the nodes. The small number on each node shows when it was visited.

🎬 BFS vs DFS — Live Animation

BFS — level by level

DFS — deep first

BFS order: 1 → 2 → 3 → 4 → 5 → 6 → 7. DFS order: 1 → 2 → 4 → 5 → 3 → 6 → 7.


Section 04

The Traversal Simulator — Build Your Own Graph

This is your playground. Draw nodes, join them with edges, pick an algorithm, and press Step. Each click runs one line of the algorithm. You will see the queue or stack fill and empty, the current line of code, and a plain-English note of what just happened.

👉 How to Use the Simulator
Draw
Add Node mode: click an empty spot to add a node. Drag a node to move it.
Join
Add Edge mode: click one node, then another node. A line joins them.
Number
Double-click (or double-tap) any node to change its number.
Run
Pick BFS or DFS and a start node. Press Step or Play. Use Back to rewind.
🕹️ BFS / DFS Traversal Simulator Not started
Draw
Load
Algorithm Start
Speed
Queue
Visit Order
Algorithm — Current Line
What Is Happening
    🎯 Predict first
    ● Blue = current node ● Amber = waiting in queue / stack ● Green = visited ⎯ Green line = edge used to reach a node d=2 = BFS distance from start
    🧪
    Try These Experiments

    1. Load the Tree. Type your guess for DFS, then check it.
    2. Load Graph + Cycle and run BFS. Watch the d= labels. They are the shortest hop counts.
    3. Run DFS (stack) and DFS (recursion) on the same graph. The visit order is the same. Only the container changes.
    4. Draw two separate groups of nodes. See how the start node's group is visited, but the other group is not.

    ℹ️
    Neighbour Order Rule

    This simulator uses undirected edges. Neighbours are always checked from the smallest number to the largest. A different order gives a different (but still correct) traversal. In DFS with a stack, we push neighbours largest first, so the smallest one comes out first.


    Section 05

    BFS Step by Step — Trace Table

    Here is BFS on the sample tree (1 is the root; 2 and 3 are its children; 4, 5 under 2; 6, 7 under 3).

    StepDequeueAdd to QueueQueue After (front → rear)Visit Order
    0—1[1]—
    112, 3[2, 3]1
    224, 5[3, 4, 5]1, 2
    336, 7[4, 5, 6, 7]1, 2, 3
    44—[5, 6, 7]1, 2, 3, 4
    55—[6, 7]1, 2, 3, 4, 5
    66—[7]1, 2, 3, 4, 5, 6
    77—[ ]1, 2, 3, 4, 5, 6, 7

    DFS Step by Step (Stack)

    StepPopPush (largest first)Stack After (bottom → top)Visit Order
    0—1[1]—
    113, 2[3, 2]1
    225, 4[3, 5, 4]1, 2
    34—[3, 5]1, 2, 4
    45—[3]1, 2, 4, 5
    537, 6[7, 6]1, 2, 4, 5, 3
    66—[7]1, 2, 4, 5, 3, 6
    77—[ ]1, 2, 4, 5, 3, 6, 7
    ⚠️
    Common Mistake — When to Mark "Visited"

    In BFS, mark a node as seen when you add it to the queue, not when you take it out. If you wait, the same node can enter the queue many times. The answer stays right, but the work grows a lot.


    Section 06

    Python Implementation

    We store the graph as an adjacency list: each node maps to a list of its neighbours.

    BFS with a Queue

    from collections import deque
    
    graph = {
        1: [2, 3],
        2: [1, 4, 5],
        3: [1, 6, 7],
        4: [2], 5: [2], 6: [3], 7: [3],
    }
    
    def bfs(graph, start):
        visited = {start}               # mark when we enqueue
        queue = deque([start])
        order = []
        while queue:
            node = queue.popleft()      # take from the FRONT
            order.append(node)
            for n in graph[node]:
                if n not in visited:
                    visited.add(n)
                    queue.append(n)     # add to the REAR
        return order
    
    print("BFS:", bfs(graph, 1))
    OUTPUT
    BFS: [1, 2, 3, 4, 5, 6, 7]
    ⚡
    Use deque, Not list

    list.pop(0) is slow. It shifts every item, so it costs O(n). deque.popleft() costs O(1). For big graphs this makes a huge difference.

    DFS with a Stack

    def dfs_stack(graph, start):
        visited = set()
        stack = [start]
        order = []
        while stack:
            node = stack.pop()           # take from the TOP
            if node in visited:
                continue
            visited.add(node)
            order.append(node)
            for n in reversed(graph[node]):  # so smallest pops first
                if n not in visited:
                    stack.append(n)
        return order
    
    print("DFS (stack):", dfs_stack(graph, 1))
    OUTPUT
    DFS (stack): [1, 2, 4, 5, 3, 6, 7]

    DFS with Recursion

    def dfs_rec(graph, node, visited=None, order=None):
        if visited is None:
            visited, order = set(), []
        visited.add(node)
        order.append(node)
        for n in graph[node]:
            if n not in visited:
                dfs_rec(graph, n, visited, order)   # go deeper
        return order
    
    print("DFS (recursion):", dfs_rec(graph, 1))
    OUTPUT
    DFS (recursion): [1, 2, 4, 5, 3, 6, 7]
    💥
    Recursion Limit

    Python stops recursion at about 1,000 calls by default. A long chain of nodes will crash with RecursionError. For large graphs, use the stack version.

    Bonus — BFS Finds the Shortest Path

    def shortest_hops(graph, start):
        dist = {start: 0}
        queue = deque([start])
        while queue:
            node = queue.popleft()
            for n in graph[node]:
                if n not in dist:
                    dist[n] = dist[node] + 1
                    queue.append(n)
        return dist
    
    print(shortest_hops(graph, 1))
    OUTPUT
    {1: 0, 2: 1, 3: 1, 4: 2, 5: 2, 6: 2, 7: 2}

    Section 07

    Queue vs Stack — Side by Side

    🌊 BFS — Queue (FIFO)
    ActionQueue
    enqueue 2[2]
    enqueue 3[2, 3]
    dequeue2 out → [3]
    RuleOldest leaves first
    🧳 DFS — Stack (LIFO)
    ActionStack
    push 2[2]
    push 3[2, 3]
    pop3 out → [2]
    RuleNewest leaves first

    Section 08

    Time and Space Complexity

    V = number of nodes (vertices). E = number of edges.

    PropertyBFSDFS
    Time (adjacency list)O(V + E)O(V + E)
    Time (adjacency matrix)O(V²)O(V²)
    Extra spaceO(V) — queue can hold a whole levelO(V) — stack can hold a whole path
    Shortest path (unweighted)YesNo
    Memory on wide graphsHighLow
    Memory on deep graphsLowHigh
    Why V + E?
    V visits + E checks
    Each node enters the queue or stack once. Each edge is checked once from each end.
    BFS Level Rule
    d(n) = d(node) + 1
    A neighbour found from a node at distance d is at distance d + 1. This is why BFS gives shortest hops.

    Section 09

    When to Use Which

    🗺️
    Shortest Route (BFS)
    Fewest moves in a maze, fewest stops on a metro map, fewest clicks between web pages.
    unweighted shortest path
    👥
    Friends of Friends (BFS)
    "People you may know" looks at level 2 of your social graph. BFS walks it level by level.
    social networks
    🌐
    Web Crawlers (BFS)
    Crawl pages close to the home page first, then move outwards.
    search engines
    🔄
    Cycle Detection (DFS)
    If DFS reaches a node that is still on its current path, the graph has a cycle.
    deadlock checks
    📦
    Topological Sort (DFS)
    Order tasks so each comes after the tasks it depends on. Used for course plans and build tools.
    pip, npm, make
    🧩
    Puzzles and Mazes (DFS)
    Sudoku, N-Queens and maze solving try one path deeply, then backtrack.
    backtracking

    Section 10

    Golden Rules

    🏆 BFS & DFS — Rules to Remember
    1
    Queue = BFS, Stack = DFS. The container decides the order. Everything else is the same.
    2
    Always keep a visited set. Without it, a cycle makes your code loop forever.
    3
    In BFS, mark on enqueue. This stops the same node from joining the queue twice.
    4
    Need the fewest steps in an unweighted graph? Use BFS. DFS does not promise the shortest path.
    5
    Recursive DFS is short and clean. For deep graphs, switch to the stack version to avoid RecursionError.
    6
    A traversal only reaches nodes connected to the start. To cover all parts of a graph, loop over every node and start a new traversal from each unvisited one.
    7
    Both run in O(V + E) time with an adjacency list. Use a list, not a matrix, for sparse graphs.
    You have completed Simulators. View all sections →