Breadth-First Search

Lecture



Breadth-first search (level-by-level traversal) is one of the algorithms for traversing a graph. The method underlies several other algorithms of a similar nature. Breadth-first search involves examining the graph level by level: first the root – an arbitrarily chosen node – is visited, then all children of that node, after which the children of the children are visited, and so on. Vertices are examined in order of increasing distance from the root.

Let a graph G=(V, E) and a root s, from which the traversal begins, be given. After visiting node s, the nodes adjacent to s will be visited next (let us denote the set of nodes adjacent to s as q; it is obvious that q⊆V, that is, q is some subset of V). Next, this procedure is repeated for the vertices adjacent to the vertices in the set q, with the exception of vertex s, since it has already been visited. Thus, continuing to traverse level by level, the algorithm will visit all vertices of the set V reachable from s. The algorithm terminates after traversing all vertices of the graph, or when some existing condition is met.

Considering the following example, let us assume that during the operation of the algorithm each vertex of the graph can be colored one of three colors: black, white, or gray. Initially all vertices are white. During the traversal, each vertex, as it is discovered, is first colored gray and then black. A particular moment of the traversal is described by the following condition: if a vertex is black, then all of its children are colored gray or black.

Breadth-First Search

We have a mixed graph (see figure) with |V| = 4 and |E| = 5. Let us traverse its vertices using the breadth-first search algorithm. We take node 3 as the starting vertex. First it is marked gray as discovered, and then black, since the nodes adjacent to it (1 and 4) are discovered, which, in turn, are marked gray in that order. Next, node 1 is colored black, and its neighbor – node 2 – is found, which becomes gray. And finally, nodes 4 and 2, in that order, are examined, and the breadth-first traversal is complete.

The breadth-first search algorithm works on both directed and undirected graphs. The mixed graph used in the example was intended to illustrate this. It should be noted that in an undirected connected graph this method will traverse all existing nodes, whereas in a mixed graph or digraph this is not necessarily the case. Moreover, up to this point we have considered a traversal of all vertices, but it is quite possible that, for example, examining a certain number of them, or finding a specific vertex, would be sufficient. In such a case the algorithm will have to be adapted somewhat, rather than being changed completely or abandoned altogether.

Now let us move on to a more formal description of the breadth-first search algorithm. The main objects – three data structures used in the program – will be:

  • the graph adjacency matrix GM;
  • the queue;
  • the array of visited vertices, visited.

The first two structures have an integer data type, the last a boolean one. Visited vertices are recorded in the visited array, which prevents looping, while the queue will store the nodes involved. Recall that the «queue» data structure operates on the «first in, first out» principle. Let us consider the graph traversal process broken down into stages:

  1. the visited array is zeroed out, i.e., not a single vertex of the graph has yet been visited;
  2. some vertex s is chosen as the starting one and placed in the queue (in the queue array);
  3. vertex s is examined (marked as visited), and all vertices adjacent to it are placed at the end of the queue, while it itself is removed;
  4. if at this stage the queue turns out to be empty, the algorithm terminates; otherwise the vertex at the front of the queue is visited, marked as visited, and all of its children are added to the end of the queue;
  5. step 4 is carried out for as long as possible.

Breadth-first search, starting from the starting vertex, gradually moves further and further away from it, passing level by level. It turns out that by the end of the algorithm's operation, all shortest paths from the starting vertex to each node reachable from it will have been found.

To implement the algorithm in a programming language, one needs the ability to define a graph programmatically, as well as an understanding of a data structure such as a queue.

Program code in C++:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include "stdafx.h"
#include
using namespace std;
const int n=4;
int i, j;
//graph adjacency matrix
int GM[n][n] =
{
{0, 1, 1, 0},
{0, 0, 1, 1},
{1, 0, 0, 1},
{0, 1, 0, 0}
};
//breadth-first search
void BFS(bool *visited, int unit)
{
int *queue=new int[n];
int count, head;
for (i=0; icount=0; head=0;
queue[count++]=unit;
visited[unit]=true;
while (head{
unit=queue[head++];
cout<

Program code in Pascal:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
program BreadthFirstSearch;
uses crt;
const n=4;
type
MassivInt=array[1..n, 1..n] of integer;
MassivBool=array[1..n] of boolean;
var
i, j, start: integer;
visited: MassivBool;
{graph adjacency matrix}
const GM: MassivInt = (
(0, 1, 1, 0),
(0, 0, 1, 1),
(1, 0, 0, 1),
(0, 1, 0, 0));
{breadth-first search}
procedure BFS(visited: MassivBool; _unit: integer);
var
queue: array[1..n] of integer;
count, head: integer;
begin
for i:=1 to n do queue[i]:=0;
count:=0; head:=0;
count:=count+1;
queue[count]:=_unit;
visited[_unit]:=true;
while headbegin
head:=head+1;
_unit:=queue[head];
write(_unit, ' ');
for i:=1 to n do
begin
if (GM[_unit, i]<>0) and (not visited[i]) then
begin
count:=count+1;
queue[count]:=i;
visited[i]:=true;
end;
end;
end;
end;
{main program block}
begin
clrscr;
write('Starting vertex >> '); read(start);
writeln('Graph adjacency matrix: ');
for i:=1 to n do
begin
visited[i]:=false;
for j:=1 to n do
write(' ', GM[i, j]);
writeln;
end;
write('Traversal order: ');
BFS(visited, start);
end.

These two programs use the graph shown in the previous figure, or more precisely its adjacency matrix. Only one of 4 values can be entered, since only one of the 4 existing vertices can be specified as the starting one (the programs do not account for invalid input data):

Input data Output data
1 1 2 3 4
2 2 3 4 1
3 3 1 4 2
4 4 2 3 1

The graph is represented by an adjacency matrix, and in terms of efficiency this is not the best option, since the time spent traversing it is estimated at O(|V|2), whereas it can be reduced to O(|V|+|E|) by using an adjacency list.

created: 2014-11-30
updated: 2021-04-18
399



Was this answer useful?
Choose a quick rating so we can improve the next answer for you.
How satisfied are you?


Comments

To leave a comment

If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

Lectures and tutorial on "Algorithms"

Terms: Algorithms