描述
最简单、直接的图搜索算法:
- 从起点开始层层扩展
- 第一层是离起点距离为1的
- 第二层是离起点距离为2的
- …
- 本质就是按层(距离)扩展,无回退。
BFS算法分析
1、算法流程:
1、给定某起点 a ,将 a 放入缓冲区,开始搜索;
2、过程:假定某时刻缓冲区内的节点为
a
b
c
abc
abc,则访问节点
a
a
a 的邻接点
a
1
a
2
a
3
a_1 a_2 a_3
a1a2a3,同时缓冲区变成
b
c
a
1
a
2
a
3
bca_1 a_2 a_3
bca1a2a3,为下一次访问做准备。
- 从上述流程分析,需要把队列作为辅助数据结构,因为队列具有先进先出的特点,从队尾入队,从队首出队,只有队首元素可见。
3、节点判重:
- 如果在扩展过程中,发现某节点在前期已经访问过,则本次不再访问该节点;显然,第一次访问到该节点时,是访问次数最少的。
4、路径记录
- 一个节点可能扩展出多个节点:多后继;但是任意一个节点最多只可能有一个前驱(起始节点没有前驱):单前驱。
- 用和节点数目等长的数组 pre[0…N-1]
- pre[i] = j:第 i 个节点的前一个节点是 j (用到存索引而不存数据本身的思路)
2、算法框架
辅助数据结构
- 队列q:用于缓存访问的节点
- d[0…N-1]:用于记录步数(即节点是第几次被访问到的)
- pre[0…N-1]:节点的前驱
算法描述
- 起点 start 进入队列 q
- 记录步数 d[start] = 0;
- 记录 start 的前驱 pre[start] = -1;
- 如果队列 q 非空,则队首节点 x 出队,尝试扩展 x:
- 找到 x 的邻接点集合
{
y
∣
(
x
,
y
)
∈
E
}
\{y|(x, y)\in E\}
{y∣(x,y)∈E}
- 对每个新扩展节点 y 判重,如果 y 是新节点,则入队 q;
- 同时,记录步数 d[y] = d[x] + 1;
- 前驱 pre[y] = x;
- 找到 x 的邻接点集合
{
y
∣
(
x
,
y
)
∈
E
}
\{y|(x, y)\in E\}
{y∣(x,y)∈E}
3、对BFS的改进——双向BFS
从起点和终点分别走,直到相遇,即将单向BFS的树形结构变为了纺锤形结构。
在经典的BFS中,树形搜索结构若树的高度非常高时,叶子非常多(树的宽度大),而通过把一颗高度为h的树用两个近似
h
2
\frac h2
2h的树代替,宽度相对较小。