Article Directory
In this tutorial, you will learn the breadth first search algorithm. In addition, you will also find an example of the BFS algorithm in C.
Traverse refers to visiting all nodes of the graph. Breadth-first traversal or breadth-first search is a recursive algorithm used to search all vertices of a graph or tree data structure.
BFS algorithm
The standard BFS implementation divides each vertex of the graph into two categories:
- Visited
- Never visited
The purpose of this algorithm is to mark each vertex as visited while avoiding loops.
The working principle of the algorithm is as follows:
- First put any vertex of the graph at the back of the queue.
- Add the first item in the queue to the visited list.
- Create a list of neighboring nodes of this vertex. Add those not in the access list to the back of the queue.
- Repeat steps 2 and 3 until the queue is empty.
The graph may have two different disconnected parts, so in order to ensure that each vertex is covered, we can also run the BFS algorithm on each node.
BFS example
Let us use an example to understand how the breadth first search algorithm works. We use an undirected graph with 5 vertices.
We start from vertex 0, the BFS algorithm first puts it in the access list, and then puts all adjacent vertices on the stack.
Next, we visit the element in front of the queue, which is 1, and go to its neighboring node. Because 0 has already been visited, we change to visit 2.
Vertex 2 has an unvisited adjacent vertex 4, so we add it to the back of the queue and visit 3 at the front of the queue.
Since 3's only neighboring node (ie 0) has been visited, only 4 remains in the queue. We visit it.
Since the queue is empty, we have completed the breadth-first traversal of the graph.
BFS pseudo code
create a queue Q
mark v as visited and put v into Q
while Q is non-empty
remove the head u of Q
mark and enqueue all (unvisited) neighbours of u
C example
// BFS algorithm in C
#include <stdio.h>
#include <stdlib.h>
#define SIZE 40
struct queue {
int items[SIZE];
int front;
int rear;
};
struct queue* createQueue();
void enqueue(struct queue* q, int);
int dequeue(struct queue* q);
void display(struct queue* q);
int isEmpty(struct queue* q);
void printQueue(struct queue* q);
struct node {
int vertex;
struct node* next;
};
struct node* createNode(int);
struct Graph {
int numVertices;
struct node** adjLists;
int* visited;
};
// BFS algorithm
void bfs(struct Graph* graph, int startVertex) {
struct queue* q = createQueue();
graph->visited[startVertex] = 1;
enqueue(q, startVertex);
while (!isEmpty(q)) {
printQueue(q);
int currentVertex = dequeue(q);
printf("Visited %d\n", currentVertex);
struct node* temp = graph->adjLists[currentVertex];
while (temp) {
int adjVertex = temp->vertex;
if (graph->visited[adjVertex] == 0) {
graph->visited[adjVertex] = 1;
enqueue(q, adjVertex);
}
temp = temp->next;
}
}
}
// Creating a node
struct node* createNode(int v) {
struct node* newNode = malloc(sizeof(struct node));
newNode->vertex = v;
newNode->next = NULL;
return newNode;
}
// Creating a graph
struct Graph* createGraph(int vertices) {
struct Graph* graph = malloc(sizeof(struct Graph));
graph->numVertices = vertices;
graph->adjLists = malloc(vertices * sizeof(struct node*));
graph->visited = malloc(vertices * sizeof(int));
int i;
for (i = 0; i < vertices; i++) {
graph->adjLists[i] = NULL;
graph->visited[i] = 0;
}
return graph;
}
// Add edge
void addEdge(struct Graph* graph, int src, int dest) {
// Add edge from src to dest
struct node* newNode = createNode(dest);
newNode->next = graph->adjLists[src];
graph->adjLists[src] = newNode;
// Add edge from dest to src
newNode = createNode(src);
newNode->next = graph->adjLists[dest];
graph->adjLists[dest] = newNode;
}
// Create a queue
struct queue* createQueue() {
struct queue* q = malloc(sizeof(struct queue));
q->front = -1;
q->rear = -1;
return q;
}
// Check if the queue is empty
int isEmpty(struct queue* q) {
if (q->rear == -1)
return 1;
else
return 0;
}
// Adding elements into queue
void enqueue(struct queue* q, int value) {
if (q->rear == SIZE - 1)
printf("\nQueue is Full!!");
else {
if (q->front == -1)
q->front = 0;
q->rear++;
q->items[q->rear] = value;
}
}
// Removing elements from queue
int dequeue(struct queue* q) {
int item;
if (isEmpty(q)) {
printf("Queue is empty");
item = -1;
} else {
item = q->items[q->front];
q->front++;
if (q->front > q->rear) {
printf("Resetting queue ");
q->front = q->rear = -1;
}
}
return item;
}
// Print the queue
void printQueue(struct queue* q) {
int i = q->front;
if (isEmpty(q)) {
printf("Queue is empty");
} else {
printf("\nQueue contains \n");
for (i = q->front; i < q->rear + 1; i++) {
printf("%d ", q->items[i]);
}
}
}
int main() {
struct Graph* graph = createGraph(6);
addEdge(graph, 0, 1);
addEdge(graph, 0, 2);
addEdge(graph, 1, 2);
addEdge(graph, 1, 4);
addEdge(graph, 1, 3);
addEdge(graph, 2, 4);
addEdge(graph, 3, 4);
bfs(graph, 0);
return 0;
}
BFS algorithm complexity
The time complexity of the BFS algorithm is expressed as O(V + E), where V is the number of nodes and E is the number of edges.
The space complexity of this algorithm is O(V).
BFS algorithm application
- Indexed by search index
- For GPS navigation
- Path finding algorithm
- Use Ford-Fulkerson algorithm to solve the maximum flow of the network
- Cycle detection of undirected graphs
- For minimum spanning tree
Reference documents
[1]Parewa Labs Pvt. Ltd.Depth First Search (DFS)[EB/OL].https://www.programiz.com/dsa/graph-bfs,2020-01-01.