Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Iterative DFS #45

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions Graph_Functions/DFS_Iterative/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Iterative Depth-First Search (DFS) Algorithm

## Overview

Depth-First Search (DFS) is a graph traversal algorithm that explores as far as possible along each branch before backtracking. It is commonly implemented recursively, but here we will discuss an **iterative approach** using a **stack** to simulate recursion.

This version of the DFS will start from a given node (usually node 0) and explore all its neighbors before moving on to the next unvisited neighbor. If all neighbors are visited, it backtracks using the stack.

## Steps of the Algorithm

1. **Initialize**:
- A stack to simulate recursion.
- A `visited` list to track the nodes that have been visited.
- An empty list to store the DFS traversal order.

2. **Start DFS**:
- Push the starting node (usually `0`) onto the stack.
- Mark it as visited.

3. **Explore**:
- Pop a node from the stack and visit it.
- Push all unvisited neighbors of the current node onto the stack and mark them as visited.

4. **Repeat**:
- Continue popping nodes from the stack and visiting unvisited neighbors until the stack is empty.

5. **End**:
- Once the stack is empty, the DFS traversal is complete.

## Example Graph

Consider the following graph:

0 -- 1
|
2 -- 3 -- 4

- Node `0` is connected to nodes `1` and `2`.
- Node `1` is connected to node `0`.
- Node `2` is connected to nodes `0` and `3`.
- Node `3` is connected to nodes `2` and `4`.
- Node `4` is connected to node `3`.

