Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Depth-First Search (DFS)

Explore one path deeply before backtracking, so you can trace structure, follow branches, and reason about stack-like traversal behavior.

DFS is the natural contrast to BFS. Instead of expanding outward one layer at a time, it commits to a path, goes as far as it can, and only then backs up to try another branch.

graph = {
    "A": ["B", "C", "D"],
    "B": ["E", "F"],
    "C": ["G"],
    "D": ["H"],
    "E": [],
    "F": [],
    "G": [],
    "H": [],
}
visited = []

def dfs(node):
    if node in visited:
        return

    visited.append(node)
    for neighbor in graph[node]:
        dfs(neighbor)

dfs("A")
print("DFS visit order:", visited)
DFS visit order: ['A', 'B', 'E', 'F', 'C', 'G', 'D', 'H']

DFS follows a branch deeply, then backs up when it hits the end

BFS taught level-by-level exploration with a queue. DFS changes the rhythm completely: follow one path as far as possible, backtrack when no new neighbor remains, and continue from the most recent unfinished branch.

Core Explanation

DFS follows a branch deeply before returning. It is often used in traversal, path finding, recursion practice, cycle reasoning, and situations where exploring one complete possibility before trying the next is useful.

Read the figure without code
  • the node labels show one valid DFS order

  • the red branch shows the first deep dive from A through B to its children

  • DFS does not visit C or D until it has finished the unfinished work under B

  • the later blue nodes appear only after backtracking has returned to the start area

Because neighbor order can change, DFS can have multiple valid visit orders on the same graph.

DFS intuition
BFS contrast
Where it helps

Think of walking through a maze by choosing one corridor and continuing until you must turn back.

Continuity from BFS

BFS emphasized queues and frontier expansion by level. DFS emphasizes stack behavior, recursion, and backtracking. The graph structure is the same; only the exploration strategy changes.

Worked Example and Practice Lab

Iterative DFS with an explicit stack

Expected output
Iterative DFS order: ['A', 'B', 'E', 'F', 'C', 'G', 'D', 'H']

This version makes the LIFO stack behavior explicit: the most recently discovered unfinished branch is the next one explored.

Recursive DFS

Expected output
Recursive DFS order: ['A', 'B', 'E', 'F', 'C', 'G', 'D', 'H']

Recursive trace: entering, base case, and closing stack frames

What to notice
  • each recursive call goes one layer deeper into the call stack

  • the base case appears when there is no new neighbor left to explore

  • the closing messages appear while the stack unwinds back toward the starting node

Exercises

  1. Explain why DFS is more naturally associated with a stack than a queue.

  2. Describe what backtracking means in your own words.

  3. Give one reason a DFS visit order can differ from BFS on the same graph.

  4. Name one situation where exploring deeply before returning could be useful.

Hint

Focus on which node gets processed next: the oldest discovered node or the most recently discovered unfinished node.

Guided Practice

QueueA queue is more aligned with BFS.
StackCorrect. DFS explores deeply using stack behavior.
Dictionary onlyThe dictionary stores the graph, not the traversal order.
Set onlyA visited set helps, but the traversal structure is stack-like.

Why can DFS have more than one valid visit order on the same graph?

Because DFS ignores edgesDFS still follows the graph edges carefully.
Because the neighbor order can change which branch is explored firstCorrect. DFS depends on which neighbor is chosen next, so multiple valid orders can exist.
Because DFS always visits nodes randomlyDFS is systematic, not random.
Because DFS never backtracksBacktracking is one of DFS's defining behaviors.

Key Takeaway

DFS follows one path deeply before backtracking, which makes it a strong contrast to BFS and a useful stepping stone toward later graph reasoning. The next notebook, Dijkstra’s algorithm, shifts again: not just exploring a graph, but choosing the cheapest path when edges carry weights.