Skip to content
DSA graphs 7 min read

Breadth-First Search (BFS): Queue-Based Graph Traversal

Breadth-First Search (BFS) explores a graph level by level: it visits the start vertex, then all of its neighbors, then all of their unvisited neighbors, and so on. It uses a queue (first-in, first-out) to remember what to visit next. BFS runs in O(V + E) time and is the go-to algorithm for finding the shortest path in an unweighted graph.

How BFS works

  1. Put the start vertex in a queue and mark it visited.
  2. Pop the front vertex, process it, and push every unvisited neighbor (marking each visited as you enqueue it).
  3. Repeat until the queue is empty.

Because vertices come off the queue in the order they were discovered, BFS expands outward in rings of equal distance from the start.

#include <vector>
#include <queue>

std::vector<int> bfs(const std::vector<std::vector<int>>& adj, int start) {
    std::vector<int> order;
    std::vector<bool> visited(adj.size(), false);
    std::queue<int> q;
    q.push(start);
    visited[start] = true;
    while (!q.empty()) {
        int u = q.front(); q.pop();
        order.push_back(u);
        for (int v : adj[u]) {
            if (!visited[v]) {
                visited[v] = true;   // mark when enqueuing
                q.push(v);
            }
        }
    }
    return order;
}

Pitfall: Mark a vertex visited when you enqueue it, not when you dequeue it. Marking on dequeue lets the same vertex be added many times, blowing up to O(V·E) or worse.

Shortest path in an unweighted graph

Because BFS reaches every vertex by the fewest possible edges, you get shortest distances for free — just record the distance to each neighbor as one more than the current vertex.

std::vector<int> bfsDistances(const std::vector<std::vector<int>>& adj, int start) {
    std::vector<int> dist(adj.size(), -1);
    std::queue<int> q;
    q.push(start); dist[start] = 0;
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int v : adj[u]) {
            if (dist[v] == -1) {
                dist[v] = dist[u] + 1;
                q.push(v);
            }
        }
    }
    return dist;   // -1 means unreachable
}

Complexity and when to use it

  • Time: O(V + E) — each vertex and edge is examined once.
  • Space: O(V) for the visited array and the queue.

Use BFS for shortest paths in unweighted graphs, level-order problems (like word ladder), and finding connected components. For weighted shortest paths you need Dijkstra; to go deep instead of wide, use DFS.

Last updated June 25, 2026
Was this helpful?