Implementation of BFS using Adjacency Matrix


A simple graph traversal algorithm called Breadth−First Search (BFS) is employed to examine a graph step by step. Before going to an additional stage of vertices, it begins with a certain vertex (source) and checks all of its neighbours in an ordered way. In this blog post, we'll look at three different ways to use an adjacency matrix in CPP methods to construct BFS. We'll go over the algorithm used by each technique, offer relevant code representations, and demonstrate each method's unique results.

Methods Used

  • Iterative BFS

  • BFS with Level Information

  • BFS Shortest Path

Iterative BFS

The first technique employs an adjacency matrix and an iterative methodology to implement BFS. To maintain a record of the vertices that need to be viewed, it makes use of a queue.

Algorithm

  • Make an array and queue to record viewed vertices.

  • Enqueue the source vertex and identify it as viewed.

  • Take the following action while there is still a queue:

    • Display a vertex by dequeuing it using the queue.

    • Label all nearby unvisited vertices as attended and queue them all up.

Exampple

#include <iostream>
#include <queue>
using namespace std;

// Function to perform Iterative BFS using adjacency matrix
void BFS(int** adjacencyMatrix, int numVertices, int startVertex) {
    // Create a boolean array to track visited vertices
    bool* visited = new bool[numVertices];
    for (int i = 0; i < numVertices; i++) {
        visited[i] = false;
    }

    // Create a queue for BFS traversal
    queue<int> q;

    // Enqueue the starting vertex and mark it as visited
    q.push(startVertex);
    visited[startVertex] = true;

    while (!q.empty()) {
        // Dequeue a vertex from the queue
        int currentVertex = q.front();
        q.pop();

        // Process the current vertex (e.g., print it)
        cout << currentVertex << " ";

        // Iterate through all vertices
        for (int i = 0; i < numVertices; i++) {
            // Check if there is an edge between currentVertex and vertex i
            // and if vertex i is not visited
            if (adjacencyMatrix[currentVertex][i] == 1 && !visited[i]) {
                // Enqueue the vertex i and mark it as visited
                q.push(i);
                visited[i] = true;
            }
        }
    }

    delete[] visited;
}

// Example usage
int main() {
    int numVertices = 5;

    // Create an adjacency matrix for the graph
    int** adjacencyMatrix = new int*[numVertices];
    for (int i = 0; i < numVertices; i++) {
        adjacencyMatrix[i] = new int[numVertices];
    }

    // Initialize the adjacency matrix (example graph)
    adjacencyMatrix[0][1] = 1;
    adjacencyMatrix[0][2] = 1;
    adjacencyMatrix[1][3] = 1;
    adjacencyMatrix[2][3] = 1;
    adjacencyMatrix[3][4] = 1;

    int startVertex = 0; // Starting vertex for BFS

    // Perform BFS traversal
    cout << "BFS traversal starting from vertex " << startVertex << ":" << endl;
    BFS(adjacencyMatrix, numVertices, startVertex);

    // Clean up
    for (int i = 0; i < numVertices; i++) {
        delete[] adjacencyMatrix[i];
    }
    delete[] adjacencyMatrix;

    return 0;
}

Output

BFS traversal starting from vertex 0:
0 1 2 3 4 

BFS with Level Information

The third technique adds level data needed for each vertex to the standard BFS execution. When the degree of each vertex from the initial point is needed, it can be valuable.

Algorithm

  • Make a queue, a marking array for inspected vertices, and a level−storing array for every vertex.

  • Change the scale of the initial vertex to 0, enqueue it, and label it as viewed.

  • Take the following action while there is still a queue:

    • Display a vertex's degree and dequeue it from the queue.

    • Enqueue all nearby vertices that aren't yet viewed, record them as viewed, and raise their level by one from the present vertex's degree.

Example

#include <iostream>
#include <queue>
#include <vector>