The graph can be represented as an adjacency list:
```python
adj = [
[1, 2], # Neighbors of 0
[0], # Neighbors of 1
[0, 3], # Neighbors of 2
[2, 4], # Neighbors of 3
[3] # Neighbors of 4
]
# DFS Traversal

## Iterative DFS Process:

1. **Start at node 0**:
- Push 0 onto the stack: `stack = [0]`
- Mark 0 as visited.
- Pop 0 and visit it.

2. **Visit neighbors of node 0**:
- The neighbors of 0 are `1` and `2`.
- Push 2 and 1 onto the stack: `stack = [2, 1]`
- Mark both 1 and 2 as visited.

3. **Visit node 1**:
- Pop 1 from the stack: `stack = [2]`
- Visit 1. The only unvisited neighbor is 0, which is already visited.

4. **Visit node 2**:
- Pop 2 from the stack: `stack = []`
- Visit 2. The neighbors of 2 are 0 and 3.
- Push 3 onto the stack: `stack = [3]`
- Mark 3 as visited.

5. **Visit node 3**:
- Pop 3 from the stack: `stack = []`
- Visit 3. The neighbors of 3 are 2 and 4.
- Push 4 onto the stack: `stack = [4]`
- Mark 4 as visited.

6. **Visit node 4**:
- Pop 4 from the stack: `stack = []`
- Visit 4. The only neighbor is 3, which is already visited.

7. The stack is now empty, and the traversal is complete.

## DFS Order:
The order in which nodes are visited is: `0, 2, 3, 4, 1`.

## Time Complexity
- **Time Complexity**: O(V + E), where V is the number of vertices (nodes) and E is the number of edges. We visit each node once and explore all its edges.
- **Space Complexity**: O(V), as we store the visited list and use the stack to store nodes during traversal.
64 changes: 64 additions & 0 deletions Graph_Functions/DFS_Iterative/dfs_iter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <bits/stdc++.h>
using namespace std;

// Iterative DFS function that takes the adjacency list and an empty container
void dfs(const vector<vector<int>>& adj, vector<int>& dfs_order) {
int n = adj.size();

// Create a visited vector to track which nodes have been visited
vector<bool> visited(n, false);

// Stack for the iterative DFS
stack<int> st;

// Let's start DFS from node 0 (or any other node)
st.push(0);
visited[0] = true;

while (!st.empty()) {
int node = st.top();
st.pop();

// Add the current node to the DFS order
dfs_order.push_back(node);

// Explore all neighbors of the current node
for (int neighbor : adj[node]) {
if (!visited[neighbor]) {
visited[neighbor] = true;
st.push(neighbor);
}
}
}
}

int main() {
// Define the graph as an adjacency list
int n = 5; // Number of nodes
vector<vector<int>> adj(n);

// Adding edges (undirected graph)
adj[0].push_back(1);
adj[0].push_back(2);
adj[1].push_back(0);
adj[2].push_back(0);
adj[2].push_back(3);
adj[3].push_back(2);
adj[3].push_back(4);
adj[4].push_back(3);

// Container to store the DFS order
vector<int> dfs_order;

// Call the DFS function
dfs(adj, dfs_order);

// Print the DFS order
cout << "DFS Order: ";
for (int node : dfs_order) {
cout << node << " ";
}
cout << endl;

return 0;
}
75 changes: 75 additions & 0 deletions Graph_Functions/DFS_Iterative/dfs_iter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package DFS_Iterative;
import java.util.*;

public class dfs_iter {

// Iterative DFS function that takes the adjacency list and an empty container
public static void dfs(List<List<Integer>> adj, List<Integer> dfsOrder) {
int n = adj.size();

// Create a visited array to track which nodes have been visited
boolean[] visited = new boolean[n];

// Stack for iterative DFS
Stack<Integer> stack = new Stack<>();

// Let's start DFS from node 0 (or any other node)
stack.push(0);
visited[0] = true;

while (!stack.isEmpty()) {
int node = stack.pop();

// Add the current node to the DFS order
dfsOrder.add(node);

// Explore all neighbors of the current node
for (int neighbor : adj.get(node)) {
if (!visited[neighbor]) {
visited[neighbor] = true;
stack.push(neighbor);
}
}
}
}

// Main function where the DFS function is called and use case is demonstrated
public static void func_body() {
// Define the graph as an adjacency list
int n = 5; // Number of nodes
List<List<Integer>> adj = new ArrayList<>();

// Initialize adjacency list
for (int i = 0; i < n; i++) {
adj.add(new ArrayList<>());
}

// Adding edges (undirected graph)
adj.get(0).add(1);
adj.get(0).add(2);
adj.get(1).add(0);
adj.get(2).add(0);
adj.get(2).add(3);
adj.get(3).add(2);
adj.get(3).add(4);
adj.get(4).add(3);

// Container to store the DFS order
List<Integer> dfsOrder = new ArrayList<>();

// Call the DFS function
dfs(adj, dfsOrder);

// Print the DFS order
System.out.print("DFS Order: ");
for (int node : dfsOrder) {
System.out.print(node + " ");
}
System.out.println();
}

public static void main(String[] args) {
// Main function where the DFS function is called
func_body();
}
}
52 changes: 52 additions & 0 deletions Graph_Functions/DFS_Iterative/dfs_iter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Python Code Example

def dfs(adj, n):
# Create a visited list to track visited nodes
visited = [False] * n
stack = []
dfs_order = []

# Start DFS from node 0 (or any other node)
stack.append(0)
visited[0] = True

while stack:
node = stack.pop()

# Add the current node to the DFS order
dfs_order.append(node)

# Explore all neighbors of the current node
for neighbor in adj[node]:
if not visited[neighbor]:
visited[neighbor] = True
stack.append(neighbor)

return dfs_order


def func_body():
# Define the graph as an adjacency list
n = 5 # Number of nodes
adj = [[] for _ in range(n)]

# Adding edges (undirected graph)
adj[0].append(1)
adj[0].append(2)
adj[1].append(0)
adj[2].append(0)
adj[2].append(3)
adj[3].append(2)
adj[3].append(4)
adj[4].append(3)

# Call the DFS function and get the DFS order
dfs_order = dfs(adj, n)

# Print the DFS order
print("DFS Order:", " ".join(map(str, dfs_order)))


if __name__ == "__main__":
# Main function where the function is called and use case is demonstrated
func_body()
4 changes: 2 additions & 2 deletions RoadMap.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ These are fundamental algorithms and functions often used in competitive program
- [x] [Reverse an Array (copy)](Array_Functions/Reverse_an_Array)
- [x] [Reverse an Array (in place)](Array_Functions/Reversing_an_array(in_place))
- [x] [Find Max-Min of Array](Array_Functions/Min_Max_Functions)
- [ ] Prefix Array
- [x] [Prefix Array](Array_Functions/Prefix_Sum)
- [ ] Suffix Array
- [ ] Finding Mex of Array (Smallest Positive integer which is not present in array)
- [ ] Print 2D Matrix
Expand Down Expand Up @@ -43,7 +43,7 @@ These are fundamental algorithms and functions often used in competitive program
### 4. Graph Algorithms
- [x] [Depth-First Search (DFS) (Recursive)](Graph_Functions/DFS_Recursion)
- [x] [Breadth-First Search (BFS)](Graph_Functions/BFS_Recursion)
- [ ] Depth-First Search (DFS) (Iterative)
- [x] [Depth-First Search (DFS) (Iterative)](Graph_Functions/DFS_Iterative)
- [ ] Dijkstra's Shortest Path Algorithm
- [ ] Bellman-Ford Algorithm
- [x] [Kruskal’s Algorithm](Graph_Functions/Kruskal_s)
Expand Down