|
| 1 | +<h1 align='center'>BFS - Of Graph</h1> |
| 2 | + |
| 3 | +## Problem Statement |
| 4 | + |
| 5 | +**Problem URL :** [BFS of Graph](https://www.geeksforgeeks.org/problems/bfs-traversal-of-graph/1) |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | + |
| 10 | + |
| 11 | +## Problem Explanation |
| 12 | +#### **Problem Description:** |
| 13 | +The problem asks to perform a **Breadth First Traversal (BFS)** of a graph. BFS is an algorithm for traversing or searching tree or graph data structures. It starts at the root (selecting some arbitrary node as the root in case of a graph) and explores the neighbor nodes at the present depth level before moving on to nodes at the next depth level. |
| 14 | + |
| 15 | +#### **Input:** |
| 16 | +- A graph represented as an **adjacency list**, where each vertex has a list of all the vertices it is connected to. |
| 17 | + |
| 18 | +#### **Output:** |
| 19 | +- A list of vertices in the order they are visited in a **BFS traversal**. |
| 20 | + |
| 21 | +#### **Example:** |
| 22 | + |
| 23 | +Given a graph represented by the following adjacency list: |
| 24 | + |
| 25 | +``` |
| 26 | +0: [1, 2] |
| 27 | +1: [0, 3, 4] |
| 28 | +2: [0] |
| 29 | +3: [1] |
| 30 | +4: [1] |
| 31 | +``` |
| 32 | + |
| 33 | +Here, vertex 0 is connected to 1 and 2, vertex 1 is connected to 0, 3, and 4, and so on. |
| 34 | + |
| 35 | +**Starting from node 0**, the BFS traversal will visit the nodes level by level: |
| 36 | +- Start at node `0`, then visit its neighbors `1` and `2`. |
| 37 | +- Visit the neighbors of node `1`, which are `3` and `4` (in the order they appear). |
| 38 | + |
| 39 | +The expected BFS traversal order is: `0, 1, 2, 3, 4`. |
| 40 | + |
| 41 | +#### **Approach:** |
| 42 | +1. **Initialize:** |
| 43 | + - A **queue** to keep track of the nodes to visit. |
| 44 | + - A **visited list** to ensure that each node is visited only once. |
| 45 | + - A **result list** to store the nodes in the order they are visited. |
| 46 | + |
| 47 | +2. **BFS Traversal:** |
| 48 | + - Start by adding the starting node (e.g., node `0`) to the queue and mark it as visited. |
| 49 | + - While the queue is not empty: |
| 50 | + - Pop the front element from the queue (this is the current node). |
| 51 | + - Add this node to the result list. |
| 52 | + - For each neighbor of the current node, if it has not been visited, add it to the queue and mark it as visited. |
| 53 | + |
| 54 | +3. **Return the result list** containing the BFS order. |
| 55 | + |
| 56 | +## Problem Solution |
| 57 | +```cpp |
| 58 | +class Solution { |
| 59 | + public: |
| 60 | + // Function to return Breadth First Traversal of given graph. |
| 61 | + vector<int> bfsOfGraph(vector<vector<int>> &adj) { |
| 62 | + int V = adj.size(); |
| 63 | + vector<int> result; |
| 64 | + vector<bool> visited(V, false); |
| 65 | + queue<int> q; |
| 66 | + |
| 67 | + q.push(0); |
| 68 | + visited[0] = true; |
| 69 | + |
| 70 | + while(!q.empty()){ |
| 71 | + int currentNode = q.front(); |
| 72 | + q.pop(); |
| 73 | + |
| 74 | + result.push_back(currentNode); |
| 75 | + |
| 76 | + for(int neighbor : adj[currentNode]){ |
| 77 | + if(!visited[neighbor]){ |
| 78 | + q.push(neighbor); |
| 79 | + visited[neighbor] = true; |
| 80 | + } |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + return result; |
| 85 | + |
| 86 | + } |
| 87 | +}; |
| 88 | +``` |
| 89 | +
|
| 90 | +## Problem Solution Explanation |
| 91 | +
|
| 92 | +```cpp |
| 93 | +class Solution { |
| 94 | + public: |
| 95 | + // Function to return Breadth First Traversal of given graph. |
| 96 | + vector<int> bfsOfGraph(vector<vector<int>> &adj) { |
| 97 | +``` |
| 98 | +- **Line 1:** This starts the definition of the `Solution` class with a public method `bfsOfGraph`. |
| 99 | +- **Line 2:** The function `bfsOfGraph` takes an adjacency list (`adj`) as input and returns a vector of integers, which will represent the BFS traversal order. |
| 100 | + |
| 101 | +```cpp |
| 102 | + int V = adj.size(); |
| 103 | + vector<int> result; |
| 104 | + vector<bool> visited(V, false); |
| 105 | + queue<int> q; |
| 106 | +``` |
| 107 | +- **Line 3:** We define `V` as the size of the adjacency list, which is the number of vertices in the graph. |
| 108 | +- **Line 4:** `result` will store the BFS traversal order, initialized as an empty vector. |
| 109 | +- **Line 5:** `visited` is a boolean vector that keeps track of whether a vertex has been visited or not. It's initialized to `false` for all vertices. |
| 110 | +- **Line 6:** `q` is a queue that stores the vertices to be visited during BFS. |
| 111 | +
|
| 112 | +```cpp |
| 113 | + q.push(0); |
| 114 | + visited[0] = true; |
| 115 | +``` |
| 116 | +- **Line 7:** We start the BFS traversal from vertex `0` by pushing it into the queue `q`. |
| 117 | +- **Line 8:** Mark vertex `0` as visited by setting `visited[0]` to `true`. |
| 118 | + |
| 119 | +```cpp |
| 120 | + while(!q.empty()){ |
| 121 | + int currentNode = q.front(); |
| 122 | + q.pop(); |
| 123 | +``` |
| 124 | +- **Line 9-10:** We enter a while loop that continues as long as the queue is not empty. In each iteration: |
| 125 | + - **Line 9:** `currentNode` is assigned the value of the front element of the queue (i.e., the node to be processed). |
| 126 | + - **Line 10:** We pop the front element from the queue since it has been processed. |
| 127 | +
|
| 128 | +```cpp |
| 129 | + result.push_back(currentNode); |
| 130 | +``` |
| 131 | +- **Line 11:** We add the `currentNode` to the `result` vector to record the order in which nodes are visited. |
| 132 | + |
| 133 | +```cpp |
| 134 | + for(int neighbor : adj[currentNode]){ |
| 135 | + if(!visited[neighbor]){ |
| 136 | + q.push(neighbor); |
| 137 | + visited[neighbor] = true; |
| 138 | + } |
| 139 | + } |
| 140 | +``` |
| 141 | +- **Line 12-16:** For each neighbor of the `currentNode` (i.e., for every element in the adjacency list of the `currentNode`): |
| 142 | + - **Line 12:** We iterate over the neighbors of `currentNode`. |
| 143 | + - **Line 13:** If the neighbor has not been visited (`!visited[neighbor]`), we: |
| 144 | + - **Line 14:** Push the neighbor into the queue to visit it later. |
| 145 | + - **Line 15:** Mark the neighbor as visited. |
| 146 | +
|
| 147 | +```cpp |
| 148 | + } |
| 149 | + |
| 150 | + return result; |
| 151 | + } |
| 152 | +}; |
| 153 | +``` |
| 154 | +- **Line 17-19:** Once all neighbors of the current node are processed, the loop continues with the next node in the queue. After the queue is empty, the function returns the `result` vector containing the BFS traversal order. |
| 155 | + |
| 156 | +### **Step 3: Example with Explanation** |
| 157 | + |
| 158 | +Consider the graph with 5 vertices, represented as the adjacency list: |
| 159 | + |
| 160 | +``` |
| 161 | +0: [1, 2] |
| 162 | +1: [0, 3, 4] |
| 163 | +2: [0] |
| 164 | +3: [1] |
| 165 | +4: [1] |
| 166 | +``` |
| 167 | + |
| 168 | +**Step-by-Step BFS Traversal:** |
| 169 | + |
| 170 | +1. **Start at node 0**: |
| 171 | + - Mark node `0` as visited. |
| 172 | + - Add node `0` to the result: `result = [0]`. |
| 173 | + - Add its neighbors (1, 2) to the queue: `q = [1, 2]`. |
| 174 | + |
| 175 | +2. **Process node 1**: |
| 176 | + - Dequeue node `1`, mark it as visited. |
| 177 | + - Add node `1` to the result: `result = [0, 1]`. |
| 178 | + - Add its unvisited neighbors (3, 4) to the queue: `q = [2, 3, 4]`. |
| 179 | + |
| 180 | +3. **Process node 2**: |
| 181 | + - Dequeue node `2`, mark it as visited. |
| 182 | + - Add node `2` to the result: `result = [0, 1, 2]`. |
| 183 | + - Node `0` is already visited, so no new neighbors to add. |
| 184 | + |
| 185 | +4. **Process node 3**: |
| 186 | + - Dequeue node `3`, mark it as visited. |
| 187 | + - Add node `3` to the result: `result = [0, 1, 2, 3]`. |
| 188 | + - Node `1` is already visited, so no new neighbors to add. |
| 189 | + |
| 190 | +5. **Process node 4**: |
| 191 | + - Dequeue node `4`, mark it as visited. |
| 192 | + - Add node `4` to the result: `result = [0, 1, 2, 3, 4]`. |
| 193 | + - Node `1` is already visited, so no new neighbors to add. |
| 194 | + |
| 195 | +At the end, the **BFS order** is: `[0, 1, 2, 3, 4]`. |
| 196 | + |
| 197 | +### **Step 4: Time and Space Complexity** |
| 198 | + |
| 199 | +#### **Time Complexity:** |
| 200 | +- **Queue Operations:** Each vertex is added and removed from the queue exactly once. This results in `O(V)` time for all vertices. |
| 201 | +- **Neighbor Processing:** For each vertex, we process all its neighbors, and each edge is processed once. This gives `O(E)` time for all edges. |
| 202 | +- Thus, the overall **time complexity** is: **`O(V + E)`**, where `V` is the number of vertices and `E` is the number of edges in the graph. |
| 203 | + |
| 204 | +#### **Space Complexity:** |
| 205 | +- **Visited Array:** We use an array of size `V` to mark visited nodes, which takes `O(V)` space. |
| 206 | +- **Queue:** The maximum number of nodes in the queue at any time is `O(V)`. |
| 207 | +- **Result Array:** The result array stores all the vertices, which takes `O(V)` space. |
| 208 | +- Thus, the overall **space complexity** is: **`O(V)`**. |
| 209 | + |
| 210 | +### **Step 5: Recommendations for Students** |
| 211 | + |
| 212 | +1. **Understand BFS Concept:** Make sure you understand the concept of BFS and how it explores nodes level by level. |
| 213 | +2. **Practice on Different Graph Representations:** Try implementing BFS on different graph representations (adjacency matrix, adjacency list, etc.). |
| 214 | +3. **Edge Cases:** Be mindful of edge cases, like when the graph is disconnected or when there are no edges. |
| 215 | +4. **Explore Variants:** BFS can be used to solve problems like finding the shortest path in an unweighted graph. Try solving such problems to enhance your understanding of BFS. |
| 216 | + |
0 commit comments