【数据结构与算法】广度优先搜索(BFS)

时间:2020-04-25
本文章向大家介绍【数据结构与算法】广度优先搜索(BFS),主要包括【数据结构与算法】广度优先搜索(BFS)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

  广度优先搜索算法:先查找离起始顶点最近的,然后是第二进的,这样依次往外搜索。树的层次遍历就是一个广度搜索算法。

  一般需要用到队列这个数据结构,但是如果你是C语言开发,并且是在考试中,时间有限。一般临时写一个队列出来还是很耗时间的,所以一般用一个大数组来模拟队列

根据百度百科:广度优先搜索算法在求解最短路径或者最短步数上有很多的应用。应用最多的是在走迷宫上。

今天做了两道力扣题目,总结一下BFS的套路:

第一题: 542. 01 矩阵

C代码实现:

 1 /* 广度优先: 用大数组实现队列 */
 2 #define MAX_SIZE 10000
 3 int numSquares(int n)
 4 {
 5     int queue[MAX_SIZE] = {0};
 6     int front = 0; // 队首
 7     int rear = 0; // 队尾
 8     int size = 0; // 当前队列中元素的个数
 9     int visit[MAX_SIZE] = {0}; // visit[i]表示元素i是否已经访问过
10 
11     // 初始化队列
12     queue[0] = n;
13     rear++;
14     visit[n] = 1;
15     int result = 0;
16     while (front < rear) { // 循环终止的条件是队列为空
17         size = rear - front;
18         result++; // 每循环一轮,说明遍历了一层,离答案就近了一层
19         for (int i = 0; i < size; i++) {
20             int topElem = queue[front]; // 队首元素出队列
21             front++;
22             for (int j = 1; j * j <= topElem; j++) {
23                 int nextElem = topElem - j * j;
24                 if (nextElem == 0) {
25                     return result;
26                 }
27                 // 入队列
28                 if (visit[nextElem] != 1) {
29                     visit[nextElem] = 1;
30                     queue[rear++] = nextElem;
31                 }
32             }
33         }
34     }
35     return result;
36 }
View Code

第二题:490. 迷宫

C代码实现:

 1 typedef struct tagPos {
 2     int rowIndex;
 3     int colIndex;
 4 } Pos;
 5 
 6 bool hasPath(int** maze, int mazeSize, int* mazeColSize, int* start, int startSize, int* destination, int destinationSize){
 7     int rowSize = mazeSize;
 8     int colSize = mazeColSize[0];
 9     int visit[rowSize][colSize];
10     for (int i = 0; i < rowSize; i++) {
11         for (int j = 0; j < colSize; j++) {
12             visit[i][j] = 0;
13         }
14     }
15     int max_size = rowSize * colSize;
16     Pos queue[max_size];
17     int front = 0;
18     int rear = 0;
19    // int size;
20     queue[0].rowIndex = start[0];
21     queue[0].colIndex = start[1];
22     rear++;
23     visit[start[0]][start[1]] = 1;
24     int direct[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
25     while (front < rear) {
26         Pos curr = queue[front];
27         front++;
28         if (curr.rowIndex == destination[0] && curr.colIndex == destination[1]) {
29             return true;
30         }
31         for (int i = 0; i < 4; i++) {
32             int x = curr.rowIndex + direct[i][0];
33             int y = curr.colIndex + direct[i][1];
34             while (x >= 0 && x < rowSize && y >= 0 && y < colSize && maze[x][y] == 0) {
35                 printf("go on, x:%d, y%d  ", x, y);
36                 x += direct[i][0];
37                 y += direct[i][1];
38             }
39             /* 走到这里x, y如果是有效的。那么maze[x][y]一定为 1
40              * 所以需要按照原来的方向退一格。所以是:
41              * x -= direct[i][0] y -= direct[i][1];
42              * 然后再判断移位之后x,y 的情况
43              */
44             x -= direct[i][0];
45             y -= direct[i][1];
46             if (x >= 0 && x < rowSize && y >= 0 && y < colSize && visit[x][y] != 1) {
47                 queue[rear].rowIndex = x;
48                 queue[rear].colIndex = y;
49                 printf("keep: x:%d, y:%d\n", x, y);
50                 rear++;
51                 visit[x][y] = 1;
52             }
53         }
54     }
55     return false;
56 }
View Code

总结:

经过上面两道题,看到别人总结了BFS的套路,现摘抄如下:

BFS 使用队列,把每个还没有搜索到的点依次放入队列,然后再弹出队列的头部元素当做当前遍历点。BFS 总共有两个模板:

1、如果不需要确定当前遍历到了哪一层,BFS 模板如下。

1 while queue 不空:
2     cur = queue.pop()
3     for 节点 in cur的所有相邻节点:
4         if 该节点有效且未访问过:
5             queue.push(该节点)
View Code

2、

如果要确定当前遍历到了哪一层,BFS 模板如下。
这里增加了 level 表示当前遍历到二叉树中的哪一层了,也可以理解为在一个图中,现在已经走了多少步了。size 表示在当前遍历层有多少个元素,也就是队列中的元素数,我们把这些元素一次性遍历完,即把当前层的所有元素都向外走了一步。

 1 level = 0
 2 while queue 不空:
 3     size = queue.size()
 4     while (size --) {
 5         cur = queue.pop()
 6         for 节点 in cur的所有相邻节点:
 7             if 该节点有效且未被访问过:
 8                 queue.push(该节点)
 9     }
10     level ++;
View Code

参考资料:

(1) : https://leetcode-cn.com/problems/01-matrix/solution/tao-lu-da-jie-mi-gao-dong-ti-mu-kao-cha-shi-yao-2/

原文地址:https://www.cnblogs.com/LydiammZuo/p/12774490.html