“ 探索迷局:解密广度寻路算法 “(一)

简介: “ 探索迷局:解密广度寻路算法 “

目录


  • 1、介绍
  • 2、思想
  • 3、定义及快捷
  • 4、创建四叉树节点
  • 5、判断能不能走
  • 6、准备工作
  • 7、寻路
  • A、标记走过
  • B、对预测点进行移动处理
  • C、能走的情况下怎么处理
  • D、切换层数
  • 8、效果展示
  • 9、综合代码
  • 10、总结


正文


1、介绍

广度寻路算法是一种基于图的搜索算法,用于寻找两个节点之间的最短路径。它从起点开始展开搜索,并逐步向外扩展,直到找到目标节点或所有节点都被访问过。广度寻路算法使用队列作为辅助数据结构来实现搜索。当一个节点被访问时,将其所有的邻居节点加入队列中,并标记为已访问。从队列中取出的节点继续进行扩展搜索,直到队列为空或目标节点被找到为止。广度寻路算法的时间复杂度为O(V+E),其中V为节点数,E为边数。由于它逐层扩展搜索,因此能够找到最短路径,但会占用较多的空间。需要源代码的私信我~

深度寻路算法:1.循环试探,遇到死胡同回退 2.循环 简单 3.不一定能找到最佳路径 4.空旷地形 深度寻路

广度寻路算法:

1. 不需要回退

2. 一定能找到最短路径


2、思想


112.png


深度寻路就好比猴哥的毫毛一样,直接派四个小兵分别去上下左右四个方位寻找,到达下一个位置时,再派四个小兵出去寻找(当然如果有的方向是障碍物,那就不用派人去了),就这样一直下去,最后会找到终点的,而且是最短路径(后面会解释为什么)

可能有的同学会问了,那要怎么实现呐,每次都要派四个小兵,而且有的不是障碍物的要一直寻路下去,这个时候我们就想到了四叉树来实现,把起点放入根节点,一层就代表一步

有的同学又会问了,那如果一张地图有很多条路径,那广度寻路怎么会找到最短的那一条路径?

其实思想很简单,就是一找到终点就结束循环,从终点往上遍历,这条路径一定是最短路径——因为这条路径是最先结束循环,即最先找到终点


3、定义及快捷


在开始写之前我们先把准备工作写好,比如行和列的定义,最大孩子的数量,因为是试探4个方向,所以最大孩子的数量为4,且这里定义的是四叉树,存储当前层和下一层节点地址的数组大小,地图中路和障碍物的枚举,上下左右方向的枚举,还要定义一个点类型,以及四叉树类型,四叉树中需要定义结构体数组,因为有四个孩子,还有一个重要的是定义当前孩子的数量,因为不仅父亲要指向孩子,孩子也还要指向父亲,因为最后确定最佳路径,还要从终点往上遍历

//行列
#define ROWS 10
#define COLS 10
//最大孩子数量
#define CHILD_NUM 4
//临时数组的最大容量
#define BUFF_SIZE 100
//地图枚举
enum Mymap{road,wall};
//方向枚举
enum Mydirect{p_up,p_left,p_down,p_right};
//点
typedef struct Mypoint 
{
  int row, col;
}Mypoint;
//四叉树节点类型
typedef struct myThree 
{
  Mypoint     pos;
  struct myThree* partent;
  struct myThree* Child[CHILD_NUM];
  int       Curchild_Num;  
}myThree;
#define SIZE sizeof(myThree)


4、创建四叉树节点


这里先是直接用快捷的方式,把四叉树中都初始化为0,然后再赋值点的坐标

myThree* createThreeNode(Mypoint* pos)
{
  myThree* pNew = malloc(SIZE);
  assert(pNew);
  memset(pNew, 0, SIZE);
  pNew->pos.row = pos->row;
  pNew->pos.col = pos->col;
  return pNew;
}


5、判断能不能走


当前点越界,以及辅助地图上标记过的点,是墙都不能走

bool can_Walk(Mypoint* pos, bool map[ROWS][COLS], bool pathMap[ROWS][COLS])
{
  //越界
  if (pos->row < 0 || pos->row >= ROWS || pos->col < 0 || pos->col >= COLS)     return false;
  //走过
  if (pathMap[pos->row][pos->col]) return false;
  //是墙
  if (map[pos->row][pos->col]) return false;
  return true;
}


6、准备工作


1、简单用数组实现一个二维地图,用于寻路

2、定义起点和终点

3、定义辅助地图,用于标记有没有走过

4、定义两个辅助数组,用来在当前层和下一层之间切换,这两个数组分别是用来存储当前层和下一层节点的地址

5、创建一棵树,起点成为树根,并且根节点还有独占一层

6、准备一个预测点

