×

Depth First Search Program to Traverse a Graph in C++

Depth First Search (DFS) is a technique that is used for transversing the graph. The process of Depth First Search (DFS) starts from the root node and then next comes to the adjacent nodes. This means Depth First Search (DFS) expands the node depth-wise. The traversing process stops when it encounters a node with no child node. Once the leaf nodes come then, the whole process repeats again. Unlike the BFS, the Depth First Search (DFS) also expands its process breadth-wise. We use the stack data structure to expand the whole process in Depth First Search (DFS). The unexplored nodes are also called discovery edges, while the already visited node is called block nodes.

Now, we will see the algorithm and pseudo code for the Depth First Search (DFS).

  • Step 1: We have to insert the root node in a graph of the stack.
  • Step 2: We have to pop the item from the stack and start visiting the nodes.
  • Step 3: Then, we have to find all the adjacent nodes and mark them as visited.
  • Step 4: Repeat steps two and step 3 until the whole stack becomes empty.

The pseudo-code for the Depth First Search (DFS) is below.

Procedure DFS(G,x)
 G>graph to be traversed.
  x> starting nodes.
Begin
x.visited= true
for each v belongs to G.Adj[x]
if v.visited==false
dfs ( G, v)
end procedure.
For each x belongs to G
x. visited = false
 for each x belongs to G
DFS(G,x)
}   

Traversal Process of Depth First Search (DFS) with Illusion

Let us start the discussion of the traversal of Depth First Search (DFS) in a stepwise manner. We will be going to use the same graph for the whole traversal process.

Let us take 0 as the starting node. Then, we mention 0 as the visited, then start the traversing process with 0. Then, we have to push all the neighboring nodes in manner wise in the stack.

Then, we have to perform the above process in node one, i.e., top of the stack. Then, we have to mark node one as visited then add node 1 to the marked list.

Depth First Search Program to Traverse a Graph in C++

 Now, we have to look for the adjacent node of 1. As 0 is already visited, then we have to perform the operation in node 2.

Depth First Search Program to Traverse a Graph in C++

Next, we have to mark node two as visited and add node two to the visited list.

Depth First Search Program to Traverse a Graph in C++

Next, we have to mark node four as marked and add node 4 to the visited list.

Depth First Search Program to Traverse a Graph in C++

Next, we have to mark node three as marked and add node 3 to the visited list.

Depth First Search Program to Traverse a Graph in C++

Now, the whole stack becomes empty. So, we have to stop our traversal process.

Depth First Search Program to Traverse a Graph in C++

Implementation of Depth First Search (DFS)

#include <iostream> 
#include <list> 
using namespace std; 
class DFSGraph 
{ 
int V;   
list<int> *adjList;   
void DFS_util(int v, bool visited[]);  
public: 
   
DFSGraph(int V)
    {
 this->V = V; 
 adjList = new list<int>[V]; 
    }
   
void addEdge(int v, int w){
adjList[v].push_back(w);
    }
     
void DFS();   
}; 
void DFSGraph::DFS_util(int v, bool visited[]) 
{ 
    
visited[v] = true; 
cout << v << " "; 
   
    
list<int>::iterator i; 
for(i = adjList[v].begin(); i != adjList[v].end(); ++i) 
if(!visited[*i]) 
DFS_util(*i, visited); 
} 
 
void DFSGraph::DFS() 
{ 
  
bool *visited = new bool[V]; 
for (int i = 0; i < V; i++) 
visited[i] = false; 
   
   
for (int i = 0; i < V; i++) 
if (visited[i] == false) 
DFS_util(i, visited); 
} 
   
int main() 
{ 
  
DFSGraph gdfs(5); 
gdfs.addEdge(0, 1); 
gdfs.addEdge(0, 2); 
gdfs.addEdge(0, 3);
gdfs.addEdge(1, 2); 
gdfs.addEdge(2, 4);
gdfs.addEdge(3, 3); 
gdfs.addEdge(4, 4);


cout << "Depth-first traversal for the given graph:"<<endl; 
gdfs.DFS(); 
   
return 0; 
}

Output:

