Perl Program to Implement Depth-First Search (DFS)

Perl Program to Implement Depth-First Search (DFS)

Depth-First Search, or DFS, is a fundamental algorithm used to traverse or explore graphs and trees. It starts at a selected node and explores as far as possible along each branch before backtracking. This approach allows programmers to visit every node systematically, making it especially useful for solving problems like pathfinding, cycle detection, or network traversal. For beginners, DFS is an excellent way to understand recursion and stack-based problem solving.

In practical terms, DFS can be applied in social networks to explore connections, in mazes to find a path, in scheduling problems, and even in computer games for AI navigation. Learning DFS in Perl gives new programmers a chance to work with arrays and hashes in the context of graph structures while gaining insight into algorithmic thinking. By experimenting with DFS, beginners can see how complex structures can be systematically explored in an organized way.

Program 1: DFS Using Recursion on a Graph

This program demonstrates a simple recursive implementation of DFS on a predefined graph represented using a hash.

use strict;
use warnings;

my %graph = (
    A => ['B', 'C'],
    B => ['D', 'E'],
    C => ['F'],
    D => [],
    E => ['F'],
    F => []
);

my %visited;

sub dfs_recursive {

    my $node = shift;
    return if $visited{$node};

    print "$node ";
    $visited{$node} = 1;

    foreach my $neighbor (@{$graph{$node}}) {
        dfs_recursive($neighbor);
    }

}

print "DFS starting from node A: ";
dfs_recursive('A');
print "\n";

In this example, DFS begins at node ‘A’ and recursively visits each unvisited neighbor. This approach is intuitive for beginners because it mirrors how one might explore a maze: go as far as possible before backtracking. It’s useful for understanding recursion and the role of a visited tracking system in preventing infinite loops.

Program 2: DFS Using a Stack (Iterative Approach)

Sometimes recursion can be replaced with an explicit stack. This program shows how DFS can be implemented iteratively.

use strict;
use warnings;

my %graph = (
    A => ['B', 'C'],
    B => ['D', 'E'],
    C => ['F'],
    D => [],
    E => ['F'],
    F => []
);

my %visited;
my @stack = ('A');

print "DFS using stack starting from node A: ";
while (@stack) {

    my $node = pop @stack;
    next if $visited{$node};

    print "$node ";
    $visited{$node} = 1;

    push @stack, reverse @{$graph{$node}};

}

print "\n";

This iterative version is valuable for beginners to understand how recursion can be mimicked using a stack. The algorithm still explores deep into the graph before moving to other branches. It demonstrates flexibility in algorithm design and shows how data structures like stacks can manage traversal order.

Program 3: DFS on a Graph with Negative Values as Node Labels

Graphs aren’t always labeled with letters; they can also have numeric or negative values. This program handles a graph with negative node labels.

use strict;
use warnings;

my %graph = (
    -1 => [0, 1],
    0 => [-2, 2],
    1 => [3],
    -2 => [],
    2 => [],
    3 => []
);

my %visited;

sub dfs_numeric {

    my $node = shift;
    return if $visited{$node};

    print "$node ";
    $visited{$node} = 1;

    foreach my $neighbor (@{$graph{$node}}) {
        dfs_numeric($neighbor);
    }

}

print "DFS on graph with negative nodes: ";
dfs_numeric(-1);
print "\n";

This example illustrates that DFS works regardless of node labels. Beginners can see that the algorithm is independent of the type of node identifiers, as long as the graph is properly defined. It reinforces the idea that DFS is about structure traversal, not just specific data types.

Program 4: DFS on a Graph Represented by an Adjacency Matrix

Another way to represent a graph is with an adjacency matrix. This program uses DFS to traverse a graph defined this way.

use strict;
use warnings;

my @graph = (
    [0, 1, 1, 0, 0, 0],
    [0, 0, 0, 1, 1, 0],
    [0, 0, 0, 0, 0, 1],
    [0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1],
    [0, 0, 0, 0, 0, 0]
);

my @visited;

sub dfs_matrix {

    my $node = shift;
    return if $visited[$node];

    print "$node ";
    $visited[$node] = 1;

    for my $i (0..$#{$graph[0]}) {
        dfs_matrix($i) if $graph[$node][$i] && !$visited[$i];
    }

}

print "DFS on graph with adjacency matrix: ";
dfs_matrix(0);
print "\n";

This method helps beginners understand that DFS can be applied regardless of how the graph is represented. Whether using hashes, arrays, or matrices, the traversal principle remains the same.

Program 5: DFS to Detect a Path Between Two Nodes

DFS can also answer specific questions, such as whether there is a path between two nodes.

use strict;
use warnings;

my %graph = (
    A => ['B', 'C'],
    B => ['D', 'E'],
    C => ['F'],
    D => [],
    E => ['F'],
    F => []
);

my %visited;

sub dfs_path {

    my ($node, $target) = @_;

    return 0 if $visited{$node};
    return 1 if $node eq $target;

    $visited{$node} = 1;

    foreach my $neighbor (@{$graph{$node}}) {
        return 1 if dfs_path($neighbor, $target);
    }

    return 0;
}

my $start = 'A';
my $end = 'F';

print dfs_path($start, $end) ? "Path exists from $start to $end\n" : "No path from $start to $end\n";

This example demonstrates how DFS can be adapted to solve practical problems. Beginners can see that DFS is not only about visiting nodes but also about using recursion to explore possibilities efficiently.

Frequently Asked Questions (FAQ)

DFS often raises questions for beginners exploring graph algorithms.

Q1. What is the time complexity of DFS?
DFS runs in O(V + E), where V is the number of vertices and E is the number of edges.

Q2. Does DFS work on disconnected graphs?
Yes, but you need to run DFS on each unvisited component to cover the entire graph.

Q3. Can DFS detect cycles in a graph?
Yes, by keeping track of the recursion stack or visited nodes, cycles can be detected.

Q4. When should I use DFS instead of BFS?
DFS is useful when you need to explore deep paths first, such as solving mazes or puzzles. BFS is better for finding shortest paths.

Q5. Is recursion mandatory for DFS?
No, DFS can be implemented iteratively using a stack, which is helpful when recursion depth is a concern.

Conclusion

Depth-First Search is a versatile and fundamental algorithm for exploring graphs and trees. By learning both recursive and iterative DFS in Perl, beginners can develop strong skills in recursion, stack usage, and graph representation. DFS is applicable in many real-world scenarios, from pathfinding to problem-solving in computer science.

Practicing DFS helps beginners think systematically about traversing complex structures and provides a foundation for more advanced graph algorithms like BFS, Dijkstra’s, and topological sorting. Experimenting with different graph representations and applications reinforces understanding and builds confidence in algorithmic programming.

Scroll to Top