In Depth First Search (or DFS) for a graph, we traverse all adjacent vertices one by one. When we traverse an adjacent vertex, we completely finish the traversal of all vertices reachable through that adjacent vertex. This is similar to a tree, where we first completely traverse the left subtree and then move to the right subtree. The key difference is that, unlike trees, graphs may contain cycles (a node may be visited more than once). To avoid processing a node multiple times, we use a boolean visited array.
Example:
Note : There can be multiple DFS traversals of a graph according to the order in which we pick adjacent vertices. Here we pick vertices as per the insertion order.
Output: [0 1 2 3 4] Explanation: The source vertex s is 0. We visit it first, then we visit an adjacent. Start at 0: Mark as visited. Output: 0 Move to 1: Mark as visited. Output: 1 Move to 2: Mark as visited. Output: 2 Move to 3: Mark as visited. Output: 3 (backtrack to 2) Move to 4: Mark as visited. Output: 4 (backtrack to 2, then backtrack to 1, then to 0)
Not that there can be more than one DFS Traversals of a Graph. For example, after 1, we may pick adjacent 2 instead of 0 and get a different DFS. Here we pick in the insertion order.
Input: [[2,3,1], [0], [0,4], [0], [2]]
Output: [0 2 4 3 1] Explanation: DFS Steps:
Start at 0: Mark as visited. Output: 0 Move to 2: Mark as visited. Output: 2 Move to 4: Mark as visited. Output: 4 (backtrack to 2, then backtrack to 0) Move to 3: Mark as visited. Output: 3 (backtrack to 0) Move to 1: Mark as visited. Output: 1 (backtrack to 0)
The algorithm starts from a given source and explores all reachable vertices from the given source. It is similar to Preorder Tree Traversal where we visit the root, then recur for its children. In a graph, there might be loops. So we use an extra visited array to make sure that we do not process a vertex again.
Let us understand the working of Depth First Search with the help of the following Illustration: for the source as 0.
C++
#include<bits/stdc++.h>usingnamespacestd;// Recursive function for DFS traversalvoiddfsRec(vector<vector<int>>&adj,vector<bool>&visited,ints,vector<int>&res){visited[s]=true;res.push_back(s);// Recursively visit all adjacent vertices// that are not visited yetfor(inti:adj[s])if(visited[i]==false)dfsRec(adj,visited,i,res);}// Main DFS function that initializes the visited array// and call DFSRecvector<int>DFS(vector<vector<int>>&adj){vector<bool>visited(adj.size(),false);vector<int>res;dfsRec(adj,visited,0,res);returnres;}// To add an edge in an undirected graphvoidaddEdge(vector<vector<int>>&adj,ints,intt){adj[s].push_back(t);adj[t].push_back(s);}intmain(){intV=5;vector<vector<int>>adj(V);// Add edgesvector<vector<int>>edges={{1,2},{1,0},{2,0},{2,3},{2,4}};for(auto&e:edges)addEdge(adj,e[0],e[1]);// Starting vertex for DFSvector<int>res=DFS(adj);// Perform DFS starting from the source verte 0;for(inti=0;i<V;i++)cout<<res[i]<<" ";}
Java
importjava.util.*;publicclassDFSGraph{// Recursive function for DFS traversalprivatestaticvoiddfsRec(ArrayList<ArrayList<Integer>>adj,boolean[]visited,ints,ArrayList<Integer>res){visited[s]=true;res.add(s);// Recursively visit all adjacent vertices that are// not visited yetfor(inti:adj.get(s)){if(!visited[i]){dfsRec(adj,visited,i,res);}}}// Main DFS function that initializes the visited array// and calls dfsRecpublicstaticArrayList<Integer>DFS(ArrayList<ArrayList<Integer>>adj){boolean[]visited=newboolean[adj.size()];ArrayList<Integer>res=newArrayList<>();dfsRec(adj,visited,0,res);returnres;}// To add an edge in an undirected graphpublicstaticvoidaddEdge(ArrayList<ArrayList<Integer>>adj,ints,intt){adj.get(s).add(t);adj.get(t).add(s);}publicstaticvoidmain(String[]args){intV=5;ArrayList<ArrayList<Integer>>adj=newArrayList<>();// Initialize adjacency listfor(inti=0;i<V;i++){adj.add(newArrayList<>());}// Add edgesint[][]edges={{1,2},{1,0},{2,0},{2,3},{2,4}};for(int[]e:edges){addEdge(adj,e[0],e[1]);}// Perform DFS starting from vertex 0ArrayList<Integer>res=DFS(adj);for(inti=0;i<res.size();i++){System.out.print(res.get(i)+" ");}}}
Python
defdfsRec(adj,visited,s,res):visited[s]=Trueres.append(s)# Recursively visit all adjacent vertices that are not visited yetforiinrange(len(adj)):ifadj[s][i]==1andnotvisited[i]:dfsRec(adj,visited,i,res)defDFS(adj):visited=[False]*len(adj)res=[]dfsRec(adj,visited,0,res)# Start DFS from vertex 0returnresdefadd_edge(adj,s,t):adj[s][t]=1adj[t][s]=1# Since it's an undirected graph# Driver codeV=5adj=[[0]*Vfor_inrange(V)]# Adjacency matrix# Define the edges of the graphedges=[(1,2),(1,0),(2,0),(2,3),(2,4)]# Populate the adjacency matrix with edgesfors,tinedges:add_edge(adj,s,t)res=DFS(adj)# Perform DFSprint(" ".join(map(str,res)))
C#
usingSystem;usingSystem.Collections.Generic;classDFSGraph{// Recursive function for DFS traversalstaticvoidDfsRec(List<int>[]adj,bool[]visited,ints,List<int>res){visited[s]=true;res.Add(s);// Recursively visit all adjacent vertices that are// not visited yetforeach(intiinadj[s]){if(!visited[i]){DfsRec(adj,visited,i,res);}}}// Main DFS function that initializes the visited array// and calls DfsRecstaticList<int>DFS(List<int>[]adj){bool[]visited=newbool[adj.Length];List<int>res=newList<int>();DfsRec(adj,visited,0,res);returnres;}// To add an edge in an undirected graphstaticvoidAddEdge(List<int>[]adj,ints,intt){adj[s].Add(t);adj[t].Add(s);}staticvoidMain(){intV=5;List<int>[]adj=newList<int>[V];// Initialize adjacency listfor(inti=0;i<V;i++){adj[i]=newList<int>();}// Add edgesint[,]edges={{1,2},{1,0},{2,0},{2,3},{2,4}};for(inti=0;i<edges.GetLength(0);i++){AddEdge(adj,edges[i,0],edges[i,1]);}// Perform DFS starting from vertex 0List<int>res=DFS(adj);foreach(intiinres){Console.Write(i+" ");}}}
JavaScript
functiondfsRec(adj,visited,s,res){visited[s]=true;res.push(s);// Recursively visit all adjacent vertices that are not// visited yetfor(leti=0;i<adj.length;i++){if(adj[s][i]===1&&!visited[i]){dfsRec(adj,visited,i,res);}}}functionDFS(adj){letvisited=newArray(adj.length).fill(false);letres=[];dfsRec(adj,visited,0,res);// Start DFS from vertex 0returnres;}functionaddEdge(adj,s,t){adj[s][t]=1;adj[t][s]=1;// Since it's an undirected graph}// Driver codeletV=5;letadj=Array.from({length:V},()=>newArray(V).fill(0));// Adjacency matrix// Define the edges of the graphletedges=[[1,2],[1,0],[2,0],[2,3],[2,4]];// Populate the adjacency matrix with edgesedges.forEach(([s,t])=>addEdge(adj,s,t));letres=DFS(adj);// Perform DFSconsole.log(res.join(" "));
Output
0 1 2 3 4
Time complexity: O(V + E), where V is the number of vertices and E is the number of edges in the graph. Auxiliary Space: O(V + E), since an extra visited array of size V is required, And stack size for recursive calls to dfsRec function.
DFS for Complete Traversal of Disconnected Undirected Graph
The above implementation takes a source as an input and prints only those vertices that are reachable from the source and would not print all vertices in case of disconnected graph. Let us now talk about the algorithm that prints all vertices without any source and the graph maybe disconnected.
The idea is simple, instead of calling DFS for a single vertex, we call the above implemented DFS for all all non-visited vertices one by one.
C++
#include<bits/stdc++.h>usingnamespacestd;voidaddEdge(vector<vector<int>>&adj,ints,intt){adj[s].push_back(t);adj[t].push_back(s);}// Recursive function for DFS traversalvoiddfsRec(vector<vector<int>>&adj,vector<bool>&visited,ints,vector<int>&res){// Mark the current vertex as visitedvisited[s]=true;res.push_back(s);// Recursively visit all adjacent vertices that are not visited yetfor(inti:adj[s])if(visited[i]==false)dfsRec(adj,visited,i,res);}// Main DFS function to perform DFS for the entire graphvector<int>DFS(vector<vector<int>>&adj){vector<bool>visited(adj.size(),false);vector<int>res;// Loop through all vertices to handle disconnected graphfor(inti=0;i<adj.size();i++){if(visited[i]==false){// If vertex i has not been visited,// perform DFS from itdfsRec(adj,visited,i,res);}}returnres;}intmain(){intV=6;// Create an adjacency list for the graphvector<vector<int>>adj(V);// Define the edges of the graphvector<vector<int>>edges={{1,2},{2,0},{0,3},{4,5}};// Populate the adjacency list with edgesfor(auto&e:edges)addEdge(adj,e[0],e[1]);vector<int>res=DFS(adj);for(autoit:res)cout<<it<<" ";return0;}
Java
importjava.util.*;publicclassGfG{// Function to add an edge to the adjacency listpublicstaticvoidaddEdge(ArrayList<ArrayList<Integer>>adj,ints,intt){adj.get(s).add(t);adj.get(t).add(s);}// Recursive function for DFS traversalprivatestaticvoiddfsRec(ArrayList<ArrayList<Integer>>adj,boolean[]visited,ints,ArrayList<Integer>res){visited[s]=true;res.add(s);// Recursively visit all adjacent vertices that are// not visited yetfor(inti:adj.get(s)){if(!visited[i]){dfsRec(adj,visited,i,res);}}}// Main DFS function to perform DFS for the entire graphpublicstaticArrayList<Integer>DFS(ArrayList<ArrayList<Integer>>adj){boolean[]visited=newboolean[adj.size()];ArrayList<Integer>res=newArrayList<>();// Loop through all vertices to handle disconnected// graphsfor(inti=0;i<adj.size();i++){if(!visited[i]){dfsRec(adj,visited,i,res);}}returnres;}publicstaticvoidmain(String[]args){intV=6;// Create an adjacency list for the graphArrayList<ArrayList<Integer>>adj=newArrayList<>();// Initialize adjacency listfor(inti=0;i<V;i++){adj.add(newArrayList<>());}// Define the edges of the graphint[][]edges={{1,2},{2,0},{0,3},{4,5}};// Populate the adjacency list with edgesfor(int[]e:edges){addEdge(adj,e[0],e[1]);}// Perform DFSArrayList<Integer>res=DFS(adj);// Print the DFS traversal resultfor(intnum:res){System.out.print(num+" ");}}}
Python
# Create an adjacency list for the graphfromcollectionsimportdefaultdictdefadd_edge(adj,s,t):adj[s].append(t)adj[t].append(s)# Recursive function for DFS traversaldefdfs_rec(adj,visited,s,res):# Mark the current vertex as visitedvisited[s]=Trueres.append(s)# Recursively visit all adjacent vertices that are not visited yetforiinadj[s]:ifnotvisited[i]:dfs_rec(adj,visited,i,res)# Main DFS function to perform DFS for the entire graphdefdfs(adj):visited=[False]*len(adj)res=[]# Loop through all vertices to handle disconnected graphforiinrange(len(adj)):ifnotvisited[i]:# If vertex i has not been visited,# perform DFS from itdfs_rec(adj,visited,i,res)returnresV=6# Create an adjacency list for the graphadj=defaultdict(list)# Define the edges of the graphedges=[[1,2],[2,0],[0,3],[4,5]]# Populate the adjacency list with edgesforeinedges:add_edge(adj,e[0],e[1])res=dfs(adj)print(' '.join(map(str,res)))
C#
usingSystem;usingSystem.Collections.Generic;classGfG{// Function to add an edge to the adjacency liststaticvoidAddEdge(List<int>[]adj,ints,intt){adj[s].Add(t);adj[t].Add(s);}// Recursive function for DFS traversalstaticvoidDfsRec(List<int>[]adj,bool[]visited,ints,List<int>res){visited[s]=true;res.Add(s);// Recursively visit all adjacent vertices that are// not visited yetforeach(intiinadj[s]){if(!visited[i]){DfsRec(adj,visited,i,res);}}}// Main DFS function to perform DFS for the entire graphstaticList<int>DFS(List<int>[]adj){bool[]visited=newbool[adj.Length];List<int>res=newList<int>();// Loop through all vertices to handle disconnected// graphsfor(inti=0;i<adj.Length;i++){if(!visited[i]){DfsRec(adj,visited,i,res);}}returnres;}staticvoidMain(){intV=6;// Create an adjacency list for the graphList<int>[]adj=newList<int>[V];// Initialize adjacency listfor(inti=0;i<V;i++){adj[i]=newList<int>();}// Define the edges of the graphint[,]edges={{1,2},{2,0},{0,3},{4,5}};// Populate the adjacency list with edgesfor(inti=0;i<edges.GetLength(0);i++){AddEdge(adj,edges[i,0],edges[i,1]);}// Perform DFSList<int>res=DFS(adj);// Print the DFS traversal resultforeach(intnuminres){Console.Write(num+" ");}}}
JavaScript
functionaddEdge(adj,s,t){adj[s].push(t);adj[t].push(s);}// Recursive function for DFS traversalfunctiondfsRec(adj,visited,s,res){visited[s]=true;res.push(s);// Recursively visit all adjacent vertices that are not visited yetfor(letiofadj[s]){if(!visited[i]){dfsRec(adj,visited,i,res);}}}// Main DFS function to perform DFS for the entire graphfunctionDFS(adj){letvisited=newArray(adj.length).fill(false);letres=[];// Loop through all vertices to handle disconnected graphsfor(leti=0;i<adj.length;i++){if(!visited[i]){dfsRec(adj,visited,i,res);}}returnres;}// Main ExecutionletV=6;// Create an adjacency list for the graphletadj=Array.from({length:V},()=>[]);letedges=[[1,2],[2,0],[0,3],[4,5]];// Populate the adjacency list with edgesfor(leteofedges){addEdge(adj,e[0],e[1]);}// Perform DFSletres=DFS(adj);// Print the DFS traversal resultconsole.log(res.join(" "));
Output
0 2 1 3 4 5
Time complexity: O(V + E). Note that the time complexity is same here because we visit every vertex at most once and every edge is traversed at most once (in directed) and twice in undirected. Auxiliary Space: O(V + E), since an extra visited array of size V is required, And stack size for recursive calls to dfsRec function.
We use cookies to ensure you have the best browsing experience on our website. By using our site, you
acknowledge that you have read and understood our
Cookie Policy &
Privacy Policy
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.