当前位置: 首页 > news >正文

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

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

1.1. Python实现BFS和DFS

from collections import dequeclass Graph:"""无向图类,支持添加边,并实现了 BFS(广度优先搜索)和 DFS(深度优先搜索)用于查找从一个顶点到另一个顶点的路径。"""def __init__(self, v):self.v = v                            # 顶点数self.adj = [[] for _ in range(v)]     # 邻接表,初始化为空列表self.found = False                    # DFS 中用于标记是否已经找到目标节点def add_edge(self, s, t):self.adj[s].append(t)self.adj[t].append(s)  # 因为是无向图,所以两个方向都要添加def bfs(self, s, t):if s == t:print(s)returnvisited = [False] * self.v     # 标记每个节点是否访问过visited[s] = Truequeue = deque()queue.append(s)prev = [-1] * self.v           # 用于记录路径,prev[i] 表示访问 i 节点的前一个节点while queue:w = queue.popleft()for q in self.adj[w]:if not visited[q]:prev[q] = wif q == t:self._print_path(prev, s, t)returnvisited[q] = Truequeue.append(q)print("No path found.")def dfs(self, s, t):self.found = Falsevisited = [False] * self.vprev = [-1] * self.vself._recur_dfs(s, t, visited, prev)if self.found:self._print_path(prev, s, t)else:print("No path found.")def _recur_dfs(self, w, t, visited, prev):    # DFS的递归辅助函数if self.found:returnvisited[w] = Trueif w == t:self.found = Truereturnfor q in self.adj[w]:if not visited[q]:prev[q] = wself._recur_dfs(q, t, visited, prev)def _print_path(self, prev, s, t):    # 打印从 s 到 t 的路径,基于 prev 反向回溯。if prev[t] != -1 and t != s:self._print_path(prev, s, prev[t])print(t, end=' ')

1.2. 广度优先搜索(BFS)

BFS的定义:

广度优先搜索(Breadth-First-Search),简称为 BFS。它其实就是一种“地毯式”层层推进的搜索策略,即先查找离起始顶点最近的,然后是次近的,依次往外搜索。

核心辅助变量:

  1. visited是用来记录已经被访问的顶点,用来避免顶点被重复访问。如果顶点 q 被访问,那相应的 visited[q] 会被设置为 true。
  2. queue是一个队列,用来存储已经被访问、但相连的顶点还没有被访问的顶点。因为广度优先搜索是逐层访问的,也就是说,我们只有把第 k 层的顶点都访问完成之后,才能访问第 k+1 层的顶点。当我们访问到第 k 层的顶点的时候,我们需要把第 k 层的顶点记录下来,稍后才能通过第 k 层的顶点来找第 k+1 层的顶点。所以,我们用这个队列来实现记录的功能。
  3. prev用来记录搜索路径。当我们从顶点 s 开始,广度优先搜索到顶点 t 后,prev 数组中存储的就是搜索的路径。不过,这个路径是反向存储的。prev[w] 存储的是,顶点 w 是从哪个前驱顶点遍历过来的。比如,我们通过顶点 2 的邻接表访问到顶点 3,那 prev[3] 就等于 2。为了正向打印出路径,我们需要递归地来打印,你可以看下 print() 函数的实现方式。

时间和空间复杂度:

V 表示顶点的个数,E 表示边的个数。

  • 时间复杂度:O(V + E) ,简写为 O(E)

对于一个连通图来说,也就是说一个图中的所有顶点都是连通的,E 肯定要大于等于 V-1,所以,广度优先搜索的时间复杂度也可以简写为 O(E)

  • 空间复杂度:O(V)

1.3. 深度优先搜索(DFS)

DFS的概念:

  • 类似“走迷宫”;
  • 一路走到底,走不通就回退,再尝试其他路径;
  • 非最短路径,但能遍历所有可能路径。

特点:

  • 用递归方式实现,体现回溯思想;
  • 辅助变量同 BFS,额外用 found 控制递归终止。

时间和空间复杂度:

  • 时间复杂度: O(E)
  • 空间复杂度:O(V)

BFS vs DFS:

特性

BFS

DFS

搜索策略

按层次,逐层推进

一路深入,回退再尝试

是否找最短路径

✅ 是

❌ 不一定

实现方式

通常用队列实现

通常用递归或栈实现

时间复杂度

O(V + E)

O(V + E)

空间复杂度

O(V)

O(V)

推荐使用场景

路径最短查找、三度好友推荐等

遍历所有可能路径、连通性检

相关文章:

  • 国产芯片LH001-91为什么可以代替TI的ADS1291?
  • 【沉浸式求职学习day40】【java面试题精选2】
  • 哈夫曼树完全解析:从原理到应用
  • 如何使用易路iBuilder智能体平台快速安全深入实现AI HR【实用帖】
  • 设置WDA_EXCLUDEFROMCAPTURE 无效的原因
  • doris节点数量规划
  • 无人机屏蔽与滤波技术模块运行方式概述!
  • Kind方式部署k8s单节点集群并创建nginx服务对外访问
  • 代码随想录算法训练营第四十一天
  • vite运行只能访问localhost解决办法
  • [Harmony]封装一个可视化的数据持久化工具
  • 蓝桥杯12届国B 123
  • 数据结构——例题2
  • [数据结构]8. 树-Tree
  • 基于YOLO算法的目标检测系统实现指南
  • Reactor模型详解与C++实现
  • 虚拟Python 环境构建器virtualenv安装(macOS版)
  • 小白上手RPM包制作
  • Obsidian Callouts标注框语法
  • 【python】字典:: a list of dictionaries
  • 湖北宜化拟斥资超32亿加价回购“弃子”,布局上游煤炭业务
  • 现场丨在胡适施蛰存等手札与文献间,再看百年光华
  • 证券日报:降准今日正式落地,年内或还有降准空间
  • 车载抬头显示爆发在即?业内:凭借市场和产业链优势,国内供应商实现反超
  • 北斗专访|特赞科技范凌:现在AI主要是“说话”,接下来要“干活”了
  • 上海杨浦:鼓励龙头企业与高校共建创新联合体,最高支持200万元