Learnerslesson
   JAVA   
  SPRING  
  SPRINGBOOT  
 HIBERNATE 
  HADOOP  
   HIVE   
   ALGORITHMS   
   PYTHON   
   GO   
   KOTLIN   
   C#   
   RUBY   
   C++   




C - PLUS-PLUS-DEPTH FIRST SEARCH CODE - RECURSIVE




We will be seeing the Recursive way for implementing Depth First Search (DFS).


In the Recursive code we don't have to create the stack and maintain it as C++ will do the job for us. And the stack will be hidden from us.


DFS - Depth First Search code for Undirected Graph - Recursive approach


Example :



#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

const int V = 5;
vector<string> vertices;
vector<vector<string>> adjacencyList;
bool visited[V];

class DFSRecursion {

	public :
	
	int indexOf(string val, vector<string> v) {
   
  		auto match = find(v.begin(), v.end(), val); 
 
  		if(match != v.end())  
    		return match - v.begin(); 
  		else  
    		return -1; 
	}

    void insertVertex(string vertex) {

        vertices.push_back(vertex);
    }

    void constructAdjacencyList(string vtx, string adjcVertex) {

        int vtxIndex = indexOf(vtx, vertices);

        adjacencyList.push_back(vector<string>());
        adjacencyList[vtxIndex].push_back(adjcVertex);
    }

    void depthFirstSearch(string source){

        int sourceIndex = indexOf(source, vertices);

        visited[sourceIndex] = true;

        cout << source+"   ";

        for (string iter : adjacencyList[sourceIndex] ) {

            string str = iter;

            int i = indexOf(str, vertices);

            if (visited[i] == false) {

                visited[i] = true;
                depthFirstSearch(str);
            }
        }
    }
};

int main() {

    DFSRecursion dfsRecursion;

    adjacencyList = vector<vector<string>>();

    vertices = vector<string>();

    // Insert Vertices

    dfsRecursion.insertVertex("a");
    dfsRecursion.insertVertex("b");
    dfsRecursion.insertVertex("c");
    dfsRecursion.insertVertex("d");
    dfsRecursion.insertVertex("e");
    dfsRecursion.insertVertex("f");

    dfsRecursion.constructAdjacencyList("a", "c");
    dfsRecursion.constructAdjacencyList("a", "d");

    dfsRecursion.constructAdjacencyList("b", "d");
    dfsRecursion.constructAdjacencyList("b" ,"e");
    dfsRecursion.constructAdjacencyList("b" ,"c");

    dfsRecursion.constructAdjacencyList("c", "a");
    dfsRecursion.constructAdjacencyList("c", "b");
    dfsRecursion.constructAdjacencyList("c", "e");

    dfsRecursion.constructAdjacencyList("d", "a");
    dfsRecursion.constructAdjacencyList("d" ,"b");
    dfsRecursion.constructAdjacencyList("d", "e");
    dfsRecursion.constructAdjacencyList("d", "f");

    dfsRecursion.constructAdjacencyList("e", "b");
    dfsRecursion.constructAdjacencyList("e", "c");
    dfsRecursion.constructAdjacencyList("e", "d");
    dfsRecursion.constructAdjacencyList("e", "f");

    dfsRecursion.constructAdjacencyList("f", "d");
    dfsRecursion.constructAdjacencyList("f", "e");

    dfsRecursion.depthFirstSearch("a");
}


Output :



  a c b d e f

We have implemented Depth First Search (DFS) on the below graph :

java_Collections

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?


Code Explanation for DFS - Depth First Search - Recursive :


Below code explains the methods :

  1. void constructAdjacencyList(string vtx, string adjcVertex)

  2. void insertVertex(string vertex)

Almost the same we have discussed in DFS - Depth First Search - Iterative approach. 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.

  1. We need a List to store the vertices.
    ruby

  2. We need a doubly List to store the adjacency List.
    ruby

  3. We need a Queue and an array to store its Levels.

  4. We need a bool array to store the Vertices that are already visited.

Now, let us see the above code.


We have a List to store the Vertices.


vector<string> vertices;

We also have a 2D List to store the Adjacency List.


vector<vector<string>> adjacencyList;

Similarly, we have a stack defined inside the method depthFirstSearch(...).


stack<string> stack;

And, there is a bool array to store the Vertices that are visited.


bool visited[V];

Note : The variables are marked as static, so that they could be accessed from main(...) method.

