DFS (Graph Theory)
Introduction
DFS, short for Depth First Search, is an algorithm for traversing or searching tree or graph data structures. The term "depth-first" means that it always tries to go deeper into the graph at each step.
This algorithm is often taught alongside BFS, but apart from both being able to traverse connected components of a graph, their applications are quite different, and there are few scenarios where the two algorithms can be used interchangeably.
DFS is often used to refer to searches implemented using recursive functions, but in reality, the two are not exactly the same. For the search paradigm, please refer to DFS (Search).
Process
The most distinctive feature of DFS is its recursive self-calls. Similar to BFS, DFS marks visited nodes during traversal, skipping nodes that have already been marked to ensure each node is visited only once. Any function that follows these two rules can be considered a generalized DFS.
Specifically, the general structure of DFS is as follows:
1 2 3 4 5 6 7 8 | |
The above code only includes the essential structure of DFS. In practice, additional code is often added to leverage DFS properties for other operations.
Properties
The algorithm typically has a time complexity of \(O(n+m)\) and a space complexity of \(O(n)\), where \(n\) represents the number of vertices and \(m\) represents the number of edges. Note that the space complexity includes stack space, which is \(O(n)\). This time complexity is achieved under the condition of traversing each edge in \(O(1)\) on average, such as when using forward stars or adjacency lists to store the graph; using an adjacency matrix may not achieve this complexity.
Note: Currently, most programming contests (including NOIP, most provincial selections, and competitions organized by CCF) support unlimited stack space, meaning: stack space is not separately restricted, but the total memory space is still limited by the problem statement. However, most operating systems impose additional restrictions on stack space, so local debugging requires methods to lift these restrictions.
- On Windows, the common method is to add
-Wl,--stack=1000000000to the compilation options, setting the stack space limit to 1,000,000,000 bytes.- On Linux, the common method is to execute
ulimit -s unlimitedin the terminal before running the program, indicating unlimited stack space. This only needs to be done once per terminal and is effective for each subsequent program run.
Implementation
Stack Implementation
DFS can be implemented using a Stack as a temporary container for nodes during traversal; this highly corresponds to BFS implemented with a Queue.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Recursive Implementation
The order of function evaluation during recursive calls resembles adding and removing elements from a stack, hence the virtual address space occupied by function calls is called the Call Stack. DFS can be implemented recursively.
Using an Adjacency List as the graph storage method:
1 2 3 4 5 6 7 8 | |
1 2 3 4 5 6 7 8 9 | |
Using Chain Forward Star as an example:
1 2 3 4 5 6 7 8 | |
1 2 3 4 5 6 7 8 | |
1 2 3 4 5 6 7 | |
DFS Sequence
The DFS sequence refers to the sequence of node IDs visited during the DFS call process.
We observe that each subtree corresponds to a contiguous segment (an interval) in the DFS sequence.
Bracket Sequence
Record a left parenthesis ( when DFS enters a node, and record a right parenthesis ) when exiting a node.
Each node appears twice. The depth difference between two adjacent nodes is 1.
DFS on General Graphs
For non-connected graphs, only the connected component containing the starting point can be visited.
For connected graphs, the DFS sequence is generally not unique.
Note: The DFS sequence of a tree is also not unique.
During DFS, by recording which node each node was visited from, a tree structure called the DFS tree can be constructed. The DFS tree is a spanning tree of the original graph.
The DFS Tree has many properties, such as being used to find Strongly Connected Components.
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:OI-wiki
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用