Previous post (bfs), I covered BFS traversal. This post, I will be focusing on Depth-First traversal.
The difference between BFS and DFS traversal lies in the order in which vertices are explored. And this mainly comes due to data structure used to do traversal. BFS uses queue whereas DFS uses stack data structure to perform traversal. Below diagram illustrates the order of traversal.
DFS Progress |
DFS Implementation
DFS implementation uses Graph.java from the post. Below class has two implementations of DFS traversals (recursive and iterative). Method, traverse(..) is stack based implementation whereas traverseRecur(..) is recursive implementation.package graph.algo;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
* Depth-First Traversal of a graph represented as adjacency list
*
* @author Siddheshwar
*
*/
public class DFS<V> {
private Graph<V> graph; // graph on which DFS will be performed
private Deque<V> stack; // Deque used to implement stack
private Set<V> visited; // stores set of visited nodes
public DFS(Graph<V> graph) {
this.graph = graph;
stack = new ArrayDeque<>();
visited = new LinkedHashSet<>(); // to maintain the insertion order
}
/**
* Iterative/stack based DFS implementation
*
* @param source
*/
public void traverse(V source) {
Objects.requireNonNull(source, "source is manadatory!");
if (this.graph == null || this.graph.isEmpty()) {
throw new IllegalStateException(
"Valid graph object is required !!!");
}
stack.push(source);
this.markAsVisited(source);
boolean pop = false;
V stackTopVertex;
System.out.print(" " + source);
while (!stack.isEmpty()) {
if (pop == true)
stackTopVertex = stack.pop();
else
stackTopVertex = stack.peek();
List<V> neighbors = graph.getAdjacentVertices(stackTopVertex);
if (!neighbors.isEmpty()
&& hasUnvisitedNeighbor(neighbors, visited)) {
for (V a : neighbors) {
if (!this.isVertexVisited(a)) {
System.out.print(" " + a);
visited.add(a);
stack.push(a);
// break from loop if an unvisited neighbor is found
break;
}
}
} else {
// if all neighbors are visited
pop = true;
}
}
}
/**
* Recursive implementation of DFS
*
* @param source
*/
public void traverseRecur(V source) {
Objects.requireNonNull(source, "source is manadatory!");
this.markAsVisited(source);
System.out.print(" " + source);
// get neighbors in sorted manner
List<V> neighbors = this.graph.getAdjacentVertices(source);
for (V n : neighbors) {
if (!this.isVertexVisited(n)) {
traverseRecur(n);
}
}
}
/**
* checks if any of the neighbor is unvisited
*
* @param neighbors
* @param visited
* @return
*/
private boolean hasUnvisitedNeighbor(List<V> neighbors, Set<V> visited) {
for (V i : neighbors) {
if (!visited.contains(i))
return true;
}
return false;
}
/**
* Returns true if vertex is already visited
*
* @param i
* @return
*/
private boolean isVertexVisited(V i) {
return this.visited.contains(i);
}
/**
* Mark a vertex visited
*
* @param i
*/
private void markAsVisited(V i) {
this.visited.add(i);
}
// test method
public static void main(String[] args) {
Graph<Integer> graph = new Graph<>();
graph.addEdge(1, 2);
graph.addEdge(1, 5);
graph.addEdge(1, 6);
graph.addEdge(2, 3);
graph.addEdge(2, 5);
graph.addEdge(3, 4);
graph.addEdge(5, 4);
// for undirected graph
graph.addEdge(2, 1);
graph.addEdge(5, 1);
graph.addEdge(6, 1);
graph.addEdge(3, 2);
graph.addEdge(5, 2);
graph.addEdge(4, 3);
graph.addEdge(4, 5);
System.out.print("DFS -->");
DFS<Integer> dfs = new DFS<>(graph);
/**
* stack based DFS traversal
*/
dfs.traverse(1);
/**
* Recursive DFS traversal
*/
// dfs.traverseRecur(1);
// validation
/**
* after traversal; stack should be empty. And visited should have
* vertices in DFS order
*/
System.out.println("\nIs Stack is empty :"
+ (dfs.stack.isEmpty() ? "yes" : "no"));
System.out.println("visited :" + dfs.visited);
}
}
Output:
DFS --> 1 2 3 4 5 6
Is Stack is empty :yes
visited :[1, 2, 3, 4, 5, 6]
Time Complexity
Assuming above implementation of Graph i.e. Adjacency List, |V| is number of vertices and |E| is number of edges.
So complexity is O(|V|+|E|)
--
happy learning !!!
happy learning !!!
No comments:
Post a Comment