So, the first thing we will do is, insert the Vertices to the list<string> vertices List.


vertices = vector<string>();

dfsRecursion.insertVertex("a");
dfsRecursion.insertVertex("b");
dfsRecursion.insertVertex("c");
dfsRecursion.insertVertex("d");
dfsRecursion.insertVertex("e");
dfsRecursion.insertVertex("f");

Explanation of void insertVertex(string vertex) method


void insertVertex(string vertex) {

	vertices.push_back(vertex);
}

void insertVertex(string vertex) is quite simple.


There is just one statement in it.


vertices.push_back(vertex);

It accepts string vertex as a parameter and adds it to the List, vertices.

java_Collections

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.


dfsRecursion.constructAdjacencyList("a", "c");
dfsRecursion.constructAdjacencyList("a", "d");

Note : Just remember, creating an Adjacency List above is same as creating an Edge. As the Adjacency List is actually a group of Edges.


Explanation of void constructAdjacencyList(string vtx, string adjcVertex) method


void constructAdjacencyList(string vtx, string adjcVertex) {

	int vtxIndex = indexOf(vtx, vertices);

	adjacencyList.push_back(vector<string>());
	adjacencyList[vtxIndex].push_back(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,

java_Collections

The variable vtx is assigned with value "a" and adjcVertex is assigned with "b".


Now, the first line,


int vtxIndex = indexOf(vtx, vertices);;

Calculates the index/position of Vertex a. And as we can see the index a is 0.


Now, in the next line,


adjacencyList.push_back(vector<string>());

We are initialising the first row of the 2D List, adjacencyList.


But with what?


We are initialising it with a List new list<string>(),


adjacencyList.push_back(vector<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].push_back(adjcVertex);

We get the index of vertex a


vtxIndex = indexOf(vtx, vertices);;

As we know vtx is a.


Then add adjcVertex(That contains vertex c) to the 0th index of adjacencyList.


adjacencyList[0].push_back(adjcVertex);

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).


Explanation of void depthFirstSearch(string source) method


void depthFirstSearch(string source){

	int sourceIndex = indexOf(source, vertices);

	visited[sourceIndex] = true;

	cout << source+"   ";

	for (string iter : adjacencyList[sourceIndex] ) {

		string str = iter;

		int i = indexOf(str, vertices);

		if (visited[i] == false) {

			visited[i] = true;
			depthFirstSearch(str);
		}
	}
}

We have called the void depthFirstSearch(string source) from the main method passing a as the parameter.


dfsRecursion.depthFirstSearch("a");

So, the first thing we will do is, take the index of a,


int sourceIndex = indexOf(source, vertices);

Now, if we see the List of vertices,

java_Collections

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;
java_Collections


Then we print the vertex a.


cout << source+"   ";

Output :



  a


Then comes the for(...) loop, where we find the adjacent vertices of the top element(i.e. a).


for (string iter : adjacencyList[sourceIndex] ) {

	string str = iter;

	int i = indexOf(str, vertices);

	if (visited[i] == false) {

		visited[i] = true;
		depthFirstSearch(str);
	}
}

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;

Next, we find the index of vertex c,


int i = indexOf(str, vertices);

Now, if we see the List of vertices,

java_Collections

We can see that c lies in index 2.


So, we check if c is visited or not.


if (visited[i] == false) {

	visited[i] = true;
	depthFirstSearch(str);
}

Now, if we check the visited array,

java_Collections

We found that visited[2] = false and we get into the if statement.


And marked visited[2] = true,


visited[i] = true;

In the visited[] array,

java_Collections

And then comes the fun part. Where the depthFirstSearch(...) method calls itself.


depthFirstSearch(str);

So, internally what happens is, C++ maintains an internal stack, that is hidden from you.


Now, since the method started from a, C++ puts a to the stack. Then whenever it meets the statement,


depthFirstSearch(str);

It recognises a recursive call is made and pushes the content of variable str(i.e. c) to the stack.

java_Collections

Similarly, we repeat the same process until all the vertices are visited. And C++ pushes all the values to the stack.

java_Collections
java_Collections

Now, since we have reached a place where all the adjacent vertices of vertex f are visited.


So, it's time for C++ to backtrack. i.e. Start popping out all the elements from its internal queue.


So, it takes out f out of the queue and checks if there are any adjacent vertices of e that are not visited.

java_Collections

Continuing in the same way, all the elements are popped out of the Queue and the execution ends.