题源及算法思路来源于“网易云课堂:数据结构实战完全手册(夏曹俊·丁宋涛)”
迷宫问题,在一个由“0(表示通路)”“1(表示障碍)”的迷宫数组中,利用回溯法,从起点出发到达最终的出口。
利用链栈的特性和回溯算法的思想,通过不断的尝试搜索寻找迷宫的出口
/* 只要严格按照East->South->West->North的优先级顺序遍历寻找
路径,就一定能够穷举到所有的路线,且要标记已经走过的坐标点,
否则就会出现走回头路
通常将已经走过的坐标点标记为“2”
East(i,j+1)、South(i+1,j)、West(i,j-1)、 North(i-1,j)
*/
#define TRUE 1
#define FALSE 0
typedef int BOOL;
typedef struct
{
int x;// 路径坐标点的横坐标值
int y;// 路径坐标点的纵坐标值
int direction;// 路径坐标点的方向
}ElemType;
typedef struct Node
{
ElemType data;// 链栈的数据域
struct Node* pNext;// 链栈的指针域
}LinkStack;
int main()
{
// 迷宫,终点处在maze[6][10]
int maze[][11] =
{
{1,1,1,1,1,1,1,1,1,1,1 },
{1,0,1,0,0,1,1,1,0,0,1 },
{1,0,0,0,0,0,1,0,0,1,1 },
{1,0,1,1,1,0,0,0,1,1,1 },
{1,0,0,0,1,0,1,1,0,1,1 },
{1,1,0,0,1,0,1,0,0,0,1 },
{1,1,1,0,0,0,0,0,1,0,0 },
{1,1,1,1,1,1,1,1,1,1,1 },
};
// 分别代表East、South、West、North四个方向
int direction [4][2] =
{
{0, 1},
{1, 0},
{0, -1},
{-1, 0}
};
ElemType element;// 操作获取迷宫各位置信息的数据
LinkStack* pStack = NULL;// 保存移动路径的栈
pStack = InitialStack();
// 设置起始位置
element.x = 1;
element.y = 1;
element.direction = -1;// 保证下一个结点推进时,起点方向是0
pStack = PushStack(pStack, element);// 迷宫入口入栈
// 控制循环遍历的当前结点横、纵坐标和方向
int currX, currY, currDire;
// 控制循环遍历的潜在结点横、纵坐标
int potenX, potenY;
while(IsLinkStackEmpty(pStack) != TRUE)
{
// 获得当前的结点坐标
currX = pStack->data.x;
currY = pStack->data.y;
currDire = pStack->data.direction + 1;
while(currDire <= 3)
{
potenX = currX + direction[currDire][0];
potenY = currY + direction[currDire][1];
// 若已到达终点
if(potenX == 6 && potenY == 10 && maze[potenX][potenY] == 0)
{
printf("Find the exit point!\n");
printf("The current coordinate is: (%d, %d)\n", currX, currY);
// 输出所有路过的坐标结点
while(IsLinkStackEmpty(pStack->pNext) != TRUE)
{
pStack = PopStack(pStack, &element);
printf("The previous coordinate is: (%d, %d)\n", pStack->data.x, pStack->data.y);
}
system("pause");
return 0;
}
// 判断是否可以前进到下一个坐标结点
if(maze[potenX][potenY] == 0)
{
maze[potenX][potenY] = 2;// 标记已经走过的坐标结点,避免走回头路
// 将结点路径保留,所以进行入栈
element.x = potenX;
element.y = potenY;
element.direction = -1;
pStack = PushStack(pStack, element);
break;
}
currDire = currDire + 1;// 确定下次选择的移动方向
}
/* 回溯:currDire > 3,说明所有的当前结点的四个方向都是死路,
所以要退栈,返回上一个结点
*/
if(currDire > 3)
{
pStack = PopStack(pStack, &element);// 使用element保存通往死路的结点
}
}
printf("There is no path in zhe maze.\n");
system("pause");
return 0;
}