【算法学习】DFS与BFS

server/2025/2/13 12:37:32/

目录

一,深度优先搜索

1,DFS

2,图的DFS遍历

(1),递归实现(隐士栈)

(2),显示栈实现(非递归)

二,广度优先搜索 

1,BFS

2,图的BFS遍历

3,路径记录

小结:

最短路径问题 (BFS)


BFS(广度优先搜索)和DFS(深度优先搜索)

BFS和DFS树是图/树遍历的两种基础算法,核心在于探索顺序和适用场景的不同。

一,深度优先搜索

1,DFS

DFS即Depth First Search,深度优先搜索。遍历顺序为:沿分支深入到底再回溯,优先探索最新发现的节点。简单来说,就是一条路走到黑。比如对下面一颗树的遍历。

从A开始遍历,再到B,有两种情况,意味着这条路还没有走完,接着走到D,之后就没路了。然后我就回溯到B,因为B还有情况没走完,接着再走到E,之后没路了,就回溯到B,发现B的两种情况以及那个走完了,就再回溯到A,然后走到C...... 

简单理解就是:一条路走动黑,直到没路可走了,再回溯回去,尝试其他路径。

2,图的DFS遍历

DFS的实现方式有两种,一种是递归实现,但递归实现有时会产生栈溢出的风险,可改用显示栈实现。

(1),递归实现(隐士栈)