Depth-first traversal for the given graph:
0 1 2 4 3

Runtime Analysis

The time complexity for Depth First Search (DFS) is O (|V|+|E|) which is similar to the breath first search. 

Here V= number of vertices.

E= number of edges given in the graph.

Handling a Disconnected Graph

The above code traverses only the vertices reachable from a given source vertex. All the vertices may not be reachable from a given vertex, as in a disconnected graph. To do a complete DFS traversal of such graphs, run DFS from all unvisited nodes after a DFS. The recursive function remains the same.

Follow the steps given below to solve the problem:

  • Create a recursive function that takes the index of the node and a visited array.
  • Mark the current node as visited and print the node.
  • Traverse all the adjacent and unmarked nodes and call the recursive function with the index of the adjacent node.
  • Run a loop from 0 to the number of vertices and check if the node is unvisited in the previous DFS, then call the recursive function with the current node.

Iterative Depth First Search (DFS)

The above Depth First Search (DFS) implementation is recursive in nature. It is used to call the function from the stack. But we have another method to implement the iterative depth-first search. We use the explicit stack method to hold the visited nodes in this method. Below we show the implementation of the iterative depth-first search method in a program.

#include<bits/stdc++.h> 
using namespace std; 
class Graph 
{ 
int V;   
list<int> *adjList;   
public: 
Graph(int V) 
    {
this->V = V; 
adjList = new list<int>[V]; 
    }
void addEdge(int v, int w)  
    {
adjList[v].push_back(w):
    }
void DFS(); 
   
    
void DFSUtil(int s, vector<bool> &visited); 
}; 
   


void Graph::DFSUtil(int s, vector<bool> &visited) 
{ 
   
stack<int> dfsstack; 
dfsstack.push(s); 
   
while (!dfsstack.empty()) 
    { 
         
        s = dfsstack.top(); 
       dfsstack.pop(); 
   
        
 if (!visited[s]) 
        { 
cout << s << " "; 
visited[s] = true; 
        } 
  
for (auto i = adjList[s].begin(); i != adjList[s].end(); ++i) 
if (!visited[*i]) 
dfsstack.push(*i); 
    } 
} 
void Graph::DFS() 
{ 
   
vector<bool> visited(V, false); 
   
for (int i = 0; i < V; i++) 
if (!visited[i]) 
DFSUtil(i, visited); 
} 
   
//main program
int main() 
{ 
    Graph gidfs(5); 
gidfs.addEdge(0, 1); 
gidfs.addEdge(0, 2); 
gidfs.addEdge(0, 3);
gidfs.addEdge(1, 2); 
gidfs.addEdge(2, 4);
gidfs.addEdge(3, 3); 
gidfs.addEdge(4, 4);
  
cout << "Output of Iterative Depth-first traversal:\n"; 
gidfs.DFS(); 
   
return 0; 
}

Output:

Output of Iterative Depth-first traversal:
0 3 2 4 1

Here, we use the same graph for the implementation of the iterative depth-first search. There is a difference in the output. It is because of the iterative implementation of a stack. As the stack flow LIFO (Last in First Out), there is a difference in the sequence of Depth First search (DFS).

Applications of DFS

  • Detecting Cycles In The Graph: If we find a back edge while performing DFS in a graph, we can conclude that the graph has a cycle. Hence DFS is used to detect the cycles in a graph.
  • Pathfinding: Given two vertices, x and y, we can find the path between x and y using DFS. We start with vertex x and then push all the vertices on the way to the stack till we encounter y. The contents of the stack give the path between x and y.
  • Minimum Spanning Tree and Shortest Path: DFS traversal of the un-weighted graph gives us a minimum spanning tree and shortest path between nodes.
  • Topological Sorting: We use topological sorting to schedule the jobs from the given dependencies among jobs. In computer science, we use it primarily to resolve symbol dependencies in linkers, data serialization, instruction scheduling, etc. DFS is widely used in Topological sorting.

Conclusion

In the last couple of tutorials, we have explored more about the two traversal techniques for graphs, i.e., BFS and DFS. We have seen the differences as well as the applications of both methods. BFS and DFS achieve the same outcome of visiting all nodes of a graph, but they differ in the order of the output and how it is done.

