BFS Visualization —
A queue explores one layer at a time.
Breadth-First Search visits every neighbor of the current layer before moving to the next — using a plain FIFO queue, no recursion. It's the algorithm behind "shortest path in an unweighted graph" and "degrees of separation." Watch the queue fill and drain on LearnBug and see exactly why BFS finds the shortest path first.
What is BFS?
Starting from a node, visit all of its direct neighbors first, then all of their unvisited neighbors, and so on — layer by layer. A queue enforces this order: nodes are processed in the exact order they were discovered. A visited set stops nodes from being enqueued twice.
Why visualization helps
The confusing part isn't the queue mechanics — it's the visited set. Forget to mark a node visited when you enqueue it (instead of when you dequeue it), and the same node can be queued multiple times. LearnBug shows the queue and the visited set side by side at every step, so that bug becomes visible instead of silent.
BFS's signature use cases
Shortest path — unweighted
The first time BFS reaches a node, it's guaranteed to be via the shortest possible path (fewest edges) from the start.
Level-by-level processing
Anything that needs to know "how many steps away" — social network degrees of separation, minimum moves in a puzzle, word ladder.
Grid flood fill
Expanding outward from a cell — connected components, number of islands, rotting oranges — is BFS applied to a grid graph.
BFS from A on A→[B,C], B→[D], C→[D]
Start: enqueue A, mark it visited immediately
Marking a node visited at enqueue time — not at dequeue time — is what prevents it from being added to the queue twice by two different neighbors later.
Dequeue A, visit it, enqueue its unvisited neighbors B and C
A's neighbors are B and C. Neither is visited yet, so both get marked visited and pushed onto the queue.
Dequeue B, visit it, enqueue D — its only unvisited neighbor
B's only neighbor is D. D isn't visited yet, so it's marked visited and enqueued. Notice B was reached via the shortest path from A — one edge.
Dequeue C — D is already visited, so it's skipped; then dequeue D
C also points to D, but D is already in the visited set, so it's not re-added to the queue. This is exactly what the visited-at-enqueue-time rule prevents: a duplicate D entry.
Return: [A, B, C, D] ✓ each node visited once, in shortest-path order from A
BFS with a queue and visited set
graph = {
"A": ["B", "C"],
"B": ["D"],
"C": ["D"],
"D": [],
}
def bfs(start):
queue = [start]
visited = {start} # mark visited when ENQUEUED, not dequeued
order = []
while queue:
node = queue.pop(0)
order.append(node)
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append(neighbor)
return orderdef bfs_shortest_path(start, target):
queue = [(start, 0)]
visited = {start}
while queue:
node, dist = queue.pop(0)
if node == target:
return dist # first time we reach target = shortest path
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.append((neighbor, dist + 1))
return -1 # target unreachableComplexity Notes
Frequently asked questions
Why must I mark a node visited when I enqueue it, not when I dequeue it?
If two different nodes both point to the same unvisited neighbor before that neighbor is dequeued, marking visited only at dequeue time lets both of them enqueue it — the same node ends up in the queue twice, wasting work and potentially breaking distance calculations.
Why does BFS guarantee the shortest path in an unweighted graph?
BFS explores nodes in strict order of distance from the start — it fully processes everything at distance 1 before touching anything at distance 2. So the first time any node is reached, it must be via the shortest possible number of edges; there's no shorter path left unexplored.
How is BFS different from DFS?
BFS uses a queue (FIFO) and explores level by level; DFS uses a stack or recursion and dives as deep as possible before backtracking. Both are O(V+E), but BFS is the right tool for shortest-path/fewest-steps problems, while DFS suits path existence, cycle detection, and exhaustive exploration.
Does BFS work on directed graphs too?
Yes — BFS only follows the edges that actually exist in the adjacency list, so on a directed graph it simply won't traverse "backward" along an edge unless a reverse edge is explicitly present. The algorithm itself is unchanged.
Watch the queue explore one layer at a time
Paste your BFS into LearnBug and see the queue and visited set update at every step.