We will be seeing the Iterative way for implementing Depth First Search (DFS). Although there are various ways to write this Iterative code.
However, we will write the code little differently. So that you can corelate it with the Depth First Search (DFS) explanation.
In the Iterative code we will create the stack and maintain it ourselves.
using System.Collections.Generic; public class DFSIteration { static List<List<string>> adjacencyList; static List<string> vertices; static bool[] visited; void insertVertex(string vertex) { vertices.Add(vertex); } void constructAdjacencyList(string vtx, string adjcVertex) { int vtxIndex = vertices.IndexOf(vtx); adjacencyList.Add(new List<string>()); adjacencyList[vtxIndex].Add(adjcVertex); } void depthFirstSearch(string source){ int sourceIndex = vertices.IndexOf(source); visited[sourceIndex] = true; Stack<string> stack = new Stack<string>(); stack.Push(source); System.Console.Write(source+" --> "); while (stack.Count != 0) { source = stack.Peek(); sourceIndex = vertices.IndexOf(source); string str = ""; foreach (string iter in adjacencyList[sourceIndex] ) { str = iter; int i = vertices.IndexOf(str); if (visited[i] == false) { stack.Push(str); visited[i] = true; System.Console.Write(str + " --> "); break; } } if (!stack.Peek().Equals(str)){ stack.Pop(); } } } public static void Main(string[] args) { int V = 6; DFSIteration dfsIteration = new DFSIteration(); visited = new bool[V]; adjacencyList = new List<List<string>>(); vertices = new List<string>(); // Insert Vertices dfsIteration.insertVertex("a"); dfsIteration.insertVertex("b"); dfsIteration.insertVertex("c"); dfsIteration.insertVertex("d"); dfsIteration.insertVertex("e"); dfsIteration.insertVertex("f"); dfsIteration.constructAdjacencyList("a", "c"); dfsIteration.constructAdjacencyList("a", "d"); dfsIteration.constructAdjacencyList("b", "d"); dfsIteration.constructAdjacencyList("b" ,"e"); dfsIteration.constructAdjacencyList("b" ,"c"); dfsIteration.constructAdjacencyList("c", "a"); dfsIteration.constructAdjacencyList("c", "b"); dfsIteration.constructAdjacencyList("c", "e"); dfsIteration.constructAdjacencyList("d", "a"); dfsIteration.constructAdjacencyList("d" ,"b"); dfsIteration.constructAdjacencyList("d", "e"); dfsIteration.constructAdjacencyList("d", "f"); dfsIteration.constructAdjacencyList("e", "b"); dfsIteration.constructAdjacencyList("e", "c"); dfsIteration.constructAdjacencyList("e", "d"); dfsIteration.constructAdjacencyList("e", "f"); dfsIteration.constructAdjacencyList("f", "d"); dfsIteration.constructAdjacencyList("f", "e"); dfsIteration.depthFirstSearch("a"); } }
We have implemented Depth First Search (DFS) on the below graph :
We can take various ways to navigate the graph using Depth First Search (DFS). Just remember our main intension is to visit all the vertices.
In this case we have covered the graph in the following path :
a --> c --> b --> d --> e --> f
Let us see how ?
Below code explains the methods :
Almost the same we have discussed in BFS. You can skip it if you wane to.
Click Here - To understand the details of the methods 'void constructAdjacencyList(string vtx, string adjcVertex)' and 'void insertVertex(string vertex)'.
Let's list out, what all do we need to support Depth First Search Data Structure.
Now, let us see the above code.
We have a Linked List to store the Vertices.
static List<string> vertices;
We also have a doubly Linked List to store the Adjacency List.
static List<List<string>> adjacencyList;
Similarly, we have a stack defined inside the method depthFirstSearch(...).
Stack<string> stack = new Stack<>();
And, there is a bool array to store the Vertices that are visited.
static bool visited[];
So, the first thing we will do is, insert the Vertices to the List<string> vertices Linked List.
vertices = new List<string>(); dfsIteration.insertVertex("a"); dfsIteration.insertVertex("b"); dfsIteration.insertVertex("c"); dfsIteration.insertVertex("d"); dfsIteration.insertVertex("e"); dfsIteration.insertVertex("f");
void insertVertex(string vertex) { vertices.AddLast(vertex); }
void insertVertex(string vertex) is quite simple.
There is just one statement in it.
vertices.AddLast(vertex);
It accepts string vertex as a parameter and adds it to the Linked List, vertices.
The next thing we will do is, create an Adjacency List to track the Adjacent Vertices.
Let us take the example of vertex a, to explain the creation of Adjacency List.
As we have seen, a has two adjacent vertices(i.e. c and d). And we have used the constructAdjacencyList(...) method to construct the Adjacency Matrix.
dfsIteration.constructAdjacencyList("a", "c"); dfsIteration.constructAdjacencyList("a", "d");
void constructAdjacencyList(string vtx, string adjcVertex) { int vtxIndex = vertices.IndexOf(vtx); adjacencyList.Add(new List<string>()); adjacencyList[vtxIndex].Add(adjcVertex); }
Although, the above method is explained in Adjacency List Code tutorial. I will give a brief explanation in this tutorial.
When a method call is made,
The variable vtx is assigned with value "a" and adjcVertex is assigned with "b".
Now, the first line,
int vtxIndex = vertices.IndexOf(vtx);
Calculates the index/position of Vertex a. And as we can see the index a is 0.
Now, in the next line,
adjacencyList.Add(new List<string>());
We are initialising the first row of the 2D Linked List, adjacencyList.
But with what?
We are initialising it with a Linked List new List<string>(),
adjacencyList.Add(new List<string>());
So that the first row can hold the Adjacency List for vertex a.
a --- c ---> d
Similarly, the second row should hold the Adjacency List for vertex b and so on.
And in this iteration, our target is to find out the first row(To create an Adjacency List for vertex a) and insert vertex b to it.
And the below code does that.
adjacencyList[vtxIndex].Add(adjcVertex);
We get the index of vertex a
vtxIndex = vertices.IndexOf(vtx);
As we know vtx is a.
Then add adjcVertex(That contains vertex c) to the 0th index of adjacencyList.
adjacencyList[0].AddLast("c");
And following it we form the Adjacency List.
Now, we come across the most important method void depthFirstSearch(string source) that performs the Depth First Search (DFS).
void depthFirstSearch(string source){ int sourceIndex = vertices.IndexOf(source); visited[sourceIndex] = true; Stack<string> stack = new Stack<string>(); stack.Push(source); System.Console.Write(source+" --> "); while (stack.Count != 0) { source = stack.Peek(); sourceIndex = vertices.IndexOf(source); string str = ""; foreach (string iter in adjacencyList[sourceIndex] ) { str = iter; int i = vertices.IndexOf(str); if (visited[i] == false) { stack.Push(str); visited[i] = true; System.Console.Write(str + " --> "); break; } } if (!stack.Peek().Equals(str)){ stack.Pop(); } } }
We have called the void depthFirstSearch(string source) from the main method passing a as the parameter.
dfsIteration.depthFirstSearch("a");
So, the first thing we will do is, take the index of a,
int sourceIndex = vertices.IndexOf(source);
Now, if we see the List of vertices,
We can see that a lies in index 0.
Next, we mark a as visited,
visited[sourceIndex] = true;
in the visited[] array,
visited[0] = true;
Then, we create the stack,
Stack<string> stack = new Stack<string>();
And the immediate next thing we do is, push a to the stack.
stack.Push(source);
Then we print the vertex a.
System.Console.Write(source+" --> ");
Next, we enter the while() loop that continues until the stack is not empty.
while (stack.Count != 0) { source = stack.Peek(); sourceIndex = vertices.IndexOf(source); string str = ""; foreach (string iter in adjacencyList[sourceIndex] ) { str = iter; int i = vertices.IndexOf(str); if (visited[i] == false) { stack.Push(str); visited[i] = true; System.Console.Write(str + " --> "); break; } } if (!stack.Peek().Equals(str)){ stack.Pop(); } }
In the while() loop, we take the top element(i.e. a) in the source variable.
source = stack.Peek();
The we take the index of the top element(0 is the index of a).
sourceIndex = vertices.IndexOf(source);
Then comes the for(...) loop, where we find the find the adjacent vertices of the top element(i.e. a).
foreach (string iter in adjacencyList[sourceIndex] ) { str = iter; int i = vertices.IndexOf(str); if (visited[i] == false) { stack.Push(str); visited[i] = true; System.Console.Write(str + " --> "); break; } }
iter variable of , stores the Adjacency List of vertex a in it.So, iter has the elements c and d in it.
Now, str contains the first adjacent vertex c.
str = iter;
Next, we find the index of vertex c,
int i = vertices.IndexOf(str);
Now, if we see the List of vertices,
We can see that c lies in index 2.
So, we check if c is visited or not.
if (visited[i] == false) { stack.Push(str); visited[i] = true; System.Console.Write(str + " --> "); break; }
Now, if we check the visited array,
We found that visited[2] = false and we get into the if statement.
So, we push c to the Queue.
And marked visited[2] = true,
visited[i] = true;
In the visited[] array,
then we break out of the for loop
break;
After getting out of the for loop, we check if the value inside the str variable and the top element are equal or not.
if (!stack.Peek().Equals(str)){ stack.pop(); }
In this case str has c inside it and the top element of the stack is also c.
So, we don't pop c out of the stack and continue with the while loop.
Similarly, we repeat the same process until all the vertices are visited.
Now, let's visit the while() loop again.
The top element is f now,
source = stack.Peek();
So, the value of source variable is f and
sourceIndex = vertices.IndexOf(source);
the value of sourceIndex variable would be 5.
The first statement of the for loop (i.e. The initialisation section of the loop),
iter
is where we get the Adjacent Vertices of vertex c in the iter.
Thinking How?
Well ! The adjacencyList is a 2D Linked List that stores the adjacent vertices. And the trick is played in,
adjacencyList[sourceIndex]
As we have seen, the sourceIndex is 0 (Because the index of vertex a is 0).
And the iter variable of iter gets the adjacency list of vertex a in it.
iter variable, stores the Adjacency List of vertex a in it.So, iter has the elements c and d in it.
Now, str contains the first adjacent vertex c.
string str = iter; int i = vertices.IndexOf(str);
And both e and d are visited. So, the lines under the if statement are never visited.
if (visited[i] == false) { stack.Push(str); visited[i] = true; System.Console.Write(str + " --> "); break; }
So, the for loop completes. And the value of the variable str would be e.
So, after getting out of the for loop, we check if the value inside the str variable and the top element are equal or not.
if (!stack.Peek().Equals(str)){ stack.Pop(); }
In this case the top element is f and the value in str is e.
And the if(!stack.Peek().Equals(str)) condition matches and f is popped out of the queue.
stack.pop();
Continuing in the same way, all the elements are popped out of the Queue and the execution ends.