《算法笔记》—— "迷宫求解" 之 广度优先搜索(BFS) - Go语言中文社区

《算法笔记》—— "迷宫求解" 之 广度优先搜索(BFS)


迷宫相关算法文章:
《算法笔记》—— “迷宫求解” 之 深度优先搜索(DFS)

BFS 用到了队列的知识,什么是队列,这里我就不说了 . . .
BFS 与 DFS 不一样的是,BFS 是针对于层面上的,一层一层的通过队列来筛选 . . .


我们还是以 BFS中的迷宫为例来讲解 BFS的使用.
BFS 求解迷宫是将当前点的所有可能性放入队列之中(入队),然后再去掉队列的头部(出队)…

例如下图所示:

在这里插入图片描述

在这里插入图片描述

BFS 思想解析:

首先我们将 (0,0)点加入队列,此时该点是队列的头,然后我们将该点四个方向所有的点都加入队列之中,出了迷宫的点、障碍物或者是已经加入队列的点不算,之后把队头去掉,以下一个新的队头继续开始遍历,直至找到终点为止 . . .

队列图所示:

首先将起点作为队头,然后将四个方向的点入队
在这里插入图片描述

队头出队,队头的下一个元素作为队头

在这里插入图片描述

下面我来一步一步讲解 BFS的使用方式.

  1. 与 BFS中需要相同的数据
// 地图 
 int map[5][5] = {
	  0 ,0 ,0 ,1 ,1 ,
	  0 ,0 ,0 ,1 ,1 , 
	  0 ,1 ,0 ,0 ,0 ,
	  0 ,0 ,0 ,1 ,1 ,
	  0 ,0 ,0 ,0 ,0
};

int flag[5][5] = { 0 };  // 标记是否走过的路

// 方向 
int direction[4][2] = {
	  0, 1,
	  1, 0,
	  0, -1,
	  -1, 0
};
  1. 声明队列的元素类型
struct note  // 队列中的元素类型 
{
    int x;   // 行下标
    int y;   // 列一标
};
  1. 定义队列,并初始化队头的元素
struct note que[25];
int head = 0;    // 队列的头部索引 
int tail = 0;    // 队列的尾部索引 

// 初始化每一个队列元素的值(开始寻找的地方)
que[head].x = que[head].y = 0;   
tail++;  	 // 尾部索引 + 1
flag[0][0] = 1;  // 标记初始位置已经查找过了
  1. 核心部分,开始 BFS
while(head < tail)  // 队列永远都有数据
{
    int i = 0;
    for(; i < 4; i++)	// 该点的四个方向
    {
       	// 每次都是以队头为单位向四个方向开始
       	int nx = que[head].x + direction[i][0];   
   	int ny = que[head].y + direction[i][1];
   	
   	// 判断该点的坐标是否满足要求
   	if(nx < 0 || nx > 4 || ny < 0 || ny > 4)
    		continue;
   	
   	if(map[nx][ny] == 0 && flag[nx][ny] == 0)
   	{
    		flag[nx][ny] = 1; 
    		que[tail].x = nx;     // 加入队列 
    		que[tail].y = ny;
    		tail++;    
   	}
   	
   	if(nx == 4 && ny == 4)	      // 判断是否找到终止了
   	{
    		printf("Yes, I found it !");
    		return 0;
   	}
    }
  
    head++;		// 队头已经失去意义了,开始下一点的循环

}

BFS核心的思想就是队列的使用,层级原理,和二叉树的层级遍历一个方式 . . .
此处可以看看我一篇文章:红黑树基本功能 —— C++实现

.

下面来展示完整的 BFS源码:

#include <stdio.h>
struct note  // 队列中的元素类型 
{
	int x;
 	int y; 
}; 

int main()
{
 	// 地图 
 	int map[5][5] = {
		  0 ,0 ,0 ,1 ,1 ,
		  0 ,0 ,0 ,1 ,1 , 
		  0 ,1 ,0 ,0 ,0 ,
		  0 ,0 ,0 ,1 ,1 ,
		  0 ,0 ,0 ,0 ,0
	};
	
	int flag[5][5] = { 0 };  // 标记是否走过的路
 	
 	// 方向 
 	int direction[4][2] = {
		  0, 1,
		  1, 0,
		  0, -1,
		  -1, 0
	}; 
	
	struct note que[25];	// 队列
 	
 	int head = 0;   // 队列的头部索引 
 	int tail = 0;   // 队列的尾部索引 
 	
 	// 初始化每一个队列元素的值(开始寻找的地方)
 	que[head].x = que[head].y = 0;   
 	tail++;  // 尾部索引 + 1
 	flag[0][0] = 1;  // 标记初始位置已经查找过了
 
 	while(head < tail) 
 	{
  		int i = 0;
  		for(; i < 4; i++)
  		{
   			// 每次都是以队头为单位向四个方向开始
   			int nx = que[head].x + direction[i][0];   
 			int ny = que[head].y + direction[i][1];
   			
   			if(nx < 0 || nx > 4 || ny < 0 || ny > 4)
    				continue;
   			
   			if(map[nx][ny] == 0 && flag[nx][ny] == 0)
   			{
    				flag[nx][ny] = 1; 
    				que[tail].x = nx;     // 加入队列 
    				que[tail].y = ny;
    				tail++;    
   			}
   			
   			if(nx == 4 && ny == 4)
   			{
    				printf("Yes, I found it !");
    				return 0;
   			}
  		}
  		
  		head++;
 	}
 	
 	return 0;
}

运行程序结果如下图所示:

在这里插入图片描述

当我们把终点周围的点都换成障碍物时,结果如下:

在这里插入图片描述

好了,你们快去试试吧,BFS 和 DFS可以求解出很多的问题,比如人工智能贪吃蛇、连连看等等 . . .

.


作者:浪子花梦

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_42100963/article/details/105407923
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-04-18 20:27:15
  • 阅读 ( 1114 )
  • 分类:算法

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