上面我们已经写过递归和非递归来实现求解迷宫的问题,今天我们就在递归的基础上实现多条通路,最短问题。
初始化最短路径地图
/////////////////////////////////////////////////
//////////////多通路最短路径/////////////////////
////////////////////////////////////////////////
void MazeInitShortPath(Maze* maze){
int map[ROW][COL]={
{0,1,0,0,0,0},
{0,1,1,0,0,0},
{0,1,0,1,1,1},
{1,1,1,0,0,0},
{0,0,1,0,0,0},
{0,0,1,0,0,0},
};
int i = 0;
for (; i<ROW; i++){
int j = 0;
for (; j<COL; j++){
maze->map[i][j] = map[i][j];
}
}
}
用这个特殊的函数来打印栈
//这个函数只用于迷宫问题,用来调试,通常意义下,我们栈不允许
//遍历的,但是如果进行测试或调试,这是个例外
//因此在这里函数虽然进行了遍历,但是仅用于调试
//之所以写这样一个函数遍历栈,为了能够从入口的顺序来打印栈中的内容
void SeqStackDebugPrint(SeqStack* stack, const char* msg){
printf("%s\n",msg);
if(stack==NULL){
return;
}
size_t i=0;
for(;i<stack->size;i++){
printf("(%d,%d)\n",stack->data[i].row,stack->data[i].col);
}
printf("\n");
}
void SeqStackDestroy(SeqStack* stack){
free(stack->data);
stack->size=0;
stack->capacity=0;
}
void _GetShortPath(Maze* maze,Point cur,Point entry,SeqStack* cur_path,SeqStack* short_path)
{
// 1、判定当前点能否落脚
if(!CanStay(maze,cur)){
return;
}
//2、如果能落脚,就对当前点进行标记,同时把当前点插入到当前cur_path
else
{
Mark(maze,cur);
SeqStackPush(cur_path,entry);
}
//3、判断当前点是否出口
if(IsExit(maze,cur,entry)){
//a、如果当前点是出口,说明当前找到了一条路经,就拿当前路径和short_path中的路径进行比较,
//如果当前路径比short_path短,或者short_path本身是一个空栈,
//就用当前路径代替short_path代替完毕之后也要回溯,尝试找其他的路径
printf("找到了一条路径\n");
if(cur_path->size<short_path->size||short_path->size==0){
printf("找到了一条比较短的路径\n");
}
SeqStackAssgin(cur_path,short_path);//栈对象赋值
// b、如果当前路径没有比short_path短,就要尝试着去找其他路径(进行回溯)
//在回溯之前也要把cur_path栈顶元素也进行出栈
SeqStackPop(cur_path);
return;
}
//4、如果当前点不是出口,尝试探测四个方向(按照顺时针来探测)
Point up=cur;
up.row-=1;
_GetShortPath(maze,up,entry,cur_path,short_path);
Point right=cur;
right.col+=1;
_GetShortPath(maze,right,entry,cur_path,short_path);
Point down=cur;
down.row+=1;
_GetShortPath(maze,down,entry,cur_path,short_path);
Point left=cur;
left.col-=1;
_GetShortPath(maze,left,entry,cur_path,short_path);
// 5、如果四个方向都递归探测过了,就可以进行
// 出栈(指当前函数栈帧结束,同时cur_path,也要进行出栈)回溯到
//上一个点
SeqStackPop(cur_path);
return;
}
核心思路
我们的思路就是尝试找到所有的路径,然后从所有的路径中找到最短的路径
void GetShortPath(Maze* maze,Point entry){
//和我们从数组中找到最小的数字的思路是一样的
//保存着当前找到的路径
SeqStack cur_path;
//保存着最短的路径
SeqStack short_path;
SeqStackInit(&cur_path);
SeqStackInit(&short_path);
_GetShortPath(maze,entry,entry,&cur_path,&short_path);//辅助递归的函数
//打印栈中的内容
SeqStackDebugPrint(&short_path,"最短路径是:");
}
测试函数如下:
void test3(){
TEST_HEADER;
Maze maze;
MazeInitShortPath(&maze);
MazePrint(&maze);
Point entry = { 0, 1 };
GetShortPath(&maze,entry);
MazePrint(&maze);
}
我们的主要思路就是定义出两个栈,然后让一个存放当前的路径,一个存放的是最小的路径,我们每次用当前的路径和最小的路径进行比较,小的存放在存放最小路径的栈中。