4、广度优先搜索(BFS)

 

一、课程目标

  1. 队列
  2. 广度优先搜索
  3. 算法实现
  4. 求最短路

二、目标详解

1、队列

队列是一种数据结构,只能从队尾加入元素,从队首弹出元素,特性就是先进入队列的元素先出队,简称FIFO(First In First Out)。

c++的stl里提供了队列容器queue,如下:

  • 头文件:#include <queue>
  • 变量:queue<int> q;
  • 入队:q.push(x); //插入x到队尾
  • 出队:q.pop(); //删除队首的元素(没有获取)
  • 访问:q.front(); //访问对首的元素
  • 判空:q.empty();
  • 个数:q.size();

2、广度优先搜索

从某个顶点v0出发,依次访问其相邻的每个点,然后逐层向外访问,直到没有可访问点(或找到解)为止。

上图从A点出发进行bfs遍历(蓝色字表示访问顺序):

  • 访问A点(出队),邻接点有B、F、G,入队后队列为BFG
  • 访问B点(出队),邻接点有C、D,入队后队列为FGCD
  • 访问F点(出队),邻接点无,队列为GCD
  • 访问G点(出队),邻接点为D、H,入队后队列为CDH(D重复不再入队)
  • 访问C点(出队),邻接点无,队列为DH
  • 访问D点(出队),邻接点为E,入队后队列为HE
  • 访问H点(出队),邻接点无,队列为E
  • 访问E点(出队),邻接点无,队列为空
  • 循环结束

bfs遍历序列为:ABFGCDHE

可以发现,整个遍历过程是分层进行的,先遍历距离为1的所有顶点,再距离为2的所有顶点,···,直到访问完毕。在距离为x的层未访问完成之前,不会访问距离为x+1的层。

层次结构如下图:

3、算法实现

伪代码:

bfs()
  起点入队
  while (队列不空)
    访问队首元素、出队
    for 队首元素相邻结点
      入队并标记

使用stl的queue容器:

void bfs(int v0) {
  queue<int> q;
  vis[v0] = true;
  q.push(v0);
  while(!q.empty()) {
    int tmp = q.front();
    cout<<tmp;
    q.pop();
    for(tmp的所有邻接点i) {
      if(vis[i]) continue;
      vis[i] = true;
      q.push(i);
    }
  }
}

4、求最短路

三、扩展理解-dfs与bfs

1、广搜的理解

你的眼镜掉了,你趴在地板上找,先摸一圈最近的地方,如果没有,再往远一点摸过去…..

2、空间复杂度

dfs占用的是栈的空间(因为递归),每次遍历需要占用等于路径深度的栈空间。

bfs占用的是队列的空间,每次遍历需要占用等于邻接点数目的队列空间。

从空间复杂度来说:

  • 链状图:bfs好于dfs,用bfs的空间占用只有1个,而dfs就要占用链深度大小的空间。
  • 星状图:dfs好于bfs,用bfs的空间占用邻接点数目大小,而dfs只有一层深度。

3、应用场景

bfs适合用于找一条最短路径(无权图),既一个最优解,也可以理解成一种贪心策略。

dfs使用找所有(最短)路径,既遍历所有的解空间,进行判定,也可以理解成枚举策略。

问题:为什么说bfs使用找无权图的最短路径?

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值