7、定义isFindend,用来判断是否找到终点,因为寻找的过程是多层循环,一个break结束不了循环,所以定义了一个标记

  //1 地图  1表示障碍  0表示路
  bool map[ROWS][COLS] = 
  {
    { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    { 1, 0, 1, 1, 0, 0, 0, 1, 1, 1 },
    { 1, 0, 1, 1, 0, 1, 0, 1, 1, 1 },
    { 1, 0, 1, 1, 0, 1, 0, 0, 0, 1 },
    { 1, 0, 1, 1, 0, 1, 1, 0, 1, 1 },
    { 1, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
    { 1, 0, 1, 1, 1, 1, 1, 0, 1, 1 },
    { 1, 0, 1, 1, 0, 0, 0, 0, 0, 1 },
    { 1, 0, 1, 0, 0, 1, 1, 1, 0, 1 },
    { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
  };
  //点--起点和终点
  Mypoint begPos = { 1,1 };
  Mypoint endPos = { 8,8 };
  //辅助地图
  bool pathMap[ROWS][COLS] = { 0 };
  //创建一颗树
  myThree* pRoot = NULL;
  //起点成为树根
  pRoot = createThreeNode(&begPos);
  //辅助数组
  //记录当前层节点的地址
  myThree* currentLayer[BUFF_SIZE] = { 0 };
  // 当前层节点的数量
  int currentLayerSize = 0;
  //记录下一层节点的地址
  myThree* nextLayer[BUFF_SIZE] = { 0 };
  //下一层节点的数量
  int nextLayerSize = 0;
  //树的根节点独占一层
  currentLayer[currentLayerSize++] = pRoot;
  //预测点
  Mypoint search;
  //标记是否走到终点
  bool isFindend = false;
  //准备一个临时变量
  myThree* temp_Node = NULL;


7、寻路


寻路的思想前面已经讲过了,我们一层一层的遍历(即一步一步的遍历),然后对每一步的四个方向进行处理

A、标记走过

处理之前,我们还要标记当前点已经走过并且要把当前的孩子数量清空

//标记走过
pathMap[currentLayer[i]->pos.row][currentLayer[i]->pos.col] = true;
//孩子数量清空
currentLayer[i]->Curchild_Num = 0;

B、对预测点进行移动处理

预测点就是当前的点,然后用switch进行处理

//预测点就是当前点
search.row = currentLayer[i]->pos.row;
search.col = currentLayer[i]->pos.col;
switch(j)
{
  case p_up:  search.row--;  break;
  case p_down:  search.row++;  break;
  case p_left:  search.col--;  break;
  case p_right:  search.col++;  break;
}

C、能走的情况下怎么处理

能走的情况下当前点就要成为预测点的父节点,预测点还要成为当前点的孩子,除此之外还要把预测点放入下一层数组中,因为它的身份是预测点,即为当前点的孩子,最后还要判断是否到达终点

//能走
if (can_Walk(&search,map,pathMap))
{
  //创建树节点
  temp_Node = createThreeNode(&search);
  //预测点成为当前点的孩子
  currentLayer[i]->Child[currentLayer[i]->Curchild_Num++] = temp_Node;
  //当前点成为预测点的父亲
  temp_Node->partent = currentLayer[i];
  //放入下一层数组中
  nextLayer[nextLayerSize++] = temp_Node;
  //判断是否到达终点
  if (temp_Node->pos.row==endPos.row&& temp_Node->pos.col == endPos.col)
  {
    isFindend = true;
    break;
  }
}

D、切换层数

如果下一层的数组为空,这时候已经遍历到最后一层了,直接退出,否则切换到下一层

//下一层为空
if (nextLayerSize == 0) break;
//切换到下一层中
for (int i = 0; i < nextLayerSize; i++)
{
  currentLayer[i] = nextLayer[i];
}
currentLayerSize = nextLayerSize;
相关文章
|
5月前
|
算法
互动游戏解决遇到问题之基于射线投射寻路算法的问题如何解决
互动游戏解决遇到问题之基于射线投射寻路算法的问题如何解决
|
6月前
|
Dart 算法 数据可视化
用flutter实现五种寻路算法的可视化效果,快来看看!
半年前我写了一篇有关排序算法可视化的文章,挺有意思,还被张风捷特烈-张老师收录进了FlutterUnit,今天让我们再来做一个有关寻路算法的可视化效果吧!
|
7月前
|
算法 Python
广度优先算法
广度优先算法
|
7月前
|
算法
【经典LeetCode算法题目专栏分类】【第4期】BFS广度优先算法:单词接龙、最小基因变化、二进制矩阵中的最短路径
【经典LeetCode算法题目专栏分类】【第4期】BFS广度优先算法:单词接龙、最小基因变化、二进制矩阵中的最短路径
|
8月前
|
算法 定位技术 图形学
unity3d寻路算法
unity3d寻路算法
169 8
|
算法
cocoscreator A* 寻路算法
cocoscreator A* 寻路算法
401 0
|
存储 算法 数据安全/隐私保护
算法训练营 - 广度优先BFS
算法训练营 - 广度优先BFS
113 0
|
数据采集 存储 算法
【基础知识】一文看懂深度优先算法和广度优先算法
图的遍历是指,从给定图中任意指定的顶点(称为初始点)出发,按照某种搜索方法沿着图的边访问图中的所有顶点,使每个顶点仅被访问一次,这个过程称为图的遍历。 我们根据访问节点的顺序与方式(根据搜索方法),可以分为广度优先(BFS)和深度优先(DFS),这是图论中两种非常重要的算法,生产上广泛用于拓扑排序,寻路(走迷宫),搜索引擎,爬虫等。
|
算法 定位技术
“ 探索迷局:解密广度寻路算法 “(二)
“ 探索迷局:解密广度寻路算法 “

热门文章

最新文章