Breadth-⁠First Search

Graph ・ O(V + E)

Visits vertices nearest to the start first, using a queue.

Move it step by step

ABCDEFG
Current vertex
none
Current edge
none
Visit order
A

Queue (leaves from the front, joins at the back)

  1. A
Leaves from the frontJoins at the back
Vertex out
  • Checking its neighbors now
  • Visited (number is visit order)
  • Not yet visited
  • Edge being looked at

When a vertex has two or more neighbors, we look at them in name order (A, B, C, ...). A vertex is marked visited at the moment it's enqueued.

Step 1 of 210 edges seen1 visited1 in queue

Mark the start vertex A as visited and enqueue it.

The pseudocode line currently running

  1. 1Mark the start vertex s as visited and enqueue it
  2. 2While the queue is not empty, repeat the following
  3. 3u = dequeue the vertex at the front
  4. 4Look at each neighbor v of u, in name order
  5. 5If v is unvisited, mark it visited and enqueue it
  6. 6If v is already visited, do nothing

Change the example

Try predicting

You're on step 1.
Which vertex comes out of the queue next?

What you'll learn

  • The flow of visiting vertices in order of distance from the start vertex
  • Why using a queue visits vertices in order of distance, and why you need a visited marker

Prerequisites

  • Queues (first in, first out)
  • Vertices and edges in a graph

How this traversal works

Breadth-first search (BFS) starts at a vertex and visits every vertex reachable by one edge, then every vertex reachable by two edges, and so on, expanding outward in order of distance.

The vertices to check next wait in a queue. Because the nearer vertices were enqueued first, they come out first, so the traversal naturally proceeds in order of distance. Marking each vertex as visited once means that even in a graph with a cycle, no vertex gets checked twice.

Steps, with an example

  1. 1Mark the start vertex as visited and enqueue it
  2. 2Dequeue one vertex from the front of the queue
  3. 3Look at that vertex's neighbors; mark any unvisited ones as visited and enqueue them at the back
  4. 4Repeat steps 2 and 3 until the queue is empty
Starting "Tree" from A
Dequeued vertexNewly visitedQueue (from the front)
AB, CB, C
BD, EC, D, E
CF, GD, E, F, G
DnoneE, F, G
EnoneF, G
FnoneG
Gnonenone

Work done and complexity

What we countCountComplexity
DequeuingOnce per vertexO(V)
Looking at edgesTwice per edge (once from each side)O(E)
CombinedProportional to the number of vertices plus edgesO(V + E)

V is the number of vertices and E is the number of edges. The tree example has 7 vertices and 6 edges, so we dequeue 7 times and look at 12 edges. Whether a vertex is visited is tracked with a set, so checking it takes one step. If you tracked it with a list and searched it every time, you wouldn't stay within this count. Sorting neighbors into name order is just to make the figure easier to follow, and isn't counted here.

When to use it

Good fit

  • When you want the shortest path measured by number of edges (the fewest moves through a maze)
  • When you want to count everything reachable from a vertex (the size of a connected component)
  • When you want to expand outward from the nearest things first (friends of friends)

Not a good fit

  • When edges have different lengths (use Dijkstra's algorithm instead)
  • When you want to follow a single path as deep as it goes (use depth-first search instead)

Code

Pseudocode

  1. 1Mark the start vertex s as visited and enqueue it
  2. 2While the queue is not empty, repeat the following
  3. 3u = dequeue the vertex at the front
  4. 4Look at each neighbor v of u, in name order
  5. 5If v is unvisited, mark it visited and enqueue it
  6. 6If v is already visited, do nothing

Working code

pythonRunnable
Output

▶ Press “Run” to see the result here

Edit the Python or JavaScript and press “Run” to see the result right away. Java is read-only here.

FAQ

Why mark a vertex visited when it's enqueued, instead of when it's dequeued?
If you marked it visited only when it's dequeued, another vertex could discover the same vertex before the mark is set, and you'd enqueue it twice. Marking it when it's enqueued guarantees every vertex is queued only once.
What happens if you replace the queue with a stack?
Then the most recently added vertex comes out first, so the traversal follows a single path as deep as it goes. That's the shape of depth-first search, and it no longer visits vertices in order of distance.
What if I want to visit disconnected vertices too?
Go through every vertex in order, and whenever you find one that isn't visited yet, start a fresh BFS from there. The number of times you restart is the number of connected components.

Related