C++ Program for BFS (Breadth-First Search) with Example
queue to explore graph nodes level by level, starting from a source node, visiting neighbors before moving deeper. The core code uses a while loop with a queue and a visited array to track explored nodes.Examples
How to Think About It
Algorithm
Code
#include <iostream> #include <vector> #include <queue> using namespace std; void bfs(int start, const vector<vector<int>>& graph) { vector<bool> visited(graph.size(), false); queue<int> q; visited[start] = true; q.push(start); while (!q.empty()) { int node = q.front(); q.pop(); cout << node << " "; for (int neighbor : graph[node]) { if (!visited[neighbor]) { visited[neighbor] = true; q.push(neighbor); } } } } int main() { vector<vector<int>> graph = { {1, 2}, // neighbors of node 0 {2}, // neighbors of node 1 {0, 3}, // neighbors of node 2 {3} // neighbors of node 3 }; bfs(2, graph); return 0; }
Dry Run
Let's trace BFS starting from node 2 on the example graph.
Initialize
visited = [false, false, false, false], queue = []
Start node 2
visited = [false, false, true, false], queue = [2]
Process node 2
Print 2; neighbors = 0, 3; mark visited[0]=true, visited[3]=true; queue = [0, 3]
Process node 0
Print 0; neighbors = 1, 2; 2 already visited; mark visited[1]=true; queue = [3, 1]
Process node 3
Print 3; neighbors = 3; already visited; queue = [1]
Process node 1
Print 1; neighbors = 2; already visited; queue = []
| Queue | Visited | Output |
|---|---|---|
| [2] | [false, false, true, false] | |
| [0, 3] | [true, false, true, true] | 2 |
| [3, 1] | [true, true, true, true] | 2 0 |
| [1] | [true, true, true, true] | 2 0 3 |
| [] | [true, true, true, true] | 2 0 3 1 |
Why This Works
Step 1: Use a queue to explore nodes
The queue stores nodes to visit next, ensuring nodes are processed in the order they are discovered.
Step 2: Mark nodes visited when enqueued
Marking nodes as visited when added to the queue prevents revisiting and infinite loops.
Step 3: Process neighbors level by level
BFS visits all neighbors of a node before moving deeper, exploring the graph in layers.
Alternative Approaches
#include <iostream> #include <vector> #include <queue> using namespace std; void bfsHelper(queue<int>& q, vector<bool>& visited, const vector<vector<int>>& graph) { if (q.empty()) return; int node = q.front(); q.pop(); cout << node << " "; for (int neighbor : graph[node]) { if (!visited[neighbor]) { visited[neighbor] = true; q.push(neighbor); } } bfsHelper(q, visited, graph); } void bfs(int start, const vector<vector<int>>& graph) { vector<bool> visited(graph.size(), false); queue<int> q; visited[start] = true; q.push(start); bfsHelper(q, visited, graph); } int main() { vector<vector<int>> graph = {{1,2},{2},{0,3},{3}}; bfs(2, graph); return 0; }
#include <iostream> #include <vector> #include <queue> using namespace std; void bfs(int start, const vector<vector<int>>& matrix) { int n = matrix.size(); vector<bool> visited(n, false); queue<int> q; visited[start] = true; q.push(start); while (!q.empty()) { int node = q.front(); q.pop(); cout << node << " "; for (int i = 0; i < n; i++) { if (matrix[node][i] == 1 && !visited[i]) { visited[i] = true; q.push(i); } } } } int main() { vector<vector<int>> matrix = { {0,1,1,0}, {0,0,1,0}, {1,0,0,1}, {0,0,0,1} }; bfs(2, matrix); return 0; }
Complexity: O(V + E) time, O(V) space
Time Complexity
BFS visits each vertex once and checks all edges once, so time is proportional to vertices plus edges.
Space Complexity
The queue and visited array use space proportional to the number of vertices.
Which Approach is Fastest?
Adjacency list BFS is faster and uses less memory for sparse graphs compared to adjacency matrix BFS.
| Approach | Time | Space | Best For |
|---|---|---|---|
| Adjacency List BFS | O(V + E) | O(V) | Sparse graphs, memory efficient |
| Adjacency Matrix BFS | O(V^2) | O(V^2) | Dense graphs, simple implementation |
| Recursive BFS | O(V + E) | O(V) + call stack | Small graphs, educational use |