BFS定义:宽度优先搜索 Breath First Search。
BFS作用:遍历图或树,或搜索目标结点,或求到目标结点的最短路径。
BFS思想:每一次以当前结点为基准,只向周围扩展一层(即相邻的结点),再不断通过这些结点,进一步扩展距离为一层的结点,从而完成整个图的搜索。
使用场景:求到达状态的最少步骤,走迷宫,拓扑排序
当bfs来求一个图的最短路径:
从起始状态不断转移到最终状态的最短路径
在转移过程中所用到的数据结构:
- 队列结构:用于实施整个bfs搜索拓展路径的过程,通过进队+出队+判断,从而保证不会进行重复的搜索
- 距离存储:如果用bfs来搜索最短路的话,则每一条边的权重需要是相同的,需要有一个距离结构来表示当前已经走过的路的距离。如果每个结点的表示比较简单,比如用int表示,则可以使用一个数组即可,如果比较复杂,可以考虑使用哈希表unordered_map
bfs解决应用题的核心思想:
我们将每个具体的应用题进行抽象,每个状态即为图中的一个结点,那么我们要求到达一种状态的最少步骤,即求出该图中从起点到达该状态结点的最短路径。
bfs解决最短路径问题的难点:结点的状态表示
在解决bfs搜寻最短路的问题时,最主要的就是考虑上方的queue和distance的数据结构存储问题。接下来要考虑的难点在于如何将这些数据结构的状态恢复到原始状态,从而完成路径的拓展。
完成路径拓展分为两步
- 取出队头元素,并出队pop
- 依据该队头元素,将状态还原成题目本身的形式,完成对路径的拓展
- 在路径拓展过程中,进行对新结点的判断(是否已经入队?是否入队过?),满足条件的进行入队处理,直到寻找到终止状态。
代码编写思路:
Bfs()
{
- Queue创建并完成初始化,入队
- While循环,进行队列操作
{
取队头,出队
判断是否达到终止条件
拓展路径(注:由于一次可能要拓展多条路径,因此遍历时注意还原状态)
}
结果不存在,return error
}
常见的状态数据结构和对应的距离数据结构
- 二维图:typedef pair<int, int> P;二维数组d[N][N];
- 字符串:string;哈希表 unordered_map<string, int> d;
额外拓展:
find查找函数:t.find(‘x’);
在C++中也是通过string来调用find函数。如果有多个需要查找的值,往往返回的是第一个被找到的下标,若想找后面的,可以在find后面加上一个参数k,表明从下标k处开始找。
hash.count(key):该函数:用以统计key值在unordered_map中出现的次数。c++ unordered_map不允许有重复的key。因此,如果key存在,则count返回1,如果不存在,则count返回0。