广度优先搜索
根据优先级进行广度搜索
通过回溯找到最短路径
代码实现
1.真实地图
//真实地图
#define MAP_ROW 6
#define MAP_COL 8
2.方向
//方向
enum PathDir
{
P_UP,
P_LEFT,
P_DOWN,
P_RIGHT
};
3.坐标
//坐标
struct MyPoint
{
int row;
int col;
};
4.地图数组节点结构
//地图节点结构
struct PathData
{
PathDir dir;
int val;
bool isFind;
};
5.树形结构 -节点
//树形结构
struct MyPathNode
{
MyPoint pos; //数据域 - 坐标
MyPathNode * pParent; //父节点指针
vector<MyPathNode *> pChild; //子节点指针数组
};
6.判断函数
//判断函数
bool isCheckPoint(MyPoint const& pos,PathData arr[][MAP_COL])
{
// 判断越界
if (pos.row >= 0 && pos.col >= 0 && pos.row < MAP_ROW && pos.col < MAP_COL)
{
//没越界
//第二个判断 空地且没有走过
if (arr[pos.row][pos.col].val == 0 && arr[pos.row][pos.col].isFind == false)
{
//空地 并且没有走过
return true;
}
}
return false;
}
7.销毁函数
//树的销毁函数
void clearTree(MyPathNode *& root)
{
if (root)
{
for (size_t i = 0; i < root->pChild.size(); ++i)
{
clearTree(root->pChild[i]); //递归孩子
}
delete root;
root = nullptr;
}
//没有节点自动结束递归
}
8.创建辅助数组
int arrMap[MAP_ROW][MAP_COL] =
{
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 1, 1, 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, 0, 0, 0 },
};
9.起点和终点
//起点和终点
MyPoint beginPoint = { 1, 1 };
MyPoint endPoint = { 4,6};
10.寻路树形结构数组
//准备两个寻路用的树形结构数组
vector<MyPathNode *> parentTable;
vector<MyPathNode *> childTable;
11.石头
//准备石头
MyPoint tempPoint;
12.开始寻路
//开始寻路
while (true)
{
//根据父节点元素做循环 四个方向
//外层 - 父节点
for (int i = 0; i < (int)parentTable.size(); ++i)
{
for (int j = 0; j < 4; ++j)
{
//石头探路
tempPoint = parentTable[i]->pos; //坐标
switch (j)
{
case P_UP:
tempPoint.row--;
break;
case P_LEFT:
tempPoint.col--;
break;
case P_RIGHT:
tempPoint.col++;
break;
case P_DOWN:
tempPoint.row++;
break;
default:
break;
}
//下一步位置确定
if (isCheckPoint(tempPoint,PathArr))
{
//添加 准备节点尾插
MyPathNode * tempNode = new MyPathNode;
tempNode->pos = tempPoint; //位置赋值
//*关联父子关系
tempNode->pParent = parentTable[i];
parentTable[i]->pChild.push_back(tempNode);
//设置已访问
PathArr[tempPoint.row][tempPoint.col].isFind = true;
//*把父节点数组所有可通行的加入子节点表
childTable.push_back(tempNode);
//判断当前节点是否为终点
if (tempPoint.row == endPoint.row&&tempPoint.col == endPoint.col)
{
//终点找到了 - 打印路径 - 遍历用指针
MyPathNode * pNode = tempNode;
//往上找父节点
while (pNode)
{
//打印
printf("row = %d, col = %d\n", pNode->pos.row, pNode->pos.col);
//步长移动
pNode = pNode->pParent;
}
//结束寻路 -跳出五层循环
goto OVER;
}
}
}
}
if (childTable.size() == 0)//没路了
{
cout << "找不到终点" << endl;
goto OVER;
}
//循环结束 - 说明父节点指针遍历完了
parentTable = childTable; //父子交接
//清除子表
childTable.clear();
}
OVER:
总体
Point = { 1, 1 };
MyPoint endPoint = { 4,6};
//辅助数组
PathData PathArr[MAP_ROW][MAP_COL];
//成员初始化
for (int i = 0; i < MAP_ROW; ++i)
{
for (int j = 0; j < MAP_COL; j++)
{
PathArr[i][j].val = arrMap[i][j];
PathArr[i][j].isFind = false;
PathArr[i][j].dir = P_UP; //从上开始
}
}
//起点且根节点已走过
PathArr[beginPoint.row][beginPoint.col].isFind = true;
//准备一个树形结构
MyPathNode *pRoot = nullptr;
pRoot = new MyPathNode;
pRoot->pos = beginPoint;
pRoot->pParent = nullptr;
//准备两个寻路用的树形结构数组
vector<MyPathNode *> parentTable;
vector<MyPathNode *> childTable;
// 父节点数组添加起点
parentTable.push_back(pRoot);
//准备石头
MyPoint tempPoint;
//开始寻路
while (true)
{
//根据父节点元素做循环 四个方向
//外层 - 父节点
for (int i = 0; i < (int)parentTable.size(); ++i)
{
for (int j = 0; j < 4; ++j)
{
//石头探路
tempPoint = parentTable[i]->pos; //坐标
switch (j)
{
case P_UP:
tempPoint.row--;
break;
case P_LEFT:
tempPoint.col--;
break;
case P_RIGHT:
tempPoint.col++;
break;
case P_DOWN:
tempPoint.row++;
break;
default:
break;
}
//下一步位置确定
if (isCheckPoint(tempPoint,PathArr))
{
//添加 准备节点尾插
MyPathNode * tempNode = new MyPathNode;
tempNode->pos = tempPoint; //位置赋值
//*关联父子关系
tempNode->pParent = parentTable[i];
parentTable[i]->pChild.push_back(tempNode);
//设置已访问
PathArr[tempPoint.row][tempPoint.col].isFind = true;
//*把父节点数组所有可通行的加入子节点表
childTable.push_back(tempNode);
//判断当前节点是否为终点
if (tempPoint.row == endPoint.row&&tempPoint.col == endPoint.col)
{
//终点找到了 - 打印路径 - 遍历用指针
MyPathNode * pNode = tempNode;
//往上找父节点
while (pNode)
{
//打印
printf("row = %d, col = %d\n", pNode->pos.row, pNode->pos.col);
//步长移动
pNode = pNode->pParent;
}
//结束寻路 -跳出五层循环
goto OVER;
}
}
}
}
if (childTable.size() == 0)//没路了
{
cout << "找不到终点" << endl;
goto OVER;
}
//循环结束 - 说明父节点指针遍历完了
parentTable = childTable; //父子交接
//清除子表
childTable.clear();
}
OVER:
//树的释放
clearTree(pRoot);
system("pause");
return 0;
}