Master the Breadth-First Search algorithm for finding shortest paths in unweighted graphs. Learn how to systematically explore graph levels and track paths efficiently.
Level 0: A ↙ ↓ ↘ Level 1: B C D ↙ ↘ ↙ Level 2: E F G
Aspect | Breadth-First Search (BFS) | Depth-First Search (DFS) |
---|---|---|
Data Structure | Queue | Stack (or recursion) |
Order of Exploration | Level by level | Path by path |
Space Complexity | O(w) where w is the maximum width | O(h) where h is the maximum depth |
Time Complexity | O(V + E) | O(V + E) |
Best For | Shortest path, nearest neighbor | Path finding, exhaustive search |
Applications | Social networks, GPS, web crawling | Puzzles, mazes, topological sorting |
/**
* Performs a breadth-first search on a graph starting from a given vertex
* @param {Object} graph - Adjacency list representation of the graph
* @param {string|number} start - The starting vertex
* @returns {Object} - Contains parent pointers and distances from start
*/
function bfs(graph, start) {
const queue = [start];
const visited = new Set([start]);
const parent = new Map();
const distance = new Map([[start, 0]]);
while (queue.length > 0) {
const vertex = queue.shift();
for (let neighbor of graph[vertex]) {
if (!visited.has(neighbor)) {
visited.add(neighbor);
queue.push(neighbor);
parent.set(neighbor, vertex);
distance.set(neighbor, distance.get(vertex) + 1);
}
}
}
return { parent, distance, visited };
}
/**
* Finds the shortest path between two vertices in an unweighted graph
* @param {Object} graph - Adjacency list representation of the graph
* @param {string|number} start - The starting vertex
* @param {string|number} end - The target vertex
* @returns {Array|null} - Array of vertices forming the path, or null if no path exists
*/
function findShortestPath(graph, start, end) {
// If start and end are the same, return a single-element path
if (start === end) {
return [start];
}
const { parent } = bfs(graph, start);
// If end vertex was not reached, return null
if (!parent.has(end)) {
return null;
}
// Reconstruct the path by following parent pointers backwards
const path = [];
let current = end;
while (current !== undefined) {
path.unshift(current);
current = parent.get(current);
}
return path;
}
// Sample graph (adjacency list representation)
Map<String, List<String>> graph = new HashMap<>();
graph.put("A", Arrays.asList("B", "C", "D"));
graph.put("B", Arrays.asList("A", "E"));
graph.put("C", Arrays.asList("A", "F"));
graph.put("D", Arrays.asList("A", "G"));
graph.put("E", Arrays.asList("B"));
graph.put("F", Arrays.asList("C"));
graph.put("G", Arrays.asList("D"));
// Basic BFS traversal
Set<String> visited = bfs(graph, "A").visited;
System.out.println("BFS traversal: " + visited);
// Output: [A, B, C, D, E, F, G]
// Find shortest path from 'A' to 'F'
List<String> path = findShortestPath(graph, "A", "F");
System.out.println("Shortest path from A to F: " + path);
// Output: [A, C, F]
// Find shortest path from 'E' to 'G'
List<String> anotherPath = findShortestPath(graph, "E", "G");
System.out.println("Shortest path from E to G: " + anotherPath);
// Output: [E, B, A, D, G]
Implement a modified BFS that can start from multiple source nodes simultaneously.
function multiSourceBFS(graph, sources) {
const queue = [...sources];
const visited = new Set(sources);
const distance = new Map();
// Initialize distances for all source nodes
sources.forEach(source => distance.set(source, 0));
while (queue.length > 0) {
const vertex = queue.shift();
for (let neighbor of graph[vertex] || []) {
if (!visited.has(neighbor)) {
visited.add(neighbor);
queue.push(neighbor);
distance.set(neighbor, distance.get(vertex) + 1);
}
}
}
return { distance, visited };
}
Find shortest path that satisfies certain conditions (e.g., must pass through specific nodes).
const graph = {
'A': ['B', 'C'],
'B': ['A', 'D', 'E'],
'C': ['A', 'F'],
'D': ['B'],
'E': ['B', 'F'],
'F': ['C', 'E']
};
// Find path from A to F that passes through E
console.log(findPathThroughNode(graph, 'A', 'F', 'E'));
// Output: ['A', 'B', 'E', 'F']
Group nodes by their levels (distances) from the start node.
const levels = groupByLevels(graph, 'A');
/*
{
0: ['A'],
1: ['B', 'C', 'D'],
2: ['E', 'F', 'G']
}
*/
Note: Previously, this course referenced the CodeSignal Arcade for practice, which is no longer available. The LeetCode problems below follow the same principles and are excellent for practicing BFS algorithms.