深度优先搜索

devtools/2025/2/22 20:23:16/

1. 算法思想

DFS 通过递归或栈来实现,其过程如下:

  1. 从起始节点开始,访问该节点并标记为已访问。

  2. 选择一个未访问的邻接节点,继续深入探索。

  3. 如果当前节点没有未访问的邻接节点,则回溯到上一个节点。

  4. 重复上述过程,直到所有节点都被访问。


2. 算法实现

DFS 可以通过 递归 或  来实现。

递归实现

void dfs(int node, vector<vector<int>>& graph, vector<bool>& visited) {// 标记当前节点为已访问visited[node] = true;cout << node << " "; // 输出访问的节点// 遍历所有邻接节点for (int neighbor : graph[node]) {if (!visited[neighbor]) {dfs(neighbor, graph, visited); // 递归访问}}
}

栈实现

void dfs(int start, vector<vector<int>>& graph) {vector<bool> visited(graph.size(), false);stack<int> stk;// 将起始节点入栈stk.push(start);visited[start] = true;while (!stk.empty()) {int node = stk.top();stk.pop();cout << node << " "; // 输出访问的节点// 遍历所有邻接节点for (int neighbor : graph[node]) {if (!visited[neighbor]) {visited[neighbor] = true;stk.push(neighbor); // 将未访问的邻接节点入栈}}}
}

3. 算法步骤

  1. 初始化

    • 创建一个标记数组 visited,用于记录节点是否被访问过。

    • 选择起始节点。

  2. 访问节点

    • 访问当前节点,并标记为已访问。

  3. 递归/栈扩展

    • 遍历当前节点的所有邻接节点,对未访问的节点递归调用 DFS 或将其入栈。

  4. 回溯

    • 当无法继续深入时,回溯到上一个节点。


4. 时间复杂度

  • 邻接表表示:O(V+E),其中 V 是顶点数,E 是边数。

  • 邻接矩阵表示:O(V2),因为需要遍历整个矩阵。


5. 应用场景

  1. 图的连通性:判断图中两个节点是否连通。

  2. 拓扑排序:用于有向无环图(DAG)的拓扑排序。

  3. 路径搜索:寻找图中从起点到终点的路径。

  4. 环检测:检测图中是否存在环。

  5. 生成迷宫:通过 DFS 生成随机迷宫。


6. 代码示例:图的连通分量

以下代码使用 DFS 计算无向图的连通分量数量:

void dfs(int node, vector<vector<int>>& graph, vector<bool>& visited) {visited[node] = true;for (int neighbor : graph[node]) {if (!visited[neighbor]) {dfs(neighbor, graph, visited);}}
}int countConnectedComponents(vector<vector<int>>& graph) {int n = graph.size();vector<bool> visited(n, false);int count = 0;for (int i = 0; i < n; ++i) {if (!visited[i]) {dfs(i, graph, visited); // 对每个未访问的节点调用 DFScount++; // 连通分量数量加 1}}return count;
}

7. DFS 的变种

  1. 回溯算法:DFS 常用于解决组合优化问题,如八皇后问题、数独等。

  2. 记忆化搜索:在递归过程中记录中间结果,避免重复计算。

  3. 迭代加深搜索(IDS):结合 DFS 和 BFS 的优点,逐步增加搜索深度。


8. DFS 与 BFS 的比较

特性DFSBFS
数据结构栈(递归或显式栈)队列
空间复杂度O(V)O(V)(递归深度)O(V)O(V)(队列大小)
适用场景路径搜索、拓扑排序最短路径、连通分量
是否找到最短路径

9.例题

P1036 [NOIP 2002 普及组] 选数 - 洛谷

#include <iostream>
#include <cstdio>
using namespace std;
bool isprime(int a){for(int i = 2; i * i <= a; i++)if(a % i == 0)return false;return true;
}int n,k;
int a[25];
long long ans;void dfs(int m, int sum, int startx){if(m == k){if(isprime(sum))ans++;return ;}for(int i = startx; i < n; i++)dfs(m + 1, sum + a[i], i + 1);return ;
}int main(){scanf("%d%d",&n,&k);for(int i = 0; i < n; i++)scanf("%d",&a[i]);dfs(0, 0, 0);printf("%d\n",ans);return 0;
}


http://www.ppmy.cn/devtools/160260.html

相关文章

【Linux】Socket编程—TCP

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 &#x1f525; 所属专栏&#xff1a;Linux系统编程 这里将会不定期更新有关Linux的内容&#xff0c;欢迎大家点赞&#xff0c;收藏&#xff0c;评论&#x1f973;&#x1f973;&#x1f389;&#x1f389;&#x1f389; 文章目…

在Windows系统中安装Open WebUI并连接Ollama

Open WebUI是一个开源的大语言模型&#xff08;LLM&#xff09;交互界面&#xff0c;支持本地部署与离线运行。通过它&#xff0c;用户可以在类似ChatGPT的网页界面中&#xff0c;直接操作本地运行的Ollama等大语言模型工具。 安装前的核心要求&#xff1a; Python 3.11&#…

【Golang学习之旅】Go 语言微服务架构实践(gRPC、Kafka、Docker、K8s)

文章目录 1. 前言&#xff1a;为什么选择Go语言构建微服务架构1.1 微服务架构的兴趣与挑战1.2 为什么选择Go语言构建微服务架构 2. Go语言简介2.1 Go 语言的特点与应用2.2 Go 语言的生态系统 3. 微服务架构中的 gRPC 实践3.1 什么是 gRPC&#xff1f;3.2 gRPC 在 Go 语言中的实…

UDP

UDP 是什么&#xff1f; 提供无连接的&#xff0c;尽最大努力的数据传输服务&#xff08;不保证数据传输的可靠性&#xff09; UDP 的特点有哪些&#xff1f; 1&#xff09;UDP 是无连接的&#xff1b; 2&#xff09;UDP 使用尽最大努力交付&#xff0c;即不保证可靠交付&am…

MySQL的聚簇索引与非聚簇索引

前言 首先我们要了解到&#xff0c;聚簇索引只能有一个&#xff0c;而非聚簇可以有多个。在本文中可以了解到&#xff0c;范围查询时聚簇索引的优势&#xff0c;以及非聚簇索引在频繁更新时的劣势。   在MySQL中&#xff0c;主键索引通常就是聚簇索引&#xff0c;如果没有显式…

VSCode 实用快捷键

前文 VSCode 作为文本编辑神器, 熟练使用其快捷键更是效率翻倍, 本文介绍 VSCode 常用的实用的快捷键 实用快捷键 涉及到文本操作, 搜索定位, 多光标, 面板打开等快捷键 功能快捷键复制光标当前行 (不需要鼠标选中) Ctrl C 剪切光标当前行 (不需要鼠标选中) Ctrl X 当前行下…

mysql 使用 CONCAT、GROUP_CONCAT 嵌套查询出 json 格式数据

tb_factory表由 factory_code 和 factory_name 字段&#xff0c;查询出如下所示效果&#xff1a; {"factory_0001": "工厂1","factory_0002": "工厂2",... } select sql&#xff1a; SELECT CONCAT( "{",GROUP_CONCAT( C…

Android-构建问题记录

文章目录 报错 No signature of method: build_4tl7r8s6qna6qev75ywim0904.android() is applicable for argument types: (build_4tl7r8s6qna6qev75ywim0904 r u n c l o s u r e 2 ) v a l u e s : [ b u i l d 4 t l 7 r 8 s 6 q n a 6 q e v 75 y w i m 0904 _run_closure2…