BFS Algorithm: Complete Guide with Code Analysis
What is BFS (Breadth-First Search)?
BFS is a graph traversal algorithm that explores vertices level by level, starting from a source vertex. It
visits all vertices at distance 1 from the source, then all vertices at distance 2, and so on. Think of it like
ripples spreading out in water - it explores outward in all directions equally.
Core Concepts
1. Graph Representation
Your code uses an adjacency list to represent the graph:
java
Map<String, List<String>> adjList = new HashMap<>();
Each vertex has a list of its neighbors
For vertex "s" connected to "r" and "w", the list would be ["r", "w"]
2. Vertex Properties
Each vertex tracks important information during BFS:
java
static class Vertex {
String name; // Vertex identifier
String color; // Discovery status
int distance; // Distance from source
Vertex predecessor; // Parent in BFS tree
}
Color Coding System:
WHITE: Undiscovered (not visited yet)
GRAY: Discovered but not fully processed (in the queue)
BLACK: Fully processed (all neighbors explored)
The BFS Algorithm Step-by-Step
Step 1: Initialization
java
// Initialize all vertices except source
for (Vertex u : vertices.values()) {
if (!u.name.equals(sourceName)) {
u.color = "WHITE"; // Mark as unvisited
u.distance = Integer.MAX_VALUE; // Set distance to infinity
u.predecessor = null; // No parent yet
}
}
What happens: All vertices start as WHITE (undiscovered) with infinite distance.
Step 2: Initialize Source
java
Vertex source = vertices.get(sourceName);
source.color = "GRAY"; // Discovered
source.distance = 0; // Distance from itself is 0
source.predecessor = null; // No parent
Queue<Vertex> queue = new LinkedList<>();
queue.add(source); // Start with source in queue
What happens: The source vertex is marked as discovered (GRAY) and added to the queue.
Step 3: Main BFS Loop
java
while (!queue.isEmpty()) {
Vertex u = queue.poll(); // Take next vertex from queue
// Process all neighbors of u
for (String neighborName : adjList.get(u.name)) {
Vertex v = vertices.get(neighborName);
if (v.color.equals("WHITE")) { // If undiscovered
v.color = "GRAY"; // Mark as discovered
v.distance = u.distance + 1; // Set distance
v.predecessor = u; // Set parent
queue.add(v); // Add to queue
}
}
u.color = "BLACK"; // Mark as fully processed
}
What happens:
1. Remove a vertex from the front of the queue
2. Check all its neighbors
3. For each WHITE neighbor: mark it GRAY, set distance, set parent, add to queue
4. Mark current vertex as BLACK (fully processed)
How Your Code Works: A Walkthrough
Let's trace through your specific graph with source "s":
Graph Structure:
r --- s --- w --- t
| | / |
v x u
| /
y --
Initial State:
Source "s": GRAY, distance=0, in queue
All others: WHITE, distance=∞
BFS Execution:
Iteration 1: Process "s"
Dequeue "s"
Neighbors: ["r", "w"]
Process "r": WHITE → GRAY, distance=1, predecessor=s, add to queue
Process "w": WHITE → GRAY, distance=1, predecessor=s, add to queue
Mark "s" as BLACK
Queue: [r, w]
Iteration 2: Process "r"
Dequeue "r"
Neighbors: ["s", "v"]
"s" is BLACK (skip)
Process "v": WHITE → GRAY, distance=2, predecessor=r, add to queue
Mark "r" as BLACK
Queue: [w, v]
Iteration 3: Process "w"
Dequeue "w"
Neighbors: ["s", "t", "x"]
"s" is BLACK (skip)
Process "t": WHITE → GRAY, distance=2, predecessor=w, add to queue
Process "x": WHITE → GRAY, distance=2, predecessor=w, add to queue
Mark "w" as BLACK
Queue: [v, t, x]
And so on...
Key Features of Your Implementation
1. Distance Calculation
java
v.distance = u.distance + 1;
This ensures shortest path distances because BFS explores level by level.
2. Path Reconstruction
java
v.predecessor = u;
By storing predecessors, you can trace back the shortest path from any vertex to the source.
3. Avoiding Cycles
java
if (v.color.equals("WHITE")) {
Only process WHITE vertices to avoid revisiting and infinite loops.
Algorithm Properties
Time Complexity: O(V + E)
V = number of vertices
E = number of edges
Each vertex and edge is processed exactly once
Space Complexity: O(V)
Queue can hold at most V vertices
Additional space for vertex properties
Output Interpretation
Your printResult() method shows:
Vertex: The vertex name
d: Distance from source (shortest path length)
prev: Predecessor in the BFS tree (parent vertex)
Example output from source "s":
Vertex d prev
s 0 nil
r 1 s
w 1 s
v 2 r
t 2 w
x 2 w
u 3 t
y 3 x
This tells you:
"r" and "w" are 1 edge away from "s"
"v", "t", "x" are 2 edges away
"u" and "y" are 3 edges away
You can trace paths: s→w→t→u or s→w→x→y
Why BFS is Important
1. Shortest Paths: In unweighted graphs, BFS finds shortest paths
2. Level-order Traversal: Visits vertices in order of their distance
3. Connected Components: Can identify if vertices are reachable
4. Applications: Web crawling, social networks, GPS navigation, puzzle solving
Your code is a textbook implementation that correctly demonstrates all these BFS principles!