DFS
BFS
Graph Traversal
Search Algorithms
Computer Science

Depth First Search and Breadth First Search Understanding

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Breadth First Search and Depth First Search are foundational graph traversal techniques, but they optimize for different outcomes. BFS explores nodes by distance layers, while DFS explores one path deeply before backtracking. Choosing correctly depends on whether you care most about shortest hop distance, structural analysis, or memory behavior on your graph shape.

Core Behavior Difference

The main difference is data structure choice:

  • BFS uses a queue.
  • DFS uses a stack or recursion.

That single decision determines traversal order and common use cases.

In unweighted graphs, BFS naturally finds shortest paths in number of edges. DFS does not guarantee shortest path, but it is excellent for deep exploration tasks such as cycle checks and component discovery.

BFS Implementation in Python

A standard BFS implementation tracks visited nodes and processes first-in-first-out order.

python
1from collections import deque
2
3
4def bfs_order(graph, start):
5    visited = {start}
6    q = deque([start])
7    order = []
8
9    while q:
10        node = q.popleft()
11        order.append(node)
12
13        for nxt in graph.get(node, []):
14            if nxt not in visited:
15                visited.add(nxt)
16                q.append(nxt)
17
18    return order
19
20
21graph = {
22    "A": ["B", "C"],
23    "B": ["D", "E"],
24    "C": ["F"],
25    "D": [],
26    "E": ["F"],
27    "F": []
28}
29
30print(bfs_order(graph, "A"))

BFS is usually the first choice for minimum-hop routing in unweighted networks.

DFS Implementation in Python

DFS can be implemented recursively or iteratively. Iterative form avoids recursion depth limits in large graphs.

python
1def dfs_order(graph, start):
2    stack = [start]
3    visited = set()
4    order = []
5
6    while stack:
7        node = stack.pop()
8        if node in visited:
9            continue
10
11        visited.add(node)
12        order.append(node)
13
14        for nxt in reversed(graph.get(node, [])):
15            if nxt not in visited:
16                stack.append(nxt)
17
18    return order
19
20print(dfs_order(graph, "A"))

DFS is often preferred for structure-oriented tasks rather than shortest path.

Shortest Path in Unweighted Graphs with BFS

If a problem asks for least number of edges, BFS with parent tracking gives the shortest path.

python
1from collections import deque
2
3
4def bfs_shortest_path(graph, start, goal):
5    q = deque([start])
6    parent = {start: None}
7
8    while q:
9        node = q.popleft()
10        if node == goal:
11            break
12
13        for nxt in graph.get(node, []):
14            if nxt not in parent:
15                parent[nxt] = node
16                q.append(nxt)
17
18    if goal not in parent:
19        return []
20
21    path = []
22    cur = goal
23    while cur is not None:
24        path.append(cur)
25        cur = parent[cur]
26
27    return list(reversed(path))
28
29print(bfs_shortest_path(graph, "A", "F"))

DFS cannot provide that guarantee without exploring extra paths.

Complexity and Memory Tradeoffs

For full traversal, both algorithms are O(V + E).

Practical differences:

  • BFS memory can spike on wide frontier-heavy graphs.
  • DFS memory can spike on very deep graphs.

Graph shape matters as much as asymptotic complexity when choosing between them.

Determinism and Testing

Traversal order depends on neighbor ordering. If adjacency lists come from unordered sources, output order can vary between runs.

For deterministic tests, sort neighbors before visiting.

python
for nxt in sorted(graph.get(node, [])):
    ...

Stable order makes snapshot tests and debugging easier.

Selection Guide

Choose BFS when:

  • You need shortest hop path in an unweighted graph.
  • You need level-by-level expansion.
  • You need nearest match behavior.

Choose DFS when:

  • You need deep structural exploration.
  • You need cycle or component analysis.
  • You need traversal logic that naturally backtracks.

If edges have weights, use algorithms such as Dijkstra instead of plain BFS or plain DFS.

Common Pitfalls

  • Using DFS for shortest-path problems in unweighted graphs.
  • Forgetting visited tracking and entering infinite cycles.
  • Using recursive DFS on deep graphs without considering recursion limits.
  • Assuming one fixed order without controlling adjacency ordering.
  • Ignoring graph shape when evaluating memory behavior.

Summary

  • BFS and DFS both traverse graphs in linear time relative to nodes plus edges.
  • BFS is best for shortest hop paths and level traversal.
  • DFS is best for deep exploration and structural graph tasks.
  • Queue versus stack behavior drives practical differences.
  • Pick algorithm based on objective, graph shape, and determinism requirements.

Course illustration
Course illustration

All Rights Reserved.