Hello! Welcome to the next lesson in our module on graph traversal.
In the last lesson, we explored Breadth-First Search (BFS), a traversal algorithm that explores a graph "layer by layer." We saw how its use of a queue makes it ideal for finding the shortest path in an unweighted graph.
Today, we shift our focus to the other fundamental graph traversal algorithm: Depth-First Search (DFS). As the name suggests, DFS takes a different approach by exploring as deeply as possible along each branch before backtracking. This lesson is designed to help you implement and analyze depth-first search (DFS) on a graph.
By the end of this lesson, you will understand:
- The core philosophy of DFS: exploring deeply and backtracking.
- How to implement DFS using both recursion (which uses the call stack implicitly) and an iterative approach with an explicit stack.
- The time and space complexity of DFS and how it compares to BFS.
Let's begin our deep dive.
1. The Core Idea: The Adventurous Explorer
Where BFS explores broadly, like ripples in a pond, DFS behaves like an explorer in a maze. It picks a path and follows it to the very end. Only when it hits a dead end (or a previously visited location) does it backtrack to the last junction and try a different, unexplored path.
This "go deep, then backtrack" strategy is the essence of DFS. The following video provides an excellent intuitive introduction to this concept.
Depth First Search (DFS) Explained: Algorithm, Examples, and Code
The video 'Depth First Search (DFS) Explained' by Reducible builds the idea of DFS from the ground up. It uses a clear visual analogy of an explorer to demonstrate the process of going deep into a graph and backtracking when necessary.
Please watch from the beginning to 06:21. The first part (until 04:43) establishes the core intuition. The second part shows how different choices at junctions can lead to different but equally valid DFS traversal orders.
The key takeaways from the video are:
- Depth-first exploration: Always move to an unvisited neighbor if one is available.
- Backtracking: When you reach a vertex with no unvisited neighbors, you return to the vertex from which you came and try another path.
- Order dependency: The specific DFS path depends on the order in which you decide to visit neighbors at each junction.
2. Implementing DFS
Because of its backtracking nature, DFS can be implemented very naturally using recursion. However, understanding the iterative approach with an explicit stack is also valuable, as it draws a direct parallel to BFS's use of a queue.
The Recursive Approach
Recursion is the most common and often most elegant way to write DFS. A recursive function that calls itself for each unvisited neighbor perfectly models the "go deep" behavior. The act of returning from a function call is the "backtrack" step. The program's call stack implicitly manages the traversal state for us.
Just as with BFS, a critical component is a visited array or set. This prevents the algorithm from re-visiting nodes and getting caught in an infinite loop if the graph contains cycles.
This image beautifully connects the recursive code, the graph, and the state of the call stack during a DFS traversal.

For a detailed walkthrough of the implementation, the next video explains the logic line by line, linking it directly to the recursive function calls.
G-6. Depth-First Search (DFS) | C++ and Java | Traversal Technique in Graphs
The 'take U forward' channel provides a practical, code-focused explanation of the recursive DFS algorithm. This video is great for seeing how the abstract concept translates directly into a function that calls itself.
Watch from 04:44 to 17:12. The presenter first establishes the connection between DFS and recursion, then walks through the setup (adjacency list, visited array), and finally provides a step-by-step trace of the recursive calls and presents the final C++ and Java code.
The recursive pseudocode is simple and powerful:
DFS(graph, vertex, visited):
mark vertex as visited
// process vertex here (e.g., add to a list)
for each neighbor of vertex:
if neighbor has not been visited:
DFS(graph, neighbor, visited)
The Iterative Approach
To implement DFS iteratively, we simply replace the implicit call stack of recursion with an explicit Stack data structure. This makes its relationship to BFS very clear:
- BFS uses a Queue (First-In, First-Out), leading to a level-by-level search.
- DFS uses a Stack (Last-In, First-Out), leading to a depth-first search.
The algorithm works as follows:
- Initialize a stack and push the starting vertex onto it.
- While the stack is not empty:
a. Pop a vertex from the top of the stack. Let's call itcurrent.
b. Ifcurrenthas not been visited:
i. Markcurrentas visited and process it.
ii. Get all adjacent neighbors ofcurrent.
iii. Push each unvisited neighbor onto the stack.
The Reducible video you watched earlier also contains a clear segment explaining this iterative process.
Depth First Search (DFS) Explained: Algorithm, Examples, and Code
Let's revisit the Reducible video for its explanation of the iterative DFS approach. It does a great job of showing how the stack's LIFO (Last-In, First-Out) nature drives the 'deep' exploration.
Watch the segment from 11:10 to 14:05. Focus on how the stack is used to keep track of nodes to visit and how this differs from the queue used in BFS.
For a quick textual reference on the algorithm and code in multiple languages, the Programiz article on DFS is a useful resource.
Depth First Search (DFS) Algorithm - Programiz
The article 'Depth First Search (DFS) Algorithm' from Programiz provides a concise summary of both the recursive and iterative approaches, along with sample code.
Skim through the sections 'Depth First Search Algorithm' (which describes the iterative version), 'DFS Pseudocode (recursive implementation)', and 'DFS Implementation in Python, Java and C/C++'. This can serve as a quick reference for the code structure.
3. Complexity Analysis
One of the most interesting aspects of DFS is that its performance characteristics are identical to BFS, even though its behavior is completely different.
-
Time Complexity:
- Each vertex is visited exactly once (pushed onto the stack or passed to a recursive call). This accounts for the term.
- When we visit a vertex, we iterate through its adjacency list. Over the entire execution of the algorithm, we examine every edge in the graph once (for directed graphs) or twice (for undirected graphs). This accounts for the term.
- Therefore, the total time complexity is .
-
Space Complexity:
- The
visitedarray requires space. - The stack (either the implicit call stack for recursion or an explicit one) is the other main consumer of space. In the worst-case scenario, such as a graph that is a single long chain, the stack might need to hold all vertices at once. Thus, the space complexity is .
- The
For a more detailed breakdown of this analysis, especially considering different graph representations, the following article provides a thorough explanation.
Depth First Search or DFS - The Algorists
The article 'Depth First Search or DFS' from The Algorists offers a rigorous analysis of the time and space complexity. This will be a good read given your preference for understanding the 'why' behind the performance.
Please read the 'Time Complexity' and 'Space Complexity' sections. Note how the analysis for time complexity differs based on whether the graph is represented by an adjacency matrix vs. an adjacency list, reinforcing our choice from the first lesson in this module.
Conclusion
In this lesson, we have thoroughly examined Depth-First Search, the "deep" counterpart to BFS. We've seen how its strategy of exploring as far as possible before backtracking can be elegantly implemented using recursion.
Key Takeaways:
- DFS explores a graph by going as deep as possible down a path before backtracking.
- It is most naturally implemented recursively, where the call stack manages the traversal state. It can also be implemented iteratively with an explicit stack.
- A
visitedset is crucial to avoid infinite loops in graphs with cycles. - Despite its different traversal order, DFS has the same time complexity as BFS: .
- The space complexity is , dominated by the
visitedset and the maximum depth of the recursion stack.
Preview of the Next Lesson:
Now that you have both BFS and DFS in your algorithmic toolkit, we can start applying them to solve specific problems. In our next lesson, we will focus on cycle detection. We will explore how both DFS and BFS can be adapted to determine if a graph contains a cycle, and we will see why the properties of DFS make it particularly well-suited for this task.