Depth First Search Code Example
Let’s suppose we have a graph that has 8 nodes, A through H. The edges between the nodes are described below.
- A has an edge to node B.
- B has an edge to node G.
- B has edges to nodes C and D.
- C has an edge to node D.
- D has an edge to node E.
- E has edges to nodes F and G.
- G has an edge to node H.
The edges of our graph are directed that is, an edge from B to C means we can go from B to C but not the other way around e.g. C to B.
If you we the algorithm in the code panel on the right, it will print:
A B G H C D E F
Here, the the DFS algorithm starts at node A and visits its neighbors B, G, H, C, D, E, F in that order
- Our DFS algorithm starts at node A and visits its only neighbor: node B.
- Then the algorithm visits node G, which is a neighbor of B, and then node H, which is a neighbor of G.
- After visiting all the nodes reachable from node A, the algorithm backtracks to node B and visits its other neighbor: node C.
- Node C has a neighbor, node D, which the algorithm then visits.
- Finally, the algorithm backtracks to node E and visits its neighbors, nodes F and G, in that order (G is already visited so it’s not printed.)
The visited
property of Node is used to keep a track of which nodes have been visited by the DFS algorithm already. It is important to mark a node as visited when it is first encountered, as this helps the algorithm avoid visiting the same node multiple times and getting stuck in an infinite loop. For example if we have the following graph:
A -- B
| |
C -- D
If we start the DFS algorithm at node A and do not mark nodes as visited, the algorithm will visit node B and then follow the the graph through nodes D and C back to A. It will then repeat indefinitely and will get stuck in an infinite loop. This is why we must mark nodes as visited.
import java.util.LinkedList; // Class to represent a node in the graph class Node { String name; LinkedList
neighbors; boolean visited; public Node(String name) { this.name = name; this.neighbors = new LinkedList<>(); this.visited = false; } } public class DepthFirstSearch { public static void main(String[] args) { // Create eight nodes Node A = new Node("A"); Node B = new Node("B"); Node C = new Node("C"); Node D = new Node("D"); Node E = new Node("E"); Node F = new Node("F"); Node G = new Node("G"); Node H = new Node("H"); // Add edges: A -> B A.neighbors.add(B); // B -> G, B -> C, B -> D B.neighbors.add(G); B.neighbors.add(C); B.neighbors.add(D); // C -> D C.neighbors.add(D); // D -> E D.neighbors.add(E); // E -> F, E -> G E.neighbors.add(F); E.neighbors.add(G); // G -> H G.neighbors.add(H); // Put all nodes in a linked list Node[] nodes = {A, B, C, D, E, F, G, H}; // Perform DFS starting from node A dfs(A); } public static void dfs(Node node) { // Mark the current node as visited node.visited = true; System.out.print(node.name + " "); // Follow all edges from current Node to all of its neighbors for (Node neighbor : node.neighbors) { if (!neighbor.visited) { dfs(neighbor); } } } } visited = set() # set to store visited vertices or nodes # The algorithm starts at the root node (specified by the node parameter) and adds # it to the visited set. It then follows the edges of the graph, visiting each neighbor # of the current node and calling the dfs function recursively on each neighbor. It # continues this process until it has visited all the nodes in the graph. def dfs(graph, node): if node not in visited: print(node) visited.add(node) for neighbor in graph[node]: dfs(graph, neighbor) # This dictionary to represent the graph, where the keys are # the nodes and the values are sets of nodes that are connected # to the key node by an edge. graph = {'A': ['B'], 'B': ['G', 'C', 'D'], 'C': ['D'], 'D': ['E'], 'E': ['F', 'G'], 'F': set(), 'G': ['H'], 'H': set()} # Call the graph starting at Node A dfs(graph, 'A') # Output # A # B # G # H # C # D # E # F
package main import "fmt" // A map to represent the graph, where the keys are the nodes // and the values are slices of nodes that are connected to the key node by an edge var graph = map[string][]string{ "A": {"B"}, "B": {"G", "C", "D"}, "C": {"D"}, "D": {"E"}, "E": {"F", "G"}, "F": {}, "G": {"H"}, "H": {}, } // DFS performs a depth-first search on the graph, starting at the specified node func DFS(graph map[string][]string, node string) { // Print the current node fmt.Print(node + " ") // Mark the current node as visited visited[node] = true // Visit each neighbor of the current node for _, neighbor := range graph[node] { if !visited[neighbor] { DFS(graph, neighbor) } } } var visited = make(map[string]bool) // set to store visited nodes func main() { // Call DFS starting at node A DFS(graph, "A") } // Output // A B G H C D E F
const graph = { A: ['B'], B: ['G', 'C', 'D'], C: ['D'], D: ['E'], E: ['F', 'G'], F: [], G: ['H'], H: [], }; const visited = new Set(); // set to store visited nodes // DFS performs a depth-first search on the graph, starting at the specified node function DFS(graph, node) { // Print the current node console.log(node); // Mark the current node as visited visited.add(node); // Visit each neighbor of the current node for (const neighbor of graph[node]) { if (!visited.has(neighbor)) { DFS(graph, neighbor); } } } // Call DFS starting at node A DFS(graph, 'A'); // Output // A // B // G // H // C // D // E // F
# A hash to represent the graph, where the keys are the nodes # and the values are arrays of nodes that are connected to the key node by an edge GRAPH = { 'A' => ['B'], 'B' => ['G', 'C', 'D'], 'C' => ['D'], 'D' => ['E'], 'E' => ['F', 'G'], 'F' => [], 'G' => ['H'], 'H' => [], } # DFS performs a depth-first search on the graph, starting at the specified node def dfs(graph, node) # Print the current node puts node # Mark the current node as visited visited.add(node) # Visit each neighbor of the current node graph[node].each do |neighbor| dfs(graph, neighbor) unless visited.include?(neighbor) end end visited = Set.new # set to store visited nodes # Call DFS starting at node A dfs(GRAPH, 'A')