(图论)广度优先搜索(Breadth First Search, BFS)

描述

最简单、直接的图搜索算法:

  • 从起点开始层层扩展
    • 第一层是离起点距离为1的
    • 第二层是离起点距离为2的
  • 本质就是按层(距离)扩展,无回退。

BFS算法分析

1、算法流程:

1、给定某起点 a ,将 a 放入缓冲区,开始搜索;
2、过程:假定某时刻缓冲区内的节点为 a b c abc ,则访问节点 a a 的邻接点 a 1 a 2 a 3 a_1 a_2 a_3 ,同时缓冲区变成 b c a 1 a 2 a 3 bca_1 a_2 a_3 ,为下一次访问做准备。

  • 从上述流程分析,需要把队列作为辅助数据结构,因为队列具有先进先出的特点,从队尾入队,从队首出队,只有队首元素可见。

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 判重,如果 y 是新节点,则入队 q;
      • 同时,记录步数 d[y] = d[x] + 1;
      • 前驱 pre[y] = x;

3、对BFS的改进——双向BFS

从起点和终点分别走,直到相遇,即将单向BFS的树形结构变为了纺锤形结构。
在经典的BFS中,树形搜索结构若树的高度非常高时,叶子非常多(树的宽度大),而通过把一颗高度为h的树用两个近似 h 2 \frac h2 的树代替,宽度相对较小。

猜你喜欢

转载自blog.csdn.net/xhj_enen/article/details/88549595