Breadth First traversal
In the last post, we discussed depth first traversal of a graph. Today, we will discuss another way to traverse a graph, which is breadth first traversal. What is breadth first traversal? Unlike depth-first traversal, where we go deep before visiting neighbors, in breadth-first search, we visit all the neighbors of a node before moving a level down. For example, breadth first traversal of the graph shown below will be [1,2,5,3,4,6]
In breadth first search, we finish visiting all the nodes at a level before going further down the graph. For example, the graph used in the above example can be divided into three levels as shown.
We start with a node in level 1 which is node(1)
. Then visit all the nodes which are one level below node(1)
which are node(2)
and node(5)
. Then we visit all the node at level 3 which are node(3)
, node(4)
and node(6)
.
Breadth First Traversal: algorithm
- Start with the given node u, put node u to queue
- While queue is not empty, repeat below steps:
- Dequeue fro queue and print node u.
- For each neighbor of u, node v
- If v is not visited already: add v to the queue
- mark v as visited
Let’s take an example and see how it works. Below is the graph and we have to find BFS for this graph.
We start from node(1)
, and put it in the queue.
While the queue is not empty, we should pop from it and print the node. In this case, node(1)
will be printed. Next, we go through all the neighbors of node(1)
and put all the unvisited node on the queue. node(2)
and node(5)
will go on to the queue and marked as visited. Traversal = {1}
Again, we dequeue from the queue and this time we get node(2)
. We print it and go for all the neighbor node, node(3)
and node(4)
and mark them as visited. Traversal = {1,2}
node(5)
is dequeued next and printed. Here, even though node(4)
is a neighbor of node(5)
, it is already visited and hence not put on to the queue again. But node(6)
is not yet visited, so put it on to the queue. Traversal = {1,2,5}
Now, we pop node(3)
and print it, however, node(4)
is already visited. Hence, nothing is added to the queue. Traversal = {1,2,5,3}
Next, node(4)
is taken out from queue and printed, nothing goes on to queue. Traversal = {1,2,5,3,4}
Last, we pop node(6)
and print it. Traversal = {1,2,5,3,4,6}.
At this point, the queue is empty and we stop traversal.
Breadth first traversal: implementation
public ArrayList<Integer> breadthFirstTraversal(){ boolean[] visited = new boolean[this.G.length]; ArrayList<Integer> traversal = new ArrayList<>(); Queue<Integer> q = new LinkedList<>(); //This is start node q.add(1); visited[1] = true; while(!q.isEmpty()){ int u = (int)q.remove(); traversal.add(u); for(int i=1; i< this.G[1].length; i++){ if(this.G[u][i] && !visited[i]){ q.add(i); visited[i]= true; } } } System.out.println(traversal); return traversal; }
The complexity of this code is O(V2)
as at least V nodes will go in queue and for each nodes internal for loop runs V times.
Implementation of breadth-first search on graph represented by adjanceny list
public ArrayList<Integer> breadthFirstTraversal(){ boolean[] visited = new boolean[this.G.size()]; ArrayList<Integer> traversal = new ArrayList<>(); Queue<Integer> q = new LinkedList<>(); //This is start node q.add(1); visited[1] = true; //This loop will run for V times, once for each node. while(!q.isEmpty()){ int u = (int)q.remove(); traversal.add(u); /*This loop has a worst-case complexity of O(V), where node has an edge to every other node, but the total number of times this loop will run is E times where E number of edges. */ for(int v : this.G.get(u)){ if(!visited[v]){ q.add(v); visited[v]= true; } } } System.out.println(traversal); return traversal; }
The complexity of Breadth First Search is O(V+E)
where V is the number of vertices and E is the number of edges in the graph.
The complexity difference in BFS when implemented by Adjacency Lists and Matrix occurs due to this fact that in Adjacency Matrix, to tell which nodes are adjacent to a given vertex, we take
O(|V|)
time, irrespective of edges. Whereas, in Adjacency List, it is immediately available to us, takes time proportional to adjacent vertices itself, which on summation over all vertices |V| is |E|. So, BFS by Adjacency List givesO(|V| + |E|)
.
When a graph is strongly connected, O(V + E)
is actually O(V2)
Applications of Breadth first traversal
- To find shortest path between two nodes u and v
- To test bipartite-ness of a graph
- To find all nodes within one connected component
Please share if there is something wrong or missing. If you are preparing for an interview and want a free coaching session to guide you through it, please reach out to us at communications@algorithmsandme.com