Welcome to the Java Breadth-First Search (BFS) tutorial! In this lesson, we'll explore the BFS algorithm, a common strategy used in graph traversal. We'll cover its implementation, real-world applications, and see it in action with practical examples. Let's get started!
š” BFS is an algorithm for traversing or searching tree or graph data structures. It starts at the tree root (or some arbitrary node in the case of graphs) and explores all of the neighbor nodes at the present depth prior to moving on to nodes at the next depth level.
ā BFS is useful in many scenarios, such as finding the shortest path between nodes in an unweighted graph, checking if a graph is connected, or determining the number of connected components in a graph.
BFS and Depth-First Search (DFS) are two common graph traversal algorithms. While both algorithms visit all vertices of a connected graph, they differ in their traversal order and use cases.
To implement BFS, we'll need a data structure to represent the graph and a queue to keep track of nodes to be visited. A common choice for the graph representation is an adjacency list.
Here's a high-level overview of the BFS algorithm:
q and a boolean array visited to keep track of visited nodes.u from the queue.v of u that has not been visited:
v as visited.v to the queue.Now, let's see how to implement BFS in Java using the adjacency list representation.
import java.util.*;
public class BreadthFirstSearch {
private static final String UNVISITED = "Unvisited";
private static final String VISITED = "Visited";
public static void main(String[] args) {
Graph graph = new Graph(6);
graph.addEdge(0, 1);
graph.addEdge(0, 2);
graph.addEdge(1, 3);
graph.addEdge(1, 4);
graph.addEdge(2, 5);
System.out.println("BFS of graph:");
bfs(graph, 0);
}
private static void bfs(Graph graph, int source) {
Queue<Integer> queue = new LinkedList<>();
boolean[] visited = new boolean[graph.getVertexCount()];
// Initialize the source node and mark it as visited
queue.add(source);
visited[source] = true;
while (!queue.isEmpty()) {
int current = queue.poll();
System.out.print(current + " ");
// Visit and enqueue neighbors
for (int neighbor : graph.getAdjacencies(current)) {
if (!visited[neighbor]) {
queue.add(neighbor);
visited[neighbor] = true;
}
}
}
}
}
class Graph {
private final int[] adjacencies;
private final int vertexCount;
public Graph(int vertexCount) {
this.vertexCount = vertexCount;
this.adjacencies = new int[vertexCount];
for (int i = 0; i < vertexCount; i++) {
adjacencies[i] = -1;
}
}
public void addEdge(int vertex1, int vertex2) {
adjacencies[vertex1] = vertex2;
}
public int[] getAdjacencies(int vertex) {
return adjacencies[vertex] >= 0 ? new int[]{adjacencies[vertex]} : new int[0];
}
public int getVertexCount() {
return vertexCount;
}
}š Note: This example demonstrates an unweighted undirected graph with adjacency list representation. You can extend this code to handle weighted graphs and directed graphs if needed.
With the BFS implementation ready, let's observe the BFS traversal of the sample graph from the main function:
BFS of graph:
0 1 2 3 4 5
This output shows the BFS traversal of the given graph, starting from vertex 0.