BFS vs DFS
BFS vs DFS broken down with side-by-side traces on the same graph. Know exactly which traversal to pick for any interview problem.
What you will learn
How BFS and DFS maintain different invariants using queue vs stack
Why BFS guarantees shortest path in unweighted graphs but DFS does not
A side-by-side trace of both algorithms on the same graph
When to use BFS for minimum steps vs DFS for cycle detection
Most engineers treat BFS vs DFS as a matter of preference. Two ways to visit every node, pick whichever you remember. That works until an interview problem punishes the wrong choice with a time limit exceeded or a missing shortest path guarantee.
They aren't variations of the same idea. They maintain different invariants, use different collections, and solve different classes of problems. Which one you pick comes down to which invariant the problem requires.
What BFS and DFS Actually Do
Breadth-first search processes all nodes at distance 1 from the source before any node at distance 2, all nodes at distance 2 before distance 3, and so on. It uses a queue to maintain this distance-order invariant. You get a level-by-level sweep outward from the starting node.
Depth-first search processes a single path as deep as possible before backtracking. It uses a stack (or the call stack via recursion) to remember where it came from. One branch gets fully exhausted before another is tried.
That distinction sounds academic until it costs you an interview. BFS's distance-order invariant means the first time it reaches a node, that path is guaranteed to be the shortest (in unweighted graphs). DFS makes no such guarantee. It might reach a node through a 7-edge path before finding a 2-edge path. BFS can't miss the shorter route because it processes all 2-edge paths before any 7-edge path.
DFS does something else entirely. Because it fully explores one branch before starting another, it naturally detects back edges (cycles), computes finish times (topological ordering), and identifies connected components. BFS's level-by-level sweep doesn't expose these properties as cleanly.
Both Algorithms on the Same Graph
Take a graph with 6 nodes and edges 0→1, 0→2, 1→3, 1→4, 2→4, 2→5. The source node is 0.
BFS trace, using a queue.
`
Step 1: Queue = [0] → Process 0, enqueue 1, 2
Step 2: Queue = [1, 2] → Process 1, enqueue 3, 4
Step 3: Queue = [2, 3, 4] → Process 2, enqueue 5 (4 already visited)
Step 4: Queue = [3, 4, 5] → Process 3 (no new neighbours)
Step 5: Queue = [4, 5] → Process 4 (no new neighbours)
Step 6: Queue = [5] → Process 5 (no new neighbours)
`The visit order is 0, 1, 2, 3, 4, 5. All nodes appear in exact distance order from the source. Everything at distance 1 (nodes 1, 2) comes before distance 2 (nodes 3, 4, 5).
DFS trace, using a stack.
`
Step 1: Stack = [0] → Process 0, push 2, 1
Step 2: Stack = [2, 1] → Process 1, push 4, 3
Step 3: Stack = [2, 4, 3] → Process 3 (no new neighbours)
Step 4: Stack = [2, 4] → Process 4 (no new neighbours)
Step 5: Stack = [2] → Process 2, push 5
Step 6: Stack = [5] → Process 5 (no new neighbours)
`The visit order is 0, 1, 3, 4, 2, 5. Node 3 (distance 2) gets processed before node 2 (distance 1). DFS doesn't prioritize distance at all. It cares about depth, committing to one branch and exhausting it before backtracking.
“Same graph, same starting node, different data structure, different visit order. The queue creates a distance guarantee. The stack doesn't.”
Why the Data Structure Matters
The queue is the entire reason BFS works for shortest paths. A queue is first-in, first-out. When you enqueue all neighbours at distance d, they sit behind any remaining distance d-1 nodes but ahead of all future distance d+1 nodes. The queue enforces distance ordering without any explicit distance tracking.
The stack is last-in, first-out. When you push neighbours, the most recently pushed node gets processed next. That's what creates the depth-first behaviour. You keep diving deeper along whichever neighbour was pushed last, and you don't come back to earlier choices until the current path is exhausted. Memory follows the same split.
BFS stores the entire frontier at once. In a balanced tree with branching factor b and depth d, BFS holds O(b^d) nodes in the queue at the widest level. DFS holds at most O(d) nodes on the stack, one per level of depth. For deep, narrow graphs, DFS is far more memory efficient. For shallow, wide graphs, either works.
DFS also has an elegance in recursive form that BFS doesn't match. When you write DFS recursively, the call stack is the stack. You don't manage any explicit collection. The function calls handle backtracking automatically. That recursive form maps cleanly onto problems with recursive character: trees, expressions, nested configurations. BFS doesn't have an equivalent recursive form because queues aren't built into the call stack. That's why DFS often feels more natural when the problem itself is recursive.
When to Use BFS vs DFS
It comes down to what the problem is asking for.
Use BFS when the problem needs:
- Shortest path in an unweighted graph. Minimum steps in a grid, shortest word transformation, nearest distance to a target. If the problem says "minimum" and every edge has equal weight, BFS is the answer.
- Level-order processing. Anything that requires processing nodes layer by layer (binary tree level order traversal, finding all nodes at distance K).
- Nearest neighbour or closest target. BFS finds the closest match first because it explores in distance order.
Use DFS when the problem needs:
- Cycle detection. DFS tracks which nodes are currently on the recursion stack. A back edge to a node still on the stack means a cycle exists. BFS can detect cycles too, but DFS's stack-based tracking is more natural for directed graphs.
- Topological ordering. DFS finish times, reversed, give a valid topological sort for directed acyclic graphs. This is the standard algorithm.
- Connected components. Run DFS from an unvisited node and mark everything reachable. Run again from the next unvisited node. Each run discovers one component.
- Exhaustive path enumeration. Backtracking problems, source-to-target paths, and Hamiltonian paths all use DFS because it explores one complete path before trying alternatives.
Two Interview Problems, Two Traversal Choices
Problem 1, minimum steps in a grid. You're given a 2D grid where 0 is passable and 1 is a wall. Find the minimum number of steps from the top-left corner to the bottom-right corner, moving in four directions.
This is a BFS problem. Every move has equal weight (one step), so BFS's distance-order guarantee applies. You enqueue the starting cell, then process level by level. The first time you reach the destination, you've found the shortest path. If you tried DFS here, it might find a path of length 30 before a path of length 8. DFS has no mechanism to prefer shorter paths.
Problem 2, detect a cycle in a directed graph. Given a directed graph, determine whether it contains a cycle.
This is a DFS problem. You track three states per node: unvisited, in-progress (on the current recursion stack), and completed. If DFS reaches a node that's still in-progress, you've found a back edge, which means a cycle. The recursion stack naturally maintains this "currently being explored" state. BFS can detect cycles in undirected graphs by checking parent relationships, but for directed graphs, DFS's stack-based state tracking is the standard approach.
The same question applies to every graph problem. Does the problem need a distance guarantee or a graph property? Distance guarantee points to BFS. Graph property (cycles, ordering, connectivity) points to DFS.
Going Deeper
Every graph pattern you'll hit in interviews (connected components, two colouring, Dijkstra's algorithm, topological sort) builds on one or both of these traversals.
Codeintuition's Graph course traces both algorithms frame by frame with 289 illustrations, then builds five pattern families on top of them. The BFS traversal lesson walks through the queue state at every step, and the DFS pattern identification lesson trains you to recognise which problems require depth-first exploration before you start coding.
Do you want to master data structures?
Try our data structures learning path made of highly visual and interactive courses. Get hands on experience by solving real problems in a structured manner. All resources you would ever need in one place for FREE