Skip to content

Commit 720072f

Browse files
authored
Update README.md
1 parent 13035ec commit 720072f

File tree

1 file changed

+143
-163
lines changed
  • 23 - Graph Data Structure Problems/02 - BFS Traversal in Graph

1 file changed

+143
-163
lines changed

23 - Graph Data Structure Problems/02 - BFS Traversal in Graph/README.md

Lines changed: 143 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public:
8383
}
8484
}
8585

86-
// Function to perform BFS traversal
86+
// Iterative BFS traversal
8787
void bfs(int startNode) {
8888
vector<bool> visited(adjacencyList.size(), false); // Visited array
8989
queue<int> q; // Queue for BFS
@@ -92,7 +92,7 @@ public:
9292
visited[startNode] = true;
9393
q.push(startNode);
9494

95-
cout << "BFS Traversal: ";
95+
cout << "BFS Traversal (Iterative): ";
9696

9797
while (!q.empty()) {
9898
int currentNode = q.front();
@@ -111,6 +111,46 @@ public:
111111
}
112112
cout << endl;
113113
}
114+
115+
// Recursive BFS traversal
116+
void bfsRecursiveHelper(int startNode, vector<bool>& visited, queue<int>& q) {
117+
if (q.empty()) {
118+
return; // Base case: queue is empty, stop recursion
119+
}
120+
121+
int currentNode = q.front();
122+
q.pop();
123+
124+
// Process the current node (e.g., print it)
125+
cout << currentNode << " ";
126+
127+
// Visit all unvisited neighbors
128+
for (int neighbor : adjacencyList[currentNode]) {
129+
if (!visited[neighbor]) {
130+
visited[neighbor] = true;
131+
q.push(neighbor);
132+
}
133+
}
134+
135+
// Recursive call with the updated queue
136+
bfsRecursiveHelper(startNode, visited, q);
137+
}
138+
139+
void bfsRecursive(int startNode) {
140+
vector<bool> visited(adjacencyList.size(), false); // Visited array
141+
queue<int> q; // Queue for BFS
142+
143+
// Start BFS from the startNode
144+
visited[startNode] = true;
145+
q.push(startNode);
146+
147+
cout << "BFS Traversal (Recursive): ";
148+
149+
// Start recursive BFS traversal
150+
bfsRecursiveHelper(startNode, visited, q);
151+
152+
cout << endl;
153+
}
114154
};
115155

