Depth-first search traversal in Javascript

DFS visits the child vertices before visiting the sibling vertices; that is, it traverses the depth of any particular path before exploring its breadth. A stack (often the program's call stack via recursion) is generally used when implementing the algorithm.

Following is how a DFS works ?

  • Visit the adjacent unvisited vertex. Mark it as visited. Display it. Push it in a stack.
  • If no adjacent vertex is found, pop up a vertex from the stack. (It will pop up all the vertices from the stack, which do not have adjacent vertices.)
  • Repeat Rule 1 and Rule 2 until the stack is empty.

DFS Algorithm Visualization

S A D B C Stack Traversal Order: S ? A ? D ? B ? C Blue: Starting node Green: Visited Orange: In stack

Complete DFS Implementation

Here's a complete implementation of DFS with both the Graph class and Stack class:

// Stack implementation for DFS
class Stack {
    constructor() {
        this.items = [];
    }
    
    push(element) {
        this.items.push(element);
    }
    
    pop() {
        if (this.isEmpty()) return null;
        return this.items.pop();
    }
    
    isEmpty() {
        return this.items.length === 0;
    }
}

// Graph implementation with DFS
class Graph {
    constructor() {
        this.nodes = [];
        this.edges = {};
    }
    
    addNode(node) {
        this.nodes.push(node);
        this.edges[node] = [];
    }
    
    addEdge(node1, node2) {
        this.edges[node1].push(node2);
        this.edges[node2].push(node1); // Undirected graph
    }
    
    DFS(startNode) {
        let stack = new Stack();
        let explored = new Set();
        let result = [];
        
        stack.push(startNode);
        explored.add(startNode);
        
        while (!stack.isEmpty()) {
            let currentNode = stack.pop();
            result.push(currentNode);
            console.log("Visiting:", currentNode);
            
            // Add all unvisited neighbors to stack
            this.edges[currentNode]
                .filter(neighbor => !explored.has(neighbor))
                .forEach(neighbor => {
                    explored.add(neighbor);
                    stack.push(neighbor);
                });
        }
        
        return result;
    }
}

// Test the implementation
let graph = new Graph();

// Add nodes
["A", "B", "C", "D", "E", "F"].forEach(node => {
    graph.addNode(node);
});

// Add edges
graph.addEdge("A", "B");
graph.addEdge("A", "C");
graph.addEdge("B", "D");
graph.addEdge("C", "E");
graph.addEdge("D", "F");

console.log("DFS Traversal starting from A:");
let traversalOrder = graph.DFS("A");
console.log("Traversal order:", traversalOrder);
Visiting: A
Visiting: C
Visiting: E
Visiting: B
Visiting: D
Visiting: F
Traversal order: [ 'A', 'C', 'E', 'B', 'D', 'F' ]

Recursive DFS Implementation

DFS can also be implemented using recursion, which implicitly uses the call stack:

class Graph {
    constructor() {
        this.nodes = [];
        this.edges = {};
    }
    
    addNode(node) {
        this.nodes.push(node);
        this.edges[node] = [];
    }
    
    addEdge(node1, node2) {
        this.edges[node1].push(node2);
        this.edges[node2].push(node1);
    }
    
    DFSRecursive(startNode, visited = new Set(), result = []) {
        visited.add(startNode);
        result.push(startNode);
        console.log("Visiting:", startNode);
        
        for (let neighbor of this.edges[startNode]) {
            if (!visited.has(neighbor)) {
                this.DFSRecursive(neighbor, visited, result);
            }
        }
        
        return result;
    }
}

// Test recursive DFS
let graph2 = new Graph();
["X", "Y", "Z", "W"].forEach(node => graph2.addNode(node));

graph2.addEdge("X", "Y");
graph2.addEdge("Y", "Z");
graph2.addEdge("X", "W");

console.log("\nRecursive DFS from X:");
let recursiveResult = graph2.DFSRecursive("X");
console.log("Result:", recursiveResult);
Visiting: X
Visiting: Y
Visiting: Z
Visiting: W
Result: [ 'X', 'Y', 'Z', 'W' ]

Key Characteristics

Aspect DFS BFS
Data Structure Stack (LIFO) Queue (FIFO)
Memory Usage Lower (O(h) where h is height) Higher (O(w) where w is width)
Path Type May not find shortest path Finds shortest path
Use Cases Topological sort, cycle detection Shortest path, level-order

Common Applications

  • Maze solving: Finding a path through a maze
  • Cycle detection: Detecting cycles in directed/undirected graphs
  • Topological sorting: Ordering tasks with dependencies
  • Connected components: Finding all connected parts of a graph

Conclusion

DFS is a fundamental graph traversal algorithm that explores as far as possible along each branch before backtracking. It uses a stack data structure and is ideal for problems requiring deep exploration of graph structures, such as pathfinding and cycle detection.

Updated on: 2026-03-15T23:18:59+05:30

4K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements