Breadth First Search and Depth First Search
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 the two core graph traversal strategies used in interviews and real systems alike. They both visit connected nodes efficiently, yet they produce different orderings and guarantees. Picking the right one depends on what answer you need, such as shortest path, cycle detection, or component discovery.
Core Difference: Queue Versus Stack Behavior
BFS explores neighbors level by level from a starting node. It uses a queue, so closer nodes are processed before farther nodes.
DFS explores one branch deeply, then backtracks. It uses recursion or an explicit stack.
That single design difference drives the main tradeoffs:
- BFS finds shortest path by edge count in unweighted graphs.
- DFS is convenient for tasks that depend on traversal state and backtracking.
If you remember one rule, remember this: BFS is nearest-first, DFS is depth-first.
BFS Example with Distances
The code below computes shortest hop distance from a source node to all reachable nodes.
The first time BFS discovers a node, it has already found the minimum number of edges from the source in an unweighted graph.
DFS Example with Iterative Stack
This DFS uses an explicit stack to avoid recursion limits in deep graphs.
DFS is a natural fit for branch-oriented exploration and algorithms that need entry and exit semantics.
Typical Use Cases in Practice
Use BFS when you need:
- shortest path by number of edges
- level-order expansion
- nearest reachable target
Use DFS when you need:
- cycle detection
- topological sort style workflows
- connected-component or strongly-connected analyses
- path existence with backtracking logic
Both are often part of bigger algorithms. For example, topological sort and articulation point detection are DFS-heavy, while multi-source expansion and shortest steps in grids are BFS-heavy.
Complexity and Memory Profile
For adjacency-list graphs, BFS and DFS both run in O(V + E) time, where V is number of vertices and E is number of edges.
Memory behavior differs:
- BFS uses a queue that can grow to graph frontier width.
- DFS uses stack depth that can grow to traversal depth.
In very wide graphs, BFS can consume more memory. In very deep graphs, recursive DFS can hit recursion limits.
Reconstructing a Shortest Path with BFS
Distance values are useful, but real applications often need the actual path. Track parent pointers while traversing.
This is one of the most common practical BFS patterns.
DFS for Cycle Detection in Directed Graphs
DFS can detect directed cycles with color states.
This pattern is concise and scales well to large dependency graphs.
Common Pitfalls
A frequent bug is forgetting a visited set, which creates infinite loops on cyclic graphs.
Another mistake is using DFS where shortest unweighted path is required. DFS can find a path, but not guaranteed shortest by edges.
Recursive DFS can fail on deep inputs due to call stack depth. Use iterative DFS for unbounded depth scenarios.
Traversal order can also vary by neighbor ordering. If deterministic output matters, define neighbor ordering explicitly.
Finally, developers sometimes stop after one traversal in disconnected graphs. To cover all nodes, loop through every node and start traversal for unvisited ones.
Summary
- BFS and DFS are both fundamental
O(V + E)traversal algorithms. - BFS is best for nearest-first exploration and shortest unweighted paths.
- DFS is best for depth-oriented analysis and cycle-related logic.
- Queue and stack behavior drive practical memory tradeoffs.
- Correct visited handling and deterministic neighbor policy prevent many bugs.

