Step by step · Python, C++ and Java

Breadth-first search, visualized step by step

Breadth-first search explores a graph in rings: the start vertex, then everything one edge away, then everything two edges away. That order is why BFS finds shortest paths in unweighted graphs.

How it works
graph = {
    "A": ["B", "C"],
    "B": ["A", "D"],
    "C": ["A", "E"],
    "D": ["B", "F"],
    "E": ["C", "F"],
    "F": ["D", "E"],
}

start = "A"
visited = set()
queue = [start]
order = []

while queue:
    node = queue.pop(0)
    if node in visited:
        continue
    visited.add(node)
    order.append(node)
    for neighbor in graph[node]:
        if neighbor not in visited:
            queue.append(neighbor)

print(order)

How breadth-first search works

A queue holds the vertices waiting to be visited. Take one from the front; if it has already been visited, skip it; otherwise mark it, record it, and add its unvisited neighbours to the back. Because the queue is first-in, first-out, every vertex at distance k is processed before any vertex at distance k + 1.

The example graph has six vertices, A to F, stored as an adjacency list. Starting from A, BFS visits A, B, C, D, E, F.

What to watch for when it runs

  1. The graph is drawn with visited vertices marked and the current one highlighted.
  2. The queue is drawn as a queue — vertices join at the back and leave from the front.
  3. F is queued twice, once from D and once from E; the visited check is what stops it being processed twice.

Time and space complexity

Time
O(V + E)
Space
O(V)

Every vertex is processed once and every edge looked at a constant number of times. Popping the front of a Python list is itself O(n); collections.deque makes it O(1).

Stuck on your own version?

Paste it into the visualizer and watch your own code run, line by line — bugs included.