116156
int main() {
@@ -126,222 +166,162 @@ int main() {
126166
g.addEdge(1, 4);
127167
g.addEdge(2, 5);
128168

129-
// Perform BFS traversal starting from node 0
169+
// Perform BFS traversal starting from node 0 (Iterative)
130170
g.bfs(0);
131171

172+
// Perform BFS traversal starting from node 0 (Recursive)
173+
g.bfsRecursive(0);
174+
132175
return 0;
133176
}
177+
134178
```
135179
136180
### Source Code Explanation
137-
Here’s a **line-by-line explanation** of the BFS traversal code with examples and the corresponding output:
138-
139-
### **Code Explanation**
140-
141-
```cpp
142-
#include <iostream>
143-
#include <vector>
144-
#include <queue>
145-
using namespace std;
146-
```
147181
148-
- **Purpose**: These are essential header files.
149-
- `#include <iostream>`: For input/output operations.
150-
- `#include <vector>`: For using the adjacency list as a vector of vectors.
151-
- `#include <queue>`: BFS requires a queue to manage nodes to visit.
182+
#### 1. **Graph Class:**
152183
184+
The `Graph` class manages the graph structure using an **adjacency list** to store the neighbors of each node.
153185
186+
##### **Constructor:**
154187
```cpp
155-
class Graph {
156-
public:
157-
vector<vector<int>> adjacencyList;
188+
Graph(int totalNodes) {
189+
adjacencyList.resize(totalNodes);
190+
}
158191
```
192+
- The constructor initializes the graph by resizing the adjacency list to hold the `totalNodes`. Each node initially has an empty list of neighbors.
159193

160-
- **Explanation**:
161-
- A class named `Graph` is defined.
162-
- `adjacencyList`: A vector of vectors to represent the graph. Each index `i` holds a list of nodes connected to node `i`.
163-
164-
165-
194+
##### **addEdge Function:**
166195
```cpp
167-
Graph(int totalNodes) {
168-
adjacencyList.resize(totalNodes);
196+
void addEdge(int sourceNode, int destinationNode, bool isDirected = false) {
197+
adjacencyList[sourceNode].push_back(destinationNode);
198+
if (!isDirected) {
199+
adjacencyList[destinationNode].push_back(sourceNode);
169200
}
201+
}
170202
```
203+
- `addEdge` adds an edge from `sourceNode` to `destinationNode`. If the graph is undirected (default behavior), it adds the reverse edge from `destinationNode` to `sourceNode`.
171204
172-
- **Explanation**:
173-
- Constructor initializes the graph with `totalNodes` nodes.
174-
- Resizes the `adjacencyList` to ensure every node has an associated list.
175-
176-
205+
#### 2. **BFS (Iterative) Implementation:**
177206
207+
##### **BFS Function:**
178208
```cpp
179-
void addEdge(int sourceNode, int destinationNode, bool isDirected = false) {
180-
adjacencyList[sourceNode].push_back(destinationNode);
181-
if (!isDirected) {
182-
adjacencyList[destinationNode].push_back(sourceNode);
209+
void bfs(int startNode) {
210+
vector<bool> visited(adjacencyList.size(), false);
211+
queue<int> q;
212+
visited[startNode] = true;
213+
q.push(startNode);
214+
215+
cout << "BFS Traversal (Iterative): ";
216+
217+
while (!q.empty()) {
218+
int currentNode = q.front();
219+
q.pop();
220+
cout << currentNode << " ";
221+
222+
for (int neighbor : adjacencyList[currentNode]) {
223+
if (!visited[neighbor]) {
224+
visited[neighbor] = true;
225+
q.push(neighbor);
226+
}
183227
}
184228
}
229+
cout << endl;
230+
}
185231
```
186232

187-
- **Purpose**: Adds edges between nodes.
188-
- **Parameters**:
189-
- `sourceNode`: Start of the edge.
190-
- `destinationNode`: End of the edge.
191-
- `isDirected`: If `true`, the edge is one-way; otherwise, it is bidirectional.
192-
- **How it works**:
193-
- Adds `destinationNode` to `sourceNode`'s adjacency list.
194-
- If the graph is undirected, it also adds `sourceNode` to `destinationNode`'s adjacency list.
195-
196-
197-
198-
```cpp
199-
void bfs(int startNode) {
200-
vector<bool> visited(adjacencyList.size(), false);
201-
queue<int> q;
202-
```
203-
204-
- **Explanation**:
205-
- Initializes a `visited` array to track visited nodes.
206-
- A queue `q` is used to manage BFS traversal.
207-
208-
209-
210-
```cpp
211-
visited[startNode] = true;
212-
q.push(startNode);
213-
```
214-
215-
- **Explanation**:
216-
- Marks the `startNode` as visited.
217-
- Pushes the `startNode` into the queue to begin traversal.
218-
219-
220-
221-
```cpp
222-
cout << "BFS Traversal: ";
223-
```
224-
225-
- **Explanation**: Outputs a label for the BFS traversal results.
233+
- **Explanation:**
234+
- The function takes `startNode` as input and performs a **Breadth-First Search** (BFS) starting from that node.
235+
- `visited` array ensures that no node is visited more than once.
236+
- A `queue` is used to manage the nodes to visit next. We push the `startNode` into the queue and mark it as visited.
237+
- The BFS traversal proceeds by dequeuing nodes from the front of the queue and processing them. Then, all their unvisited neighbors are pushed into the queue.
226238

239+
#### 3. **BFS (Recursive) Implementation:**
227240

241+
##### **Recursive Helper Function:**
228242
```cpp
229-
while (!q.empty()) {
230-
int currentNode = q.front();
231-
q.pop();
232-
```
233-
234-
- **Explanation**:
235-
- The loop continues until the queue is empty.
236-
- Retrieves the front node of the queue (`currentNode`) and removes it.
243+
void bfsRecursiveHelper(int startNode, vector<bool>& visited, queue<int>& q) {
244+
if (q.empty()) {
245+
return; // Base case: queue is empty, stop recursion
246+
}
237247

248+
int currentNode = q.front();
249+
q.pop();
250+
cout << currentNode << " ";
238251

252+
for (int neighbor : adjacencyList[currentNode]) {
253+
if (!visited[neighbor]) {
254+
visited[neighbor] = true;
255+
q.push(neighbor);
256+
}
257+
}
239258

240-
```cpp
241-
cout << currentNode << " ";
259+
bfsRecursiveHelper(startNode, visited, q); // Recursive call
260+
}
242261
```
262+
- **Explanation:**
263+
- This helper function is designed to perform the recursive part of BFS.
264+
- It processes nodes in a similar way to the iterative BFS but using recursion to handle the queue management.
265+
- If the queue is empty, the recursion terminates. Otherwise, it pops a node from the queue, processes it, and pushes all its unvisited neighbors into the queue, making a recursive call after each step.
243266
244-
- **Explanation**: Prints the `currentNode` to show its processing in BFS.
245-
246-
267+
##### **Main Recursive BFS Function:**
247268
```cpp
248-
for (int neighbor : adjacencyList[currentNode]) {
249-
if (!visited[neighbor]) {
250-
visited[neighbor] = true;
251-
q.push(neighbor);
252-
}
253-
}
254-
}
255-
cout << endl;
256-
}
269+
void bfsRecursive(int startNode) {
270+
vector<bool> visited(adjacencyList.size(), false);
271+
queue<int> q;
272+
visited[startNode] = true;
273+
q.push(startNode);
274+
275+
cout << "BFS Traversal (Recursive): ";
276+
bfsRecursiveHelper(startNode, visited, q);
277+
cout << endl;
278+
}
257279
```
280+
- This function initializes the `visited` array and the queue, starting from `startNode`, and calls the recursive helper to perform the BFS traversal.
258281

259-
- **Explanation**:
260-
- Iterates through all neighbors of the `currentNode`.
261-
- If a neighbor has not been visited:
262-
- Marks it as visited.
263-
- Adds it to the queue for future processing.
264-
265-
266-
282+
#### 4. **Main Function:**
267283
```cpp
268284
int main() {
269285
int totalNodes = 6;
270-
271-
// Create the graph
272286
Graph g(totalNodes);
273-
```
274-
275-
- **Explanation**:
276-
- Declares `totalNodes` as `6`.
277-
- Creates a graph object `g` with `6` nodes.
278-
279287

280-
```cpp
281288
g.addEdge(0, 1);
282289
g.addEdge(0, 2);
283290
g.addEdge(1, 3);
284291
g.addEdge(1, 4);
285292
g.addEdge(2, 5);
286-
```
287-
288-
- **Explanation**:
289-
- Adds edges to the graph:
290-
- Node `0` is connected to nodes `1` and `2`.
291-
- Node `1` is connected to nodes `3` and `4`.
292-
- Node `2` is connected to node `5`.
293-
294293

295-
```cpp
296-
g.bfs(0);
294+
g.bfs(0); // Iterative BFS starting from node 0
295+
g.bfsRecursive(0); // Recursive BFS starting from node 0
297296

298297
return 0;
299298
}
300299
```
300+
- Creates a graph with 6 nodes.
301+
- Adds edges to the graph.
302+
- Calls both the **Iterative BFS** (`g.bfs(0)`) and **Recursive BFS** (`g.bfsRecursive(0)`) functions to perform BFS starting from node `0`.
301303

302-
- **Explanation**:
303-
- Calls `bfs(0)` to perform BFS starting from node `0`.
304-
- Returns `0` to indicate successful program execution.
305-
306-
307-
### **Graph Representation**
308-
309-
The graph looks like this:
304+
### **Output:**
310305

311306
```
312-
0
313-
/ \
314-
1 2
315-
/ \ \
316-
3 4 5
307+
BFS Traversal (Iterative): 0 1 2 3 4 5
308+
BFS Traversal (Recursive): 0 1 2 3 4 5
317309
```
318310

311+
### **Time and Space Complexity:**
319312

320-
### **Output**
321-
322-
```
323-
BFS Traversal: 0 1 2 3 4 5
324-
```
325-
326-
- **Explanation**:
327-
- BFS starts at node `0`.
328-
- Visits nodes `1` and `2` (neighbors of `0`).
329-
- Then visits nodes `3` and `4` (neighbors of `1`) and finally node `5` (neighbor of `2`).
330-
331-
### **Time Complexity**
332-
333-
1. **Adjacency List Traversal**:
334-
- Each edge is visited once: **O(E)**.
335-
- Each node is visited once: **O(V)**.
336-
337-
Total Time Complexity: **O(V + E)**.
338-
339-
340-
### **Space Complexity**
313+
#### **Time Complexity:**
314+
- Both **Iterative BFS** and **Recursive BFS** have the same time complexity:
315+
- **O(V + E)**, where:
316+
- `V` is the number of vertices (nodes) in the graph.
317+
- `E` is the number of edges in the graph.
318+
- We visit each vertex and edge exactly once.
341319

342-
1. **Visited Array**: Stores the state of each node: **O(V)**.
343-
2. **Queue**: Can hold up to **O(V)** nodes.
344-
3. **Adjacency List**: Takes **O(V + E)**.
320+
#### **Space Complexity:**
321+
- **O(V)**:
322+
- The space is mainly used for the `visited` array (of size `V`), the queue (`O(V)`), and the recursion stack in the recursive approach (`O(V)` in the worst case).
345323

346-
Total Space Complexity: **O(V + E)**.
324+
### **Conclusion:**
325+
- **Iterative BFS** is more common and efficient in terms of stack space, as it avoids recursion depth limitations.
326+
- **Recursive BFS** is an interesting implementation that can be used for educational purposes, but it may suffer from stack overflow issues for large graphs.
347327

0 commit comments

Comments
 (0)