Java Program to Implement BFS (Breadth-First Search)
Queue to explore nodes level by level starting from a source node, like: Queue queue = new LinkedList<>(); queue.add(startNode); while(!queue.isEmpty()) { int node = queue.poll(); /* process node */ } .Examples
How to Think About It
Algorithm
Code
import java.util.*; public class BFS { private int vertices; private LinkedList<Integer>[] adjList; public BFS(int v) { vertices = v; adjList = new LinkedList[v]; for (int i = 0; i < v; i++) { adjList[i] = new LinkedList<>(); } } public void addEdge(int src, int dest) { adjList[src].add(dest); } public void bfs(int start) { boolean[] visited = new boolean[vertices]; Queue<Integer> queue = new LinkedList<>(); visited[start] = true; queue.add(start); while (!queue.isEmpty()) { int node = queue.poll(); System.out.print(node + " "); for (int neighbor : adjList[node]) { if (!visited[neighbor]) { visited[neighbor] = true; queue.add(neighbor); } } } } public static void main(String[] args) { BFS graph = new BFS(4); graph.addEdge(0, 1); graph.addEdge(0, 2); graph.addEdge(1, 2); graph.addEdge(2, 0); graph.addEdge(2, 3); graph.addEdge(3, 3); System.out.print("BFS traversal starting from node 2: "); graph.bfs(2); } }
Dry Run
Let's trace BFS starting from node 2 on the example graph.
Initialize
visited = [false, false, false, false], queue = []
Start from node 2
visited = [false, false, true, false], queue = [2]
Process node 2
Print 2; neighbors = [0, 3]; add unvisited neighbors 0 and 3 visited = [true, false, true, true], queue = [0, 3]
Process node 0
Print 0; neighbors = [1, 2]; add unvisited neighbor 1 visited = [true, true, true, true], queue = [3, 1]
Process node 3
Print 3; neighbors = [3]; already visited, no addition queue = [1]
Process node 1
Print 1; neighbors = [2]; already visited, no addition 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 ensures nodes are processed in the order they are discovered, which is key to BFS visiting nodes level by level.
Step 2: Mark nodes visited when added
Marking nodes as visited when adding to the queue prevents revisiting and infinite loops.
Step 3: Process neighbors of each node
For each node removed from the queue, add all unvisited neighbors to the queue to explore them next.
Alternative Approaches
import java.util.*; public class RecursiveBFS { private int vertices; private LinkedList<Integer>[] adjList; public RecursiveBFS(int v) { vertices = v; adjList = new LinkedList[v]; for (int i = 0; i < v; i++) { adjList[i] = new LinkedList<>(); } } public void addEdge(int src, int dest) { adjList[src].add(dest); } public void bfs(int start) { boolean[] visited = new boolean[vertices]; Queue<Integer> queue = new LinkedList<>(); visited[start] = true; queue.add(start); bfsHelper(queue, visited); } private void bfsHelper(Queue<Integer> queue, boolean[] visited) { if (queue.isEmpty()) return; int node = queue.poll(); System.out.print(node + " "); for (int neighbor : adjList[node]) { if (!visited[neighbor]) { visited[neighbor] = true; queue.add(neighbor); } } bfsHelper(queue, visited); } public static void main(String[] args) { RecursiveBFS graph = new RecursiveBFS(4); graph.addEdge(0, 1); graph.addEdge(0, 2); graph.addEdge(1, 2); graph.addEdge(2, 0); graph.addEdge(2, 3); graph.addEdge(3, 3); System.out.print("Recursive BFS starting from node 2: "); graph.bfs(2); } }
import java.util.*; public class BFSMatrix { private int vertices; private int[][] adjMatrix; public BFSMatrix(int v) { vertices = v; adjMatrix = new int[v][v]; } public void addEdge(int src, int dest) { adjMatrix[src][dest] = 1; } public void bfs(int start) { boolean[] visited = new boolean[vertices]; Queue<Integer> queue = new LinkedList<>(); visited[start] = true; queue.add(start); while (!queue.isEmpty()) { int node = queue.poll(); System.out.print(node + " "); for (int i = 0; i < vertices; i++) { if (adjMatrix[node][i] == 1 && !visited[i]) { visited[i] = true; queue.add(i); } } } } public static void main(String[] args) { BFSMatrix graph = new BFSMatrix(4); graph.addEdge(0, 1); graph.addEdge(0, 2); graph.addEdge(1, 2); graph.addEdge(2, 0); graph.addEdge(2, 3); graph.addEdge(3, 3); System.out.print("BFS traversal using adjacency matrix from node 2: "); graph.bfs(2); } }
Complexity: O(V + E) time, O(V) space
Time Complexity
BFS visits every vertex and edge once, so the time is proportional to the number of vertices plus edges, O(V + E).
Space Complexity
The queue and visited array use space proportional to the number of vertices, O(V).
Which Approach is Fastest?
Using adjacency lists is faster and more memory efficient for sparse graphs compared to adjacency matrices.
| 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 |