BFS算法的优化 双向宽度优先搜索
双向宽度优先搜索 (Bidirectional BFS) 算法适用于如下的场景:
- 无向图
- 所有边的长度都为 1 或者长度都一样
- 同时给出了起点和终点
以上 3 个条件都满足的时候,可以使用双向宽度优先搜索来求出起点和终点的最短距离。
算法描述
双向宽度优先搜索本质上还是BFS,只不过变成了起点向终点和终点向起点同时进行扩展,直至两个方向上出现同一个子节点,搜索结束。我们还是可以利用队列来实现:一个队列保存从起点开始搜索的状态,另一个保存从终点开始的状态,两边如果相交了,那么搜索结束。起点到终点的最短距离即为起点到相交节点的距离与终点到相交节点的距离之和。
Q.双向BFS是否真的能提高效率?
假设单向BFS需要搜索 N 层才能到达终点,每层的判断量为 X,那么总的运算量为 X ^ NXN. 如果换成是双向BFS,前后各自需要搜索 N / 2 层,总运算量为 2 * X ^ {N / 2}2∗XN/2。如果 N 比较大且X 不为 1,则运算量相较于单向BFS可以大大减少,差不多可以减少到原来规模的根号的量级。
from collections import deque def doubleBFS(start, end):
if start == end:
return 1 # 分别从起点和终点开始的两个BFS队列
startQueue, endQueue = deque(), deque()
startQueue.append(start)
endQueue.append(end)
step = 0 # 从起点开始和从终点开始分别访问过的节点集合
startVisited, endVisited = set(), set()
startVisited.add(start)
endVisited.add(end)
while len(startQueue) and len(endQueue):
startSize, endSize = len(startQueue), len(endQueue)
# 按层遍历
step += 1
for _ in range(startSize):
cur = startQueue.popleft()
for neighbor in cur.neighbors:
if neighbor in startVisited: # 重复节点
continue
elif neighbor in endVisited: # 相交
return step
else:
startVisited.add(neighbor)
startQueue.append(neighbor)
step += 1
for _ in range(endSize):
cur = endQueue.popleft()
for neighbor in cur.neighbors:
if neighbor in endVisited:
continue
elif neighbor in startVisited:
return step
else:
endVisited.add(neighbor)
endQueue.append(neighbor) return -1
学习建议
Bidirectional BFS 掌握起来并不是很难,算法实现上稍微复杂了一点(代码量相对单向 BFS 翻倍),掌握这个算法一方面加深对普通 BFS 的熟练程度,另外一方面,基本上写一次就能记住,如果在面试中被问到了如何优化 BFS 的问题,Bidirectional BFS 几乎就是标准答案了。
参考资料
https://www.geeksforgeeks.org/bidirectional-search
应用例题
Shortest Path in Undirected Graph
Knight Shortest Path
Knight Shortest Path II
BFS算法的优化 双向宽度优先搜索的更多相关文章
- 【算法入门】广度/宽度优先搜索(BFS)
广度/宽度优先搜索(BFS) [算法入门] 1.前言 广度优先搜索(也称宽度优先搜索,缩写BFS,以下采用广度来描述)是连通图的一种遍历策略.因为它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较 ...
- 算法基础⑦搜索与图论--BFS(宽度优先搜索)
宽度优先搜索(BFS) #include<cstdio> #include<cstring> #include<iostream> #include<algo ...
- 层层递进——宽度优先搜索(BFS)
问题引入 我们接着上次“解救小哈”的问题继续探索,不过这次是用宽度优先搜索(BFS). 注:问题来源可以点击这里 http://www.cnblogs.com/OctoptusLian/p/74296 ...
- 【BFS宽度优先搜索】
一.求所有顶点到s顶点的最小步数 //BFS宽度优先搜索 #include<iostream> using namespace std; #include<queue> # ...
- 搜索与图论②--宽度优先搜索(BFS)
宽度优先搜索 例题一(献给阿尔吉侬的花束) 阿尔吉侬是一只聪明又慵懒的小白鼠,它最擅长的就是走各种各样的迷宫. 今天它要挑战一个非常大的迷宫,研究员们为了鼓励阿尔吉侬尽快到达终点,就在终点放了一块阿尔 ...
- 挑战程序2.1.5 穷竭搜索>>宽度优先搜索
先对比一下DFS和BFS 深度优先搜索DFS 宽度优先搜索BFS 明显可以看出搜索顺序不同. DFS是搜索单条路径到 ...
- [宽度优先搜索] FZU-2150 Fire Game
Fat brother and Maze are playing a kind of special (hentai) game on an N*M board (N rows, M columns) ...
- 宽度优先搜索--------迷宫的最短路径问题(dfs)
宽度优先搜索运用了队列(queue)在unility头文件中 源代码 #include<iostream>#include<cstdio>#include<queue&g ...
- "《算法导论》之‘图’":深度优先搜索、宽度优先搜索(无向图、有向图)
本文兼参考自<算法导论>及<算法>. 以前一直不能够理解深度优先搜索和广度优先搜索,总是很怕去碰它们,但经过阅读上边提到的两本书,豁然开朗,马上就能理解得更进一步. 下文将会用 ...
随机推荐
- SQL2008R2下数据库修复一例
某天访问某个数据库的时候,系统报错.连上去看了一下,服务器是SQL2008R2.由于有上次修复的经验,先使用DBCC查看数据库情况. DBCC的返回: XXXXXXXXXXX发生异常数据库 ID 7, ...
- 2018-2019-2 20165315《网络对抗技术》Exp9 Web安全基础
2018-2019-2 20165315<网络对抗技术>Exp9 Web安全基础 目录 一.实验内容 二.实验步骤 1.Webgoat前期准备 2.SQL注入攻击 Command Inje ...
- [技术博客] Springboot的Controller类使用
Springboot的Controller类使用 @Controller:处理http请求. 代码: @Controller public class QuestionController { ... ...
- Spring配置中<bean>的id和name属性
在BeanFactory的配置中,<bean>是我们最常见的配置项,它有两个最常见的属性,即id和name,最近研究了一下,发现这两个属性还挺好玩的,特整理出来和大家一起分享. 1.id属 ...
- PostgreSQL 缓存
PostgreSQL physical storage和 inter db 值得阅读 数据在物理介质上存储是以page的形式,大小为8K,如下: a tuple或an item是行的同义词 a ...
- MyEclipse部署外部引用的jar到web-inf的lib目录下
在用MyEclipse开发java web项目的时候,引入了外部jar,都是以library的形式存在左边的explore中的,调试没有问题,但是部署之后呢,经常遇到个非常头疼的问题就是,这些jar不 ...
- Angular的Observable可观察对象(转)
原文:https://blog.csdn.net/qq_34414916/article/details/85194098 Observable 在开始讲服务之前,我们先来看一下一个新东西——Obse ...
- nginx 反向代理Jenkins
进入nginx 配置文件 cd /root/nginx/conf 找到nginx.conf 修改server块内容: server { listen 80; ...
- Python3.x--33个保留字
查询方法也在下图:
- Django(一)初始
一:Web开发中的基本术语 1.两种架构 (1)cs架构 Client/Server:客户端-服务端架构 优点:CS能充分发挥客户端PC的处理能力,很多工作可以在客户端处理后在提交给服务器,用户体验好 ...