We have also seen the implementation of both techniques. While BFS uses a queue, DFS uses stacks to implement the method. With this, we conclude the tutorial on traversal techniques for graphs. We can also use BFS and DFS on trees.


Related Topics

Initialize Array of objects with parameterized constructors in C++

Initialize Array of objects with parameterized constructors in C++ When a class is defined, only the specification for the object is specified; no memory or capacity is allocated. You need to...

3 minutes read.

Auto keyword in C++

The primary function of auto keyword is to assign and detect the value of the data type automatically in C++. The compiler knows the data type of the variable by...

2 minutes read.

Timsort Implementation Using C++

Timsort Implementation Using C++ The Timsort is a stable sorting algorithm that uses the idea of merge sort and insertion sort. It can also be called a hybrid algorithm of insertion...

3 minutes read.

C++ STL Components

C++ STL Components In today’s article, we are going to learn about all the points things that is related to STL in C++ so stay connected because you are going to...

6 minutes read.

C++ | C Plus Plus Data type

Data type in every language is very important. Data type means the different kinds of data that are supported by a particular programming language. A computer language’s data types specify the...

15 minutes read.

Array of sets in C++

Instead of defining distinct variables for each item, arrays are used to hold numerous values in a single variable. A collection of data objects stored in a continuous way is...

6 minutes read.

Random Number Generator in C++

In programming, we need to frequently create the randomly. For example, a dice game, handing out cards to players, apps for rearranging tunes, etc. T There are two tools available in...

4 minutes read.

Sliding Window Technique in C++

Sliding Window Technique or Window Sliding Technique is a computational technique that is mainly used to reduce the use of nested loop and replace it with a single loop. It...

4 minutes read.

C++ Encapsulation

The following two essential components are present in all C++ programmes: Functions are the parts of a programme that perform actions, and they are termed programme statements (code).Program data is the...

4 minutes read.

C++ Infinite loop

The term "infinite loop" refers to a loop that does not terminate the loop according to the condition. In some cases, an infinite loop may be required in programming, or...

4 minutes read.

C++ Bidirectional Iterators

Iterators : Iterators serve as a link between algorithms and STL containers, allowing the data inside the container to be modified. They let you to iterate through the container, access and...

3 minutes read.

Lambda Expression in C++

The lambda expression was introduced in C++ 11. It is used to write the inline function in C++. The code written in lambda expression cannot be reused further. The syntax...

3 minutes read.

How the value is passed in C++

Introduction: The call-by-value method of giving arguments to a function duplicates the real value of an argument into the formal parameter of the function. In this instance, modifications to the parameter...

5 minutes read.

Bits stdc++.h in C++

<bits/stdc++.h> in C++ In essence, it is a header file that contains all the standard libraries. It makes sense to use this file in programming competitions to speed up work, especially...

2 minutes read.

Palindrome Using While Loop in C++

A palindrome is a word, number, phrase, or other sequence of letters that reads the same backward as forward, such as 101 or MOM. Like other programming languages, C++ also allows...

6 minutes read.

How to declare a 2D array dynamically in C++

In this article, we will learn how to declare the dynamic array in C++. We also learn the initialization of a 2D array using a pointer in C++. Here, we...

3 minutes read.

C++ STL (Standard Template Library)

Introduction C++ is a flexible type and general proposed programming language. So we need a standard library that supports C++. C++ STL (Standard Template Library) is a collection of templates that...

6 minutes read.

Const Keyword in C++

The const programming language keyword will be covered in this section. The constant value that cannot change during program execution is defined using the const keywords. It implies that once...

9 minutes read.

How to implement map in C++

Part of the C++ STL is maps (Standard Template Library). Maps are associative containers that hold sorted key-value pairs, where each key is distinct and may only be added or...

4 minutes read.

Pure Virtual Function in C++ With Example Program

What is a Virtual Function? A virtual function is created inside a class with the keyword virtual. A virtual function does not have any value to be returned. Once a virtual...

3 minutes read.