Breadth-First Search
Definition
- Breadth-first search (BFS) is a general technique for traversing a graph
- A BFS traversal of a graph G
- Visits all the vertices and edges of G
- Determines whether G is connected
- Computes the connected components of G
- Computes a spanning forest of G
- BFS on a graph with n vertices and m edges takes O(n + m ) time
- BFS can be further extended to solve other graph problems
- Find and report a path with the minimum number of edges between two given vertices
- Find a simple cycle, if there is one
- Application: Using the template method pattern, we can specialize the BFS traversal of a graph G to solve the following problems in O(n + m) time:
- Compute the connected components of G
- Compute a spanning forest of G
- Find a simple cycle in G, or report that G is a forest
- Given two vertices of G, find a path in G between them with the minimum number of edges, or report that no such path exists
BFS Algorithm
- The algorithm uses a mechanism for setting and getting “labels” of vertices and edges
Algorithm BFS(G)
Input graph G
Output labeling of the edges and partition of the vertices of G
for all u ∈ G.vertices()
setLabel(u, UNEXPLORED)
for all e ∈ G.edges()
setLabel(e, UNEXPLORED)
for all v ∈ G.vertices()
if getLabel(v) = UNEXPLORED
BFS(G, v)
Algorithm BFS(G, s)
L0 ← new empty sequence
L0.insertLast(s)
setLabel(s, VISITED)
i ← 0
while ¬Li.isEmpty()
Li +1 ← new empty sequence
for all v ∈ Li.elements()
for all e ∈ G.incidentEdges(v)
if getLabel(e) = UNEXPLORED
w ← opposite(v,e)
if getLabel(w) = UNEXPLORED
setLabel(e, DISCOVERY)
setLabel(w, VISITED)
Li +1.insertLast(w)
else
setLabel(e, CROSS)
i ← i +1
![BFS_Example](Images/BFS_Example.PNG)
Properties
- Notation
- Gs: connected component of s
- Property 1
- BFS(G, s) visits all the vertices and edges of Gs
- Property 2
- The discovery edges labeled by BFS(G, s) form a spanning tree Ts of Gs
- Property 3
- For each vertex v in Li
- The path of Ts from s to v has i edges
- Every path from s to v in Gs has at least i edge
![BFS_Properties](Images/BFS_Properties.PNG)
Analysis
- Setting/getting a vertex/edge label takes O(1) time
- Each vertex is labeled twice
- once as UNEXPLORED
- once as VISITED
- Each edge is labeled twice
- once as UNEXPLORED
- once as DISCOVERY or CROSS
- Each vertex is inserted once into a sequence Li
- Method incidentEdges is called once for each vertex
- BFS runs in O(n + m) time provided the graph is represented by the adjacency list structure
- Recall that Σv deg(v) = 2m
DFS vs. BFS
![BFS_vs_DFS](Images/BFS_vs_DFS.PNG)
- DFS Back edge (v,w)
- w is an ancestor of v in the tree of discovery edges
- BFS Back edge (v,w)
- w is in the same level as v or in the next level in the tree of discovery edges
![BFS_vs_DFS](Images/BFS_vs_DFS2.PNG)
Code
package examples;
import graphLib.*;
import graphTool.Algorithm;
import graphTool.Attribute;
import graphTool.GraphTool;
import java.awt.Color;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Random;
public class GraphExamples<V,E> {
@Algorithm(vertex=true)
public void visitBFS(Graph<V,E> g, Vertex<V> v, GraphTool<V,E> t) {
LinkedList<Vertex<V>> list = new LinkedList<>();
v.set(Attribute.color,Color.BLUE);
v.set(Attribute.VISITED,null);
list.addLast(v);
t.show(g);
while (! list.isEmpty()){
Vertex w = list.removeFirst();
Iterator<Edge<E>> it = g.incidentEdges(w);
while (it.hasNext()){
Edge e = it.next();
Vertex n = g.opposite(e, w);
if ( ! n.has(Attribute.VISITED)){
e.set(Attribute.color,Color.GREEN);
n.set(Attribute.color,Color.GREEN);
n.set(Attribute.VISITED,null);
n.set(Attribute.DISCOVERY,e);
n.set(v,e);
list.addLast(n);
t.show(g);
}
}
}
}
public static void main(String[] args) {
IncidenceListGraph<String,String> g =
new IncidenceListGraph<>(true);
GraphExamples<String,String> ge = new GraphExamples<>();
Vertex vA = g.insertVertex("A");
vA.set(Attribute.name,"A");
Vertex vB = g.insertVertex("B");
vB.set(Attribute.name,"B");
Vertex vC = g.insertVertex("C");
vC.set(Attribute.name,"C");
Vertex vD = g.insertVertex("D");
vD.set(Attribute.name,"D");
Vertex vE = g.insertVertex("E");
vE.set(Attribute.name,"E");
Vertex vF = g.insertVertex("F");
vF.set(Attribute.name,"F");
Vertex vG = g.insertVertex("G");
vG.set(Attribute.name,"G");
Edge e_a = g.insertEdge(vA,vB,"AB");
Edge e_b = g.insertEdge(vD,vC,"DC");
Edge e_c = g.insertEdge(vD,vB,"DB");
Edge e_d = g.insertEdge(vC,vB,"CB");
Edge e_e = g.insertEdge(vC,vE,"CE");
e_e.set(Attribute.weight,2.0);
Edge e_f = g.insertEdge(vB,vE,"BE");
e_f.set(Attribute.weight, 7.0);
Edge e_g = g.insertEdge(vD,vE,"DE");
Edge e_h = g.insertEdge(vE,vG,"EG");
e_h.set(Attribute.weight,3.0);
Edge e_i = g.insertEdge(vG,vF,"GF");
Edge e_j = g.insertEdge(vF,vE,"FE");
GraphTool t = new GraphTool(g,ge);
}
}