前提:
重新看数据结构,自己总结并加深印象
问题:
在二维地图中,0代表此路可以走,1代表是墙,从(1,1)坐标走到(8,8),找出路径(不考虑斜的走)
地图如下:
map[10][10] = {
1,1,1,1,1,1,1,1,1,1,
1,0,1,0,0,0,0,0,0,1,
1,0,1,1,0,0,0,0,1,1,
1,0,0,0,0,0,1,0,0,1,
1,0,0,0,1,0,1,1,0,1,
1,0,0,0,1,0,1,0,0,1,
1,0,1,0,0,0,1,0,0,1,
1,0,1,0,1,0,0,0,0,1,
1,0,0,0,1,0,0,1,0,1,
1,1,1,1,1,1,1,1,1,1};
1.栈实现
大致思路:
1. 设置节点Node,保存一个格子的x,y 和 方向
2. 从右边顺时针访问相邻的格子,判断相邻格子中是否是墙,如果不是墙则保存要走的方向,把相邻的格子加入栈中
3. 如果一个格子中4个方向都走过,则栈中要弹出这个格子(也就意味着这个格子已经走到底了),返回上一个格子,再检测相邻格子是否能走
注意:
在判断完格子a相邻格子中哪个可以走时,要在map中把格子a的位置设为1,为了防止下个格子判断相邻格子时往回判断
总结:
回溯,要保存每个格子走过的方向
类似于深度优先搜索,运气好可能是最短路径
伪代码 :
while(栈不为空)
{
得到栈顶格子a
if(此格子是终点)
{
return true
}
找到相邻位置中哪个格子可以走
if(有格子b可以走)
{
地图中格子a的位置设为1
栈中加入此格子
}
else
{
地图中格子a的位置设为0
栈中弹出格子a
}
}
代码 :
#include <iostream>
#include <stack>
using namespace std;
int map[10][10] =
{
/* 1,2,3,4,5,6,7,8,9*/
1,1,1,1,1,1,1,1,1,1,
/*1*/ 1,0,1,0,0,0,0,0,0,1,
/*2*/ 1,0,1,1,0,0,0,0,1,1,
/*3*/ 1,0,0,0,0,0,1,0,0,1,
/*4*/ 1,0,0,0,1,0,1,1,0,1,
/*5*/ 1,0,0,0,1,0,1,0,0,1,
/*6*/ 1,0,1,0,0,0,1,0,0,1,
/*7*/ 1,0,1,0,1,0,0,0,0,1,
/*8*/ 1,0,0,0,1,0,0,1,0,1,
/*9*/ 1,1,1,1,1,1,1,1,1,1
};
struct Node
{
int x;
int y;
int dir;
};
bool FindSrcByStack(int startX, int startY, int endX, int endY, int(*map)[10], stack<Node> & resultPath)
{
stack<Node> storePath;
Node startNode;
startNode.x = startX;
startNode.y = startY;
startNode.dir = -1;
storePath.push(startNode);
while (!storePath.empty())
{
//拿出栈顶格子
Node node = storePath.top();
int x = node.x;
int y = node.y;
int dirIndex = node.dir;
bool isFind = false;
//此格子是终点
if (x == endX && y == endY)
{
while (!storePath.empty())
{
Node node = storePath.top();
resultPath.push(node);
storePath.pop();
}
return true;
}
//找到相邻位置中哪个格子可以走
int ii = x;
int jj = y;
while (dirIndex < 4 && !isFind)
{
dirIndex++;
switch (dirIndex)
{
case 0:
ii = x;jj = y + 1; break;
case 1:
ii = x + 1; jj = y; break;
case 2:
ii = x; jj = y - 1; break;
case 3:
ii = x + 1; jj = y; break;
}
if (map[ii][jj] == 0)
{
isFind = true;
map[ii][jj] = 1;
break;
}
}
//有格子b可以走
if (isFind)
{
//地图中格子a的位置设为1
//栈中加入此格子
Node nextNode;
nextNode.x = ii;
nextNode.y = jj;
nextNode.dir = -1;
storePath.top().dir = dirIndex;
storePath.push(nextNode);
}
else
{
//地图中格子a的位置设为0
//栈中弹出格子a
storePath.pop();
map[x][y] = 0;
}
}
return false;
}
void Print(stack<Node> path)
{
while (!path.empty())
{
Node node = path.top();
cout << "(" << node.x << "," << node.y << ")" << endl;
path.pop();
}
}
结果:
2.队列实现
大致思路:
1. 设置节点Node,保存 前面格子的位置(即格a 到 格b ,我在格b保存 格a的位置)
2. 从格子a 右边顺时针访问相邻的格子,判断相邻格子中是否是墙,如果不是墙则保存要走的方向,把四周能走的格子全部加入队列中,并且 保存 格子a 位置
3. 再从队列中拿出格子,反复格子2操作,有格子是最后终点 或者 队列为空
注意:
在判断完格子a相邻格子中哪个可以走时,要在map中把格子a的位置设为1,为了防止下个格子判断相邻格子时往回判断
总结:
需要记录上一个格子的位置,根据这个记录来显示路径
类似于广度优先搜索,这个路径找出来肯定是最短路径
伪代码 :
while(队列不为空)
{
从队列前面拿出格子
if(拿出的格子是终点)
{
return true;
}
while(遍历四周格子)
{
if(格子是否不是墙)
{
加入队列
map中设置格子处为1
}
}
}
代码 :
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int map[10][10] =
{
/* 1,2,3,4,5,6,7,8,9*/
1,1,1,1,1,1,1,1,1,1,
/*1*/ 1,0,1,0,0,0,0,0,0,1,
/*2*/ 1,0,1,1,0,0,0,0,1,1,
/*3*/ 1,0,0,0,0,0,1,0,0,1,
/*4*/ 1,0,0,0,1,0,1,1,0,1,
/*5*/ 1,0,0,0,1,0,1,0,0,1,
/*6*/ 1,0,1,0,0,0,1,0,0,1,
/*7*/ 1,0,1,0,1,0,0,0,0,1,
/*8*/ 1,0,0,0,1,0,0,1,0,1,
/*9*/ 1,1,1,1,1,1,1,1,1,1
};
struct QNode
{
int x;
int y;
int preNode;
};
bool FindSrcByQueue(int startX, int startY, int endX, int endY, int(*map)[10], stack<QNode> & resultPath)
{
queue<QNode> storePath;
vector<QNode> tmpStoreResultPath;
QNode startNode;
startNode.x = startX;
startNode.y = startY;
startNode.preNode = -1;
storePath.push(startNode);
int preIndex = -1;
while (!storePath.empty())
{
QNode node = storePath.front();
tmpStoreResultPath.push_back(node);
storePath.pop();
preIndex++;
node.preNode = preIndex;
int x = node.x;
int y = node.y;
int dirIndex = -1;
int ii = x;
int jj = y;
if (x == endX && y == endY)
{
QNode resultNode = tmpStoreResultPath.back();
do
{
resultPath.push(resultNode);
resultNode = tmpStoreResultPath[resultNode.preNode];
} while (resultNode.preNode != -1);
resultPath.push(tmpStoreResultPath[0]);
return true;
}
while (dirIndex < 4)
{
dirIndex ++;
switch (dirIndex)
{
case 0:
ii = x;jj = y + 1;break;
case 1:
ii = x + 1;jj = y;break;
case 2:
ii = x;jj = y - 1;break;
case 3:
ii = x - 1;jj = y;break;
}
if (map[ii][jj] == 0)
{
QNode newNode;
newNode.x = ii;
newNode.y = jj;
newNode.preNode = preIndex;
map[ii][jj] = 1;
storePath.push(newNode);
}
}
}
return false;
}
void Print(stack<QNode> path)
{
while (!path.empty())
{
QNode node = path.top();
cout << "(" << node.x << "," << node.y << ")" << endl;
path.pop();
}
}
结果: