回溯算法可以看成是栈的一个十分成熟的应用,
本质上秉承着:"正确前进错误返回" 的原则,通过入栈存储以前经过的所有节点,
当在一个方向上遇到死路,则依次弹栈返回前一个节点,继续按照相同的规律继续下一步的判断+入栈+弹栈操作。
< 本篇文章主要通过顺序栈与链栈(通过链表模拟)的方式实现迷宫问题 >
一:迷宫问题思路分析及实现(顺序栈)
1> 先不谈具体算法,首先我们需要实现迷宫的物理存储,
可以采用二维数组来存储一个二维平面地图,使用0表示是通路,1表示是墙:
int maze[10][10] = //迷宫在计算机中的物理存储方式
{
{1,1,1,1,1,1,1,1,1,1},
{1,0,0,1,1,0,1,1,0,1},
{1,0,0,1,0,0,0,1,0,1},
{1,0,0,0,0,1,1,0,0,1},
{1,0,1,1,1,0,0,1,1,1},
{1,0,0,0,1,0,0,0,0,1},
{1,0,1,0,0,0,1,0,0,1},
{1,0,1,1,1,0,1,1,0,1},
{1,0,0,1,1,0,0,1,0,1},
{1,1,1,1,1,1,1,1,1,1}
};
2> 存储完地图之后,因为需要用到栈的操作,新建一个栈 (用于保存当前的位置坐标与下一个需要前进的方向)
struct Try
{
int i;
int j;
int d;
}path[MaxSize];
int top = -1; //初始化栈指针
3> 接下来写主体结构
首先进行思路的整理:
* 函数参数传入的分别是起点坐标与出口坐标;
* 首先需要将起点入栈,然后开始循环,循环结束条件为栈空;
* 循环的第一步我们需要明白因为循环一次后栈中节点就会多一个,所以需要在开始判断栈顶节点的坐标是不是出口坐标;
如果是出口坐标,则遍历整个栈输出坐标;
* 当判断当前栈顶的节点坐标不是出口坐标,顺时针进行下一步的寻找 (上右下左0123),这样的方向定义可以任意,
但是这里需要再考虑一点:
当A ( 假设) 上方的路不通,判断右方的路是通的,然后右方经过一系列判断后是死路,返回A,
此时就需要保证循环不会再从上方/右方开始执行,而且不会再原路向左返回 ( 返回操作只允许弹栈),这就需要在新节点入栈
之前存储这个节点的方向数据d,当弹栈后读取该节点,直接可以向下一个方向遍历,为了防止原路返回就要对已走的路
进行标记 ( 数据替换);
* 对原路的标记不仅可以看到运动轨迹 (次要) ,主要是为了防止节点方向参数d取3 (想像节点向右走) 的时候原路返回;
* 路不通直接弹栈,将被-1覆盖的迷宫数据再用0恢复,栈指针减1。
下面给出该部分的代码实现:
vo