// Function to perform Breadth First Search (BFS) with level information
void bfsWithLevel(const std::vector<std::vector<int>>& graph, int source) {
    int numVertices = graph.size();

    // Create visited array to keep track of visited vertices
    std::vector<bool> visited(numVertices, false);

    // Create level array to store the level of each vertex
    std::vector<int> level(numVertices, 0);

    // Create a queue for BFS traversal
    std::queue<int> q;

    // Mark the source vertex as visited and enqueue it
    visited[source] = true;
    q.push(source);

    while (!q.empty()) {
        // Dequeue a vertex from the queue
        int currentVertex = q.front();
        q.pop();

        // Process the current vertex
        std::cout << "Vertex: " << currentVertex << " Level: " << level[currentVertex] << std::endl;

        // Explore all adjacent vertices of the current vertex
        for (int adjacentVertex = 0; adjacentVertex < numVertices; ++adjacentVertex) {
            // If there is an edge from the current vertex to the adjacent vertex and
            // the adjacent vertex is not visited yet
            if (graph[currentVertex][adjacentVertex] == 1 && !visited[adjacentVertex]) {
                // Mark the adjacent vertex as visited
                visited[adjacentVertex] = true;

                // Update the level of the adjacent vertex
                level[adjacentVertex] = level[currentVertex] + 1;

                // Enqueue the adjacent vertex
                q.push(adjacentVertex);
            }
        }
    }
}

int main() {
    // Example usage
    std::vector<std::vector<int>> graph = {
        {0, 1, 1, 0},
        {1, 0, 0, 1},
        {1, 0, 0, 1},
        {0, 1, 1, 0}
    };

    bfsWithLevel(graph, 0);

    return 0;
}

Output

Vertex: 0 Level: 0
Vertex: 1 Level: 1
Vertex: 2 Level: 1
Vertex: 3 Level: 2

BFS Shortest Path

The fourth technique applies BFS to determine the shortest path in a network symbolised by an adjacency matrix between an initial vertex and the objective vertex. In order to re−create the way, it maintains track of the parent for every vertex.

Algorithm

  • Make a queue, an array for noting checked out vertices, an array that keeps each vertex's parent, and an array to record the distance from the initial source.

  • Change the parent of the initial vertex to −1 and the distance to 0 while marking it as viewed and enqueuing it.

  • Take the following action while there is still a queue:

    • A vertex can be dequeued from the queue.

    • Terminate the BFS if the goal's vertex is the dequeued vertex.

    • Add their parent to the present vertex, assign all nearby unvisited vertices as viewed, queue them up, and modify the distance between them.

  • Employing the parent array, retrace a route from the desired vertex to the point of origin if the aim vertex has been attained.

Example

#include <iostream>
#include <queue>
#include <vector>
#include <utility> // for std::pair

using namespace std;

void BFS(vector<pair<int, int>>& edgeList, int numVertices, int source) {
    vector<bool> visited(numVertices, false);
    vector<int> distance(numVertices, 0);
    queue<int> q;

    // Mark the source vertex as visited and enqueue it
    visited[source] = true;
    q.push(source);

    while (!q.empty()) {
        int currentVertex = q.front();
        q.pop();

        // Process the current vertex (e.g., print its value)
        cout << currentVertex << " ";

        // Explore all adjacent vertices of the current vertex
        for (const auto& edge : edgeList) {
            int u = edge.first;
            int v = edge.second;

            if (u == currentVertex && !visited[v]) {
                visited[v] = true;
                distance[v] = distance[currentVertex] + 1;
                q.push(v);
            } else if (v == currentVertex && !visited[u]) {
                visited[u] = true;
                distance[u] = distance[currentVertex] + 1;
                q.push(u);
            }
        }
    }
}

int main() {
    int numVertices = 6;

    // Example graph representation (edge list)
    vector<pair<int, int>> edgeList = {
        {0, 1},
        {0, 2},
        {1, 3},
        {2, 3},
        {2, 4},
        {3, 4},
        {3, 5},
        {4, 5},
        {1, 0}
    };

    int source = 0;  // Starting vertex for BFS

    cout << "BFS Traversal: ";
    BFS(edgeList, numVertices, source);

    return 0;
}

Output

BFS Traversal: 0 1 2 3 4 5 

Conclusion

In this post, we looked at three distinct ways to execute Breadth−First Search (BFS) in CPP algorithms implementing an adjacency matrix. Iterative BFS, recursive BFS, BFS with level information, and discovering the shortest path are just a few of the functions that each technique delivers as it traverses a graph stage by stage. You can quickly explore and analyse graphs, carry out level−based functions, and determine the shortest pathways between vertices by comprehending and using these techniques. The strategy chosen will rely on the particular needs and features of the current graph.

Updated on: 14-Jul-2023

2K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements