zoukankan      html  css  js  c++  java
  • 【数据结构与算法】广度优先搜索1

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

      一般需要用到队列这个数据结构,但是如果你是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
    ", 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/

  • 相关阅读:
    QMainWindow透明背景
    在Xcode中产看QString的数据
    使用QtConcurrent在线程池中执行网络操作
    QThread和QObject的调用方法总结
    策略模式 C++实现
    【转】单元测试要做多细?
    Mac系统添加QQ邮箱帐号提示无法验证
    Qt半透明对话框
    SVD的几何意义,以及在去噪,推荐系统中的应用
    BP神经网络原理及python实现
  • 原文地址:https://www.cnblogs.com/LydiammZuo/p/12774490.html
Copyright © 2011-2022 走看看