Enrol to start learning
Reading is open to everyone. Enrolling is free, and it is what unlocks the audio lessons, practice tests and progress tracking.
21.1.1. Depth First Search (DFS)
Learn content
Interactive Audio Lesson
Unlock the classroom podcast
The transcript is free to read. A free account plays the conversation back.
Today we’re discussing Depth First Search, or DFS. Unlike BFS, which explores level by level, DFS dives deep into a graph. Can anyone tell me what this means?
It means we go as far as possible along one branch before moving to others!
Exactly! We extend along one path until we can’t anymore. What do you think happens when we reach a dead end?
We have to backtrack to the last vertex that had unexplored neighbors!
Yes! We use a stack to manage these vertices. Let's remember that with the acronym S for Stack, B for Backtrack! Great understanding!
Unlock the classroom podcast
The transcript is free to read. A free account plays the conversation back.
Now, let’s talk about how to implement DFS. We can do it recursively or use an explicit stack. Who can explain the recursive method?
We call DFS on the unexplored neighbor and suspend the current vertex.
Correct! This makes the stack implicit. Why do we track parents during DFS?
To understand the traversal path and the connectivity between vertices!
Great! It’s essential to have that context. Remember: Parent Tracks Vertices! Let's keep that in mind.
Unlock the classroom podcast
The transcript is free to read. A free account plays the conversation back.
Next, let’s look at the complexity. Why is it O(n + m) with an adjacency list?
Every vertex is visited once, and we check each edge once!
Exactly! It’s efficient. What about using an adjacency matrix?
That’s O(n^2) because we might check every entry in the matrix even when it isn’t needed!
Well done! Keep in mind: Efficient Edges for Lists, Square for Matrices!
Unlock the classroom podcast
The transcript is free to read. A free account plays the conversation back.
Finally, let’s discuss what we can do with the results of DFS. Can anyone share some applications?
We can find cycles in the graph!
And figure out connected components!
Yes! DFS reveals many graphs' structural properties. Remember: Discover Cycles with DFS!
Overview
Short Summary
Depth First Search (DFS) is an algorithm used for traversing or searching tree or graph data structures, exploring as far as possible along each branch before backtracking.
Medium Summary
DFS is a search strategy that explores vertices in a graph by going deep into one branch before exploring others. It uses a stack structure to keep track of vertices to explore and can be implemented recursively. This approach enables the algorithm to identify structural features of the graph over breadth-first search, despite not necessarily finding the shortest path.
Detailed Summary
Depth First Search (DFS)
Depth First Search (DFS) is a fundamental algorithm in graph theory used for traversing or searching tree or graph structures. It differs from Breadth First Search (BFS) by exploring as far along a branch as possible before backtracking. The algorithm begins at a starting vertex, marking it as visited, and then goes to an unexplored neighbor, moving deeper into the graph.
Key Mechanism
The critical mechanism behind DFS is the use of a stack (or recursion) to track vertices. When we reach a vertex, if it has unexplored neighbors, we suspend processing of the current vertex and explore the neighbor. If we reach a dead end with no unexplored neighbors, we backtrack to the last suspended vertex.
Recursive Implementation
DFS can also be implemented recursively, eliminating the need for an explicit stack. The algorithm initializes each vertex’s state and marks them visited, tracking their parent vertices and returning when necessary.
Complexity Analysis
The complexity of DFS is noteworthy; each vertex is visited once, leading to a time complexity of O(n + m) when using an adjacency list, where n is the number of vertices and m is the number of edges. In contrast, using an adjacency matrix gives a time complexity of O(n^2).
Applications
DFS reveals various graph properties, such as detecting cycles, identifying connected components, and finding articulation points. While it does not ensure the shortest path like BFS, it captures deeper structural relationships.
By tracking pre- and post-visit numbers during the traversal, additional valuable insights into the graph's structure can be derived.
Reference YouTube Videos
Audio Book
Unlock the audio lesson
The script is above and free to read. A free account plays it back, in the voice you pick.
Create a free accountDepth first search (DFS) is an algorithm for exploring graphs. Unlike breadth first search, which explores all vertices level by level, DFS explores each vertex's neighbors immediately. Starting at a vertex, we visit the first unvisited neighbor, suspending the execution at the current vertex until all its neighbors are explored.
Detailed Explanation
DFS begins at a starting vertex and explores as deep as possible along each branch before backtracking. When a vertex has unvisited neighbors, DFS explores these neighbors, marking the current vertex as suspended. If a dead-end is reached, the algorithm backtracks to the nearest vertex that has unexplored neighbors, continuing the same process until all vertices have been visited.
Examples & Analogies
Imagine you are in a library looking for a specific book in a section. You go down each aisle (the depth) and check each shelf (the neighbors) for the book. If you find one section has no books, you backtrack to the previous aisle and explore a different section until you either find the book or check all the aisles.
Unlock the audio lesson
The script is above and free to read. A free account plays it back, in the voice you pick.
Create a free accountIn DFS, all the suspended vertices are kept in a stack. As you go deeper into the graph, this stack grows. When you reach a dead end, you backtrack using the stack to process earlier suspended vertices.
Detailed Explanation
The stack helps track the path taken during the DFS. Each time a vertex is visited, it gets pushed onto the stack. When there are no more unvisited neighbors, the algorithm pops the vertex off the stack to return to the last suspended vertex, allowing you to continue exploring from there. This technique efficiently manages the state of the algorithm using the principle of Last In, First Out (LIFO).
Examples & Analogies
Think of a person climbing a mountain and using a series of ropes (the stack) to ascend different ridges. When they cannot go higher, they return along the ropes they used until they can find a new route to explore. Each point where they paused is like a suspended vertex in DFS.
Unlock the audio lesson
The script is above and free to read. A free account plays it back, in the voice you pick.
Create a free accountWhen executing DFS on a graph, we start with a designated vertex, mark it as visited, and move through its neighbors recursively. For example, starting from vertex 4, we explore its neighbors: 1, then move to 2, 3, etc., marking each as visited until we return to finish our exploration.
Detailed Explanation
In practical terms, you mark the starting vertex as visited and systematically explore each unvisited neighbor. The algorithm tracks which vertices have been visited to prevent cycles and ensure all vertices are explored efficiently. As we demonstrate on a sample graph, we can mark the sequence in which we visit vertices and backtrack when necessary.
Examples & Analogies
Picture a maze: you start at the entrance (vertex), explore each passageway (neighbors) blindly until you reach a wall (dead end), then retrace your steps back to previous junctions until every path has been explored.
Unlock the audio lesson
The script is above and free to read. A free account plays it back, in the voice you pick.
Create a free accountDFS can also be implemented recursively. Each time a new vertex is visited, the DFS function is called recursively on that vertex, eliminating the need for an explicit stack.
Detailed Explanation
Recursion simplifies the DFS implementation because each function call is akin to pushing a vertex onto a stack. When a vertex is explored, a function call is made for its unvisited neighbors, and the call stack takes care of backtracking automatically, leading to a cleaner and more intuitive implementation.
Examples & Analogies
Imagine a nesting doll scenario: you open one doll (visit a vertex) and find another inside (call the function recursively) until you reach the innermost doll. Once you reach the smallest doll (dead end), you put each doll back on top as you exit (backtrack).
Unlock the audio lesson
The script is above and free to read. A free account plays it back, in the voice you pick.
Create a free accountThe complexity of DFS is determined by the number of vertices and edges in the graph. Each vertex is visited once, leading to O(n) calls, and checking all neighbors amounts to O(n) for adjacency matrices, resulting in O(n^2) time. With adjacency lists, it yields a linear time complexity of O(m + n), where m is edges and n is vertices.
Detailed Explanation
DFS time complexity involves two factors: the number of vertices (n) and the connections (edges, m) between them. For dense graphs represented as matrices, each neighbor must be checked for each vertex, making it slower (O(n^2)). However, for sparse graphs represented using lists, we only examine existing edges, leading to better performance (O(m + n)). It’s vital to use the appropriate representation based on the graph structure to optimize performance.
Examples & Analogies
Consider moving through a busy city (dense graph) where you'd take longer routes, and now imagine moving through a small town (sparse graph) where each street is quick to traverse. In the town, you spend less time checking each intersection than in the busy city with countless traffic signals.
--
Key concepts
Core takeaways and short definitions to help you quickly recall the key ideas from this section.
- Stack:
A data structure used to remember the vertices to explore during DFS.
- Backtracking:
The process of returning to a previously suspended vertex to explore other unexplored neighbors.
- Recursive Implementation:
DFS can use recursive function calls, which implicitly manage the stack.
- Complexity Analyses:
Time complexity can vary based on whether an adjacency list or matrix is used.
Examples
Step-by-step examples to apply the section's ideas and test your understanding.
Exploring a graph with vertices and edges: Starting at vertex A, we traverse to B, then C, marking each vertex as visited, until we can no longer move forward.
Determining if a graph contains a cycle: Using DFS, if we encounter an already visited vertex that is not the direct parent, we identify a cycle.
Memory aids
In a vast forest of nodes, a traveler picks one path, explores every corner until there’s none left, then he retraces his steps, visiting untraveled trails — that's like DFS!
Flash Cards
Glossary
Depth First Search (DFS)
An algorithm for traversing or searching tree or graph data structures that explores as far as possible along a branch before backtracking.
Adjacency List
A collection of lists or linked lists where each list corresponds to a vertex in the graph and contains the vertices that are adjacent to it.
Stack
A data structure that follows the Last In First Out (LIFO) principle, used for keeping track of vertices to explore in DFS.
Cycle
A path in a graph that starts and ends at the same vertex, forming a closed loop.
Connected Component
A subset of a graph where every two vertices are connected to each other by paths, and which is connected to no additional vertices.