Search algorithmsCTRL K

BFS

· level by level from a source
/graphs/bfs
VISITED
0/ 10
dequeued and expanded
QUEUE
1
waiting
EDGES
0
looked at so far
LEVEL
0
distance of the current node
ORDER
visit order
currentfrontier · tree edgedoneunvisited
10 nodes · 11 edges · seed 7 · 34 steps
step 0 / 33
Nodes10
bfs.ts
1
function bfs(graph: Graph, start: Node) {
2
  const queue = [start];
3
  const dist = new Map([[start, 0]]);
4
  while (queue.length > 0) {
5
    const node = queue.shift()!;
6
    for (const neighbor of graph.neighbors(node)) {
7
      if (dist.has(neighbor)) continue;
8
      dist.set(neighbor, dist.get(node)! + 1);
9
      queue.push(neighbor);
10
    }
11
  }
12
  return dist;
13
}
CURRENT STEP
line 2

Start at A: distance 0, the queue holds only A.

// how it works

Understanding BFS

BFS · every node at distance 1, then 2, then 3
01

The idea

Breadth-first search on a graph is the same idea as on a grid: keep a queue, take the oldest node, and put its unseen neighbours at the back. Nodes come out in order of distance from the source, so the queue holds at most two consecutive levels at any time.

The tree edges, the edge through which each node was first reached, form the BFS tree, and the distance labels are the shortest path lengths in hops. Everything else about the graph, weights included, is ignored.

02

The four stages

1
dequeuethe oldest node in the queue
2
expandlook at every neighbour
3
enqueueunseen ones get distance + 1
4
donethe node leaves the frontier
03

Complexity

best
O(V + E)always: every node and edge once
average
O(V + E)linear in the size of the graph
worst
O(V + E)dense graph: E ≈ V²
space
O(V)queue and distances
04

Versus its siblings

EDGES EXAMINED · 1 000 NODES, 3 000 EDGES
bfs
6,000
dfs
6,000
dijkstra
6,000
bellman-ford
3M
floyd-warshall
1B
undirected: each edge is seen from both ends
05

Pseudocode

BFS(graph, source)
  queue ← [source]; dist[source] ← 0
  while queue not empty
    node ← dequeue
    for each neighbour of node with no dist yet
      dist[neighbour] ← dist[node] + 1; enqueue neighbour
06

When to use

Shortest paths in hops: social distance, fewest transfers, the web crawler's frontier.
Anything level-based: bipartite checks, connected components, the layers of a flow network.
07

Pitfalls

Weights are ignored: three light edges lose to one heavy edge. Use Dijkstra.
Marking a node when it is dequeued instead of when it is enqueued adds it to the queue several times.
On an implicit graph (states of a puzzle) the frontier can explode; store visited states compactly.
08

History

Breadth-first search was written down by Konrad Zuse in 1945 and rediscovered by Edward Moore in 1959 for finding the way out of a maze. Its linear running time makes it the first tool reached for on any unweighted graph, and the layering it produces is the backbone of Hopcroft–Karp matching and Dinic's max-flow.

Back to Graphs