#include <iostream>
#include <vector>
using namespace std;void DFS(vector<vector<int>>& graph, int node, vector<bool>& visited)
{visited[node] = true;cout << node << " ";    //前序遍历for (int neighbors : graph[node]){if (!visited[neighbors])DFS(graph, neighbors, visited);}}int main()
{//邻接表表示(无向图)vector<vector<int>> graph = {{1,2},      //节点0的邻居是1 2{0,3,4},	//节点1的邻居是0 3 4{0,5},		//节点2的邻居是0 5{1},        //节点3的邻居是1{1},        //节点4的邻居是1{2}         //节点5的邻居是2};//记录访问过的节点vector<bool> visited(graph.size(), false);cout << "DFS结果为:";DFS(graph, 0, visited);return 0;
}

(2),显示栈实现(非递归)


#include <iostream>
#include <stack>
#include <vector>
using namespace std;
void DFS_Stack(vector<vector<int>>& graph, int start)
{vector<bool> visited(graph.size(), false);stack<int> s;s.push(start);visited[start] = true;while (!s.empty()){int node = s.top();s.pop();cout << node << " ";//逆序入栈 以保证和递归顺序一致for (auto it = graph[node].rbegin(); it != graph[node].rend(); it++){int neighbors = *it;if (!visited[neighbors]){visited[neighbors] = true;s.push(neighbors);}}}
}
int main()
{//邻接表表示(无向图)vector<vector<int>> graph = {{1,2},      //节点0的邻居是1 2{0,3,4},	//节点1的邻居是0 3 4{0,5},		//节点2的邻居是0 5{1},        //节点3的邻居是1{1},        //节点4的邻居是1{2}         //节点5的邻居是2};cout << "栈实现遍历结果为:" << endl;DFS_Stack(graph, 0);return 0;
}

二,广度优先搜索 

1,BFS

BFS即Breadth First Search,即广度优先搜索。DFS是一条路走到黑,那么 BFS就可以理解成是在每个岔路口都向前走一步。也可以理解成是一层一层遍历。

从A开始遍历,有两种情况B,C。 将B,C遍历完后,再遍历D,E,F。一层一层的遍历。

上述是对树的BFS,然而树也是一种 图。 不难发现,我们每次搜索的位置都是离当前节点最近的点。因此,BFS是具有最短路性质的。这里用到的贪心策略是:想要找到最短路径,保证每次在选节点时,也就是每次前进的时候,都是距离上一个节点最近的点。

因此,BFS也可以求解最短路问题。

2,图的BFS遍历

#include <iostream>
#include <vector>
#include <queue>
#include <unordered_set>using namespace std;// BFS 遍历函数
void BFS(const vector<vector<int>>& graph, int start) {vector<bool> visited(graph.size(), false); // 访问标记数组queue<int> q;q.push(start);visited[start] = true;while (!q.empty()) {int node = q.front();q.pop();cout << node << " "; // 输出当前节点(可替换为自定义操作)// 遍历所有邻接节点for (int neighbor : graph[node]) {if (!visited[neighbor]) {visited[neighbor] = true;q.push(neighbor);}}}
}int main() {// 示例图的邻接表表示(无向图)vector<vector<int>> graph = {{1, 2},     // 节点0的邻居是1和2{0, 3, 4},  // 节点1的邻居是0、3、4{0, 5},     // 节点2的邻居是0、5{1},        // 节点3的邻居是1{1},        // 节点4的邻居是1{2}         // 节点5的邻居是2};cout << "BFS遍历结果:";BFS(graph, 0); // 从节点0开始遍历// 输出:0 1 2 3 4 5 return 0;
}

3,路径记录

在图中寻找一条从开始到目标target的路径。

vector<int> BFS_Path(vector<vector<int>>& graph, int start, int target)
{vector<bool> visited(graph.size(), false);  //记录访问过的节点vector<int> parent(graph.size(), -1);  //记录父节点queue<int> q;q.push(start);visited[start] = true;while (!q.empty()){int node = q.front();q.pop();if (node == target)break;for (int neighbors : graph[node]){if (!visited[neighbors]){visited[neighbors] = true;parent[neighbors] = node; //neighbors的父节点nodeq.push(neighbors);}}}vector<int> path;for (int at = target; at != -1; at = parent[at])path.push_back(at);reverse(path.begin(), path.end());return path;
}

最短路径问题 (BFS)

【题目描述】

给的那个一个n*m的二维整数数组,用来表示迷宫,数组中只包含1和0,0表示可以走的路,1表示不可以通过的墙壁。

最初,有一个人位于左上角(1,1)处,已知改人每次可以向上,下,做,右任意一个方向移动一个位置。请问:改人从左上角移动到右下角(n,m),至少需要移动多少次。数据保证(0,0)和(n,m)的位置均为0。且一定至少存在一条通路。

【输入格式】

第一行包含两个整数n和m。

接下来n行,每行包含m个整数(0或1),表示迷宫。

【输出格式】

表示最少移动次数。

本题求的是最短路,所以可以用bfs从当前节点出发,每次向四周扩展。

#include <iostream>
#include <queue>
#include <cstring>
using namespace std;typedef pair<int, int> PII;//方向数组
int dx[4] = { -1,0,1,0 }, dy[4] = { 0,1,0,-1 };
const int N = 110;
int map[N][N];  //迷宫
int mark[N][N];  //标记数组
int n, m;void BFS()
{memset(mark, -1, sizeof(mark));queue<PII> q;q.push({ 0,0 });mark[0][0] = 0;while (!q.empty()){PII top = q.front();q.pop();for (int i = 0; i < 4; i++){int x = top.first + dx[i];int y = top.second + dy[i];if (x >= 0 && x < n && y >= 0 && y < m && mark[x][y] == -1 && map[x][y] == 0){q.push({ x,y });mark[x][y] = mark[top.first][top.second] + 1;}}}cout<<mark[n - 1][m - 1]<<endl;
}
int main()
{cin >> n >> m;for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)cin >> map[i][j];BFS();return 0;
}

小结:

BFS优势与局限
  • 优点

    • 保证找到最短路径(无权图)。

    • 避免深度过大的栈溢出风险。

  • 缺点

    • 空间消耗大(存储整层节点)。

    • 不适合目标节点在深层的情况(效率低)。

DFS优势与局限
  • 优点

    • 空间效率高(仅存储当前路径)。

    • 适合寻找所有解(如回溯算法)。

  • 缺点

    • 可能陷入无限深的分支(需设置最大深度)。

    • 递归实现有栈溢出风险(可改用显式栈)。


http://www.ppmy.cn/server/167325.html

相关文章

Hive的数据库操作和表操作

1、启动zookeeper以正确启动高可用集群 2、启动HiveServer2服务 3、连接HiveServer2服务 4、创建数据库hive_db 5、调整日志级别忽略INFO日志 6、查看数据库hive_db的属性信息 7、修改数据库hive_db的属性信息&#xff0c;并查看数据库hive_db的属性信息 8、删除数据库hive_db&…

dify.ai 怎么配置链接火山引擎等云厂商的deepseek模型

要将 dify.ai 配置链接到火山引擎等云厂商的 DeepSeek 模型. 申请火山引擎的key&#xff0c;创建endpoint 添加模型 测试模型

1.攻防世界 unserialize3(wakeup()魔术方法、反序列化工作原理)

进入题目页面如下 直接开审 <?php // 定义一个名为 xctf 的类 class xctf {// 声明一个公共属性 $flag&#xff0c;初始值为字符串 111public $flag 111;// 定义一个魔术方法 __wakeup()// 当对象被反序列化时&#xff0c;__wakeup() 方法会自动调用public function __wa…

本地部署【LLM-deepseek】大模型 ollama+deepseek/conda(python)+openwebui/docker+openwebui

通过ollama本地部署deepseek 总共两步 1.模型部署 2.[web页面] 参考官网 ollama:模型部署 https://ollama.com/ open-webui:web页面 https://github.com/open-webui/open-webui 设备参考 Mac M 芯片 windows未知 蒸馏模型版本:deepseek-r1:14b 运行情况macminim2 24256 本地…

总结Thread的基本用法

1. 线程创建 1.1 创建一个类, 继承Thread, 重写run方法 class MyThread extends Thread {Overridepublic void run() {while (true) {System.out.println("hello thread");try {// 这里只能 try catch, 不能 throws.// 此处是方法重写. Java 的方法重写规则不允许子…

DeepSeek与核货宝订货系统的协同进化:智能商业范式重构

数据处理与分析方面 深度数据洞察&#xff1a;利用Deepseek强大的智能数据挖掘与分析能力&#xff0c;处理核货宝订货系统中的海量订单数据、客户数据、商品数据等。比如分析不同地区、不同时间、不同客户群体的订货偏好和趋势&#xff0c;为批发订货企业制定精准的采购、库存…

CNN-day8-经典神经网络GoogleNet

day9-经典神经网络GoogleNet 1 11卷积 卷积核的尺寸等于1的特例&#xff0c;用来做升维和降维&#xff0c;减少参数量&#xff0c;改变通道数&#xff0c;通道间的特征融合 1.1作用 1.1.1实现通道间特征的融合 常规转换公式&#xff1a;0.2989R 0.5870G 0.1140B import…

我用AI做数据分析之四种堆叠聚合模型的比较

我用AI做数据分析之四种堆叠聚合模型的比较 这里AI数据分析不仅仅是指AI生成代码的能力&#xff0c;我想是测试AI数据分析方面的四个能力&#xff0c;理解人类指令的能力、撰写代码的能力、执行代码的能力和解释结果的能力。如果这四个能力都达到了相当的水准&#xff0c;才可…