算法学习(十五)广度优先

广度优先

1. 概念

1、又叫层次遍历,从上往下对每一层依次访问,在每一层中,从左往右(也可以从右往左)访问结点,访问完一层就进入下一层,直到没有结点可以访问为止
2、保留全部结点,占用空间大; 无回溯操作(即无入栈、出栈操作),运行速度快。
3、一般需存储产生的所有结点,占用的存储空间要比深度优先搜索大得多,因此,程序设计中,必须考虑溢出和节省内存空间的问题

广度优先算法的核心思想是:从初始节点开始,应用算符生成第一层节点,检查目标节点是否在这些后继节点中,若没有,再用产生式规则将所有第一层的节点逐一扩展,得到第二层节点,并逐一检查第二层节点中是否包含目标节点。若没有,再用算符逐一扩展第二层的所有节点……,如此依次扩展,检查下去,直到发现目标节点为止。即

  1. 从图中的某一顶点V0开始,先访问V0;
  2. 访问所有与V0相邻接的顶点V1,V2,…,Vt;
  3. 依次访问与V1,V2,…,Vt相邻接的所有未曾访问过的顶点;
  4. 循此以往,直至所有的顶点都被访问过为止。
    这种搜索的次序体现沿层次向横向扩展的趋势,所以称之为广度优先搜索。

2. 解题技巧(我的总结)

1> 拓扑排序,课程表问题
每一次都从图中删除没有前驱的顶点,这里并不需要真正的做删除操作,我们可以设置一个入度数组,
每一轮都输出入度为 000 的结点,并移除它、修改它指向的结点的入度(−1-1−1即可),依次得到的
结点序列就是拓扑排序的结点序列。如果图中还有结点没有被移除,则说明“不能完成所有课程的学习”。

1、在开始排序前,扫描对应的存储空间(使用邻接表),将入度为 0 的结点放入队列。
2、只要队列非空,就从队首取出入度为 000 的结点,将这个结点输出到结果集中,并且将这个结点的所有邻接结点(它指向的结点)的入度减 1,在减 1 以后,如果这个被减 1 的结点的入度为 0 ,就继续入队。
3、当队列为空的时候,检查结果集中的顶点个数是否和课程数相等即可。
思考这里为什么要使用队列?(马上就会给出答案。)
在代码具体实现的时候,除了保存入度为 0 的队列,我们还需要两个辅助的数据结构:
1、邻接表:通过结点的索引,我们能够得到这个结点的后继结点;
2、入度数组:通过结点的索引,我们能够得到指向这个结点的结点个数。
这个两个数据结构在遍历题目给出的邻边以后就可以很方便地得到。
题目说明实现
207. 课程表队列存放入度为0的节点我的提交
310. 最小高度树从叶子节点向根节点不断扩散到只剩一个(或者多个)我的提交

2> 双向广度优先搜索,优化时间复杂度

题目说明实现
127. 单词接龙leftVisited和rightVisited分别记录左右访问的节点,选取startWord和endWord中邻居少的节点开始扩散我的提交
2359. 找到离给定两个节点最近的节点双向同步扩散直到有交集为止我的提交
752. 打开转盘锁leftVisited和rightVisited分别记录左右访问的节点,选取left和right中邻居少的节点开始扩散我的提交

3> 广度优先搜索求最短路径,距离等问题,学会剪枝

题目说明实现
488. 祖玛游戏经分析,只有 相同序列的右端插入相同球(简化),或相同序列的中间插入不同球 两种选择是有效的(保留备用)我的提交

3. 更多练习

4. 参考

  1. 大部分参考自:算法基础——枚举
  2. 总库:tryHard
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值