How to keep track of depth in breadth 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 visits nodes level by level, so depth is naturally available if you carry the right state through the queue. The two standard approaches are storing (node, depth) pairs directly or processing the queue one level at a time.
Pair Each Node With Its Depth
The most explicit approach is to push both the node and its depth into the queue. When you dequeue the node, you already know how far it is from the start.
This is usually the simplest version to explain and debug because the queue state makes the depth explicit.
Process One Level at a Time
Another common pattern is to track the current level outside the queue. At each step, you process exactly the number of nodes already in the queue, because those nodes all belong to the same depth.
This pattern is especially useful when the task itself is level-based, such as printing layers of a tree or finding the minimum number of moves in an unweighted graph.
Use a Distance Map When You Need Lookup Later
If you need to remember the depth of every node after BFS finishes, a distance dictionary is often the cleanest representation.
This is effectively depth tracking with a more reusable output structure. It is also the standard shortest-path distance map for an unweighted graph.
Trees and Graphs Need Slightly Different Attention
In a tree, you can often skip a visited set if you already know the parent-child structure prevents cycles. In a general graph, you need visited tracking or a distance map so that BFS does not revisit nodes forever.
That matters for depth correctness too. If a node is enqueued multiple times through different parents, the recorded depth can become noisy unless you mark it the first time it is discovered.
Which Approach Should You Use
Use (node, depth) pairs when:
- you want the clearest implementation
- you need the depth while processing each node
Use level-by-level iteration when:
- the problem is naturally phrased by layers
- you need to do one action per level rather than per node-depth pair
Use a distance map when:
- you need to query depths later
- the BFS is really computing shortest path lengths
All three are valid. The best choice depends on what the rest of the problem needs.
Common Pitfalls
The biggest mistake is incrementing a global depth counter every time a node is popped. That does not reflect BFS depth; it only counts how many nodes were processed.
Another common issue is forgetting visited tracking in graphs with cycles. Without it, BFS can revisit nodes endlessly or assign misleading depths.
People also sometimes mark nodes as visited too late. Mark them when enqueueing, not when dequeueing, so the same node is not added multiple times.
Finally, do not mix level-based logic with pair-based logic unless you truly need both. Pick one depth-tracking pattern and keep it consistent.
Summary
- BFS depth is easiest to track by storing
(node, depth)in the queue or by processing one level at a time. - A distance dictionary is the best choice when you need the depths after traversal.
- In graphs, mark nodes as visited when they are enqueued.
- A single global counter per popped node does not represent BFS depth correctly.
- Choose the tracking style that matches the rest of the problem, not just the traversal itself.

