广度寻路(C++实现)

广度优先遍历,是一种非启发式、不用预处理的寻路算法。通常会将整个图全部遍历,意图寻找终点。(也就是说如果终点位置适宜期一般会遍历整个地图)一般情况,广度优先遍历算法都是基于队列结构,先进先出的遍历所有节点。
该寻路算法,通常先将起点加入队列结构,然后将该点周边符合要求(未加入队列结构并且可以到达的点)的点全部再次加入队列结构中,意图下一次遍历。一直循环该方法。直至全部遍历或者找到终点。
关于广度优先搜索还具有以下性质:
1.其遍历方式走直线不走斜线
2.如果有路必然可以找到路,找到的路也是最短路径
3.需要遍历所有可能通行的节点,如果地图比较大,开销也会比较大
首先从起点开始,每一次搜索这个起点的下一层的所有子节点,第二次通过下一层的所有子节点去搜索第三层的所有的子节点。
通过遍历找到可通行的所有的路径点但没有路径。
在这里插入图片描述
这是一幅关于广度遍历规则的一幅图,由图可见,其总体呈菱形结构,如果当这个图足够大时,由于其采用的是横向存储子节点,会导致其内存空间不够用。
下面是深度优先搜索的的C++实现代码:

//深度寻路需要终点才可以寻路
//广度寻路不需要终点就可以寻路
#include "stdafx.h"
#include<vector>
#include<iostream>
using std::cout;
using std::endl;
using std::vector;
#define MAP_ROW 6
#define MAP_COL 8
//准备坐标结构体,表示横坐标和纵坐标
struct Pos
{
	int row, col;
};
//准备查找的方向这里采用枚举的方式便于区分后面便于使用switch选择
enum Dir{up,down,left,right};
//准备一个新的地图,这里表示这个新的地图的一个结构体
struct pathNode
{
	Dir dir;
	int value;
	bool isFind;
};
//要进行寻路的地图
int map[MAP_ROW][MAP_COL] = {
	{ 0, 0, 0, 1, 0, 0, 0, 0 },
	{ 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 0, 0, 1, 0, 0, 0, 0 },
	{ 0, 0, 0, 1, 0, 0, 0, 0 },
	{ 0, 0, 0, 1, 0, 0, 0, 0 },
	{ 0, 0, 0, 1, 0, 0, 0, 0 },
};
//由于广度优先搜索采用的树搜寻到子节点挂载上,所以这里定义一个树节点的结构体
struct MyTreeNode
{
	Pos pos;
	MyTreeNode *parent;
	vector<MyTreeNode*>children;
};
//判断当前节点是否越界,或者是否已经被遍历过
bool isChecked(pathNode array[][MAP_COL], Pos pos)
{
	if (pos.row < 0 || pos.col<0 || pos.row>MAP_ROW || pos.col > MAP_COL)
	{
		return false;
	}
  if (array[pos.row][pos.col].value == 1 || array[pos.row][pos.col].isFind == true)
	{
		return false;
	}
	else
	{
		return true;
	}
}
void clearTree(MyTreeNode*&pRoot)
{
	if (pRoot)
	{
		for (int i = 0; i < pRoot->children.size(); i++)
		{
			clearTree(pRoot->children[i]);
		}
		delete pRoot;
		pRoot = nullptr;
	}
}
int _tmain(int argc, _TCHAR* argv[])
{
	//准备到最后用来打印画图的数组
	int draw_map[MAP_ROW][MAP_COL] = { 0 };
	//为新准备的结构体赋值
	pathNode array[MAP_ROW][MAP_COL];
	for (int i = 0; i < MAP_ROW; i++)
	{
		for (int j = 0; j < MAP_COL; j++)
		{
			array[i][j].dir = up;
			array[i][j].isFind = false;
			array[i][j].value = map[i][j];
		}
	}
	Pos begin_pos = { 1, 2 };//寻路的起始点
	Pos end_pos = { 5,6 };//寻路的终点
	array[begin_pos.row][begin_pos.col].isFind = true;//将其实点的isFind赋值为true
	//定义根节点
	MyTreeNode *pRoot=new MyTreeNode;
	pRoot->parent = nullptr;
	pRoot->pos = begin_pos;
	//准备两个数组用来保存当前节点坐标和下一次进行读取的坐标
	vector<MyTreeNode*> NodeList;
	vector<MyTreeNode*> NextNodeList;
	NodeList.push_back(pRoot);
	Pos temp_pos;
	//开始寻路操作
	while (true)
	{
		for (int i = 0; i < NodeList.size(); i++)
		{
			for (int j = 0; j < 4; j++)
			{ 
				temp_pos = NodeList[i]->pos;
				switch (j)
				{
				case up:
					temp_pos.row--;
					break;
				case down:
					temp_pos.row++;
					break;
				case left:
					temp_pos.col--;
					break;
				case right:
					temp_pos.col++;
					break;
				}
				if (isChecked(array, temp_pos))
				{
					//如果这个坐标存在,则创建一个新的树节点并将这个坐标赋值给这个树节点,并将这个节点关联。
					MyTreeNode *NewNode = new MyTreeNode;
					NewNode->parent = NodeList[i];
					NewNode->pos = temp_pos;
					NodeList[i]->children.push_back(NewNode);
					NextNodeList.push_back(NewNode);
					array[temp_pos.row][temp_pos.col].isFind = true;
					if (temp_pos.row == end_pos.row&&temp_pos.col == end_pos.col)
					{
						MyTreeNode *tempNode = NewNode;
						while (tempNode)
						{
							///cout << "row:" << tempNode->pos.row << "col:" << tempNode->pos.row << endl;
							draw_map[tempNode->pos.row][tempNode->pos.col] = 5;
							tempNode = tempNode->parent;
						}
						goto LoGo;
					}
				}
			}
		}
		//将下一组节点复制给当前节点,便于进行循环
		NodeList = NextNodeList;
		NextNodeList.clear();//将之前保存的下一组节点清空,便于其回收利用
	}
LoGo:
	clearTree(pRoot);
	for (int i = 0; i < MAP_ROW; i++)
	{
		for (int j = 0; j < MAP_COL; j++)
		{
			if (draw_map[i][j] == 5)
			{
				cout << " *";
			}
			else
			{
				cout << " -";
			}
		}
		cout << endl;
	}
	system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值