代码如下:
Maze.h
#pragma once
#include<stdio.h>
typedef struct Pos{
int _Row;
int _COL;
}Pos;
Maze.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"Maze.h"
#include"Stack.h"
/*判断当前路径是否在地图上*/
int CanStay(Pos* pos, int Maze[5][5]) {
if (pos == NULL) {
return;
}
if (pos->_Row < 0 || pos->_COL < 0 ||
pos->_Row > 4 || pos->_COL > 4) {
/*当前点在地图外*/
return 0;
}
return 1;
}
/*标记一个点*/
void MarkPos(Pos* pos, int Maze[5][5]) {
if (pos == NULL) {
return;
}
Maze[pos->_Row][pos->_COL] = 2;
}
/*检查该点是不是是通路*/
int CanWalk(Pos* pos, int Maze[5][5]) {
if (pos == NULL) {
return;
}
if (Maze[pos->_Row][pos->_COL] == 1) {
return 1;
}
return 0;
}
/*检查该点是不是出口*/
int Check_Export(Pos* pos, int Maze[5][5]) {
if (pos == NULL) {
return;
}
if (pos->_Row == 0 || pos->_COL == 0 ||
pos->_Row == 4 || pos->_COL == 4) {
/*该点在地图边缘,判断该点是不是出口*/
if (Maze[pos->_Row][pos->_COL] == 2 ) {
return 1;
}
}
return 0;
}
/*stack1这个栈是存储路径的结点的*/
/*stack2这个栈是存储路径的*/
int GetShortPath(Pos* entry, int Maze[5][5]) {
if (entry == NULL) {
return;
}
//判断当前入口点是否合法
if (!CanStay(entry, Maze)) {
return 0;
}
//然后把入口点标记
MarkPos(entry, Maze);
SeqStack stack1;
SeqStack stack2;
/*初始化两个栈*/
SeqStackInit(&stack1);
SeqStackInit(&stack2);
Pos pos;
pos._Row = entry->_Row;
pos._COL = entry->_COL;
/*pos_path是存储路径的长短的,row是第几个通路,用col表示第几条路径*/
Pos pos_path;;
/*初始化pos_path*/
pos_path._Row = 0;
pos_path._COL = 0;
/*把入口点入栈*/
SeqStackPush(&stack1, *entry);
++pos_path._Row;
//开始循环
/*
**与不是最短路径的区别是,设置一个len,每次入栈一个元素,就让len+1, 出栈一个元素,就len-1
**创建一个栈,存储最短路径,如果遇到出口,如果栈为空,就把当前len入栈,反之就把当前的len和栈的栈顶元素比较
**如果len大于栈顶元素,就回溯,反之就把当前len入栈,再回溯
**知道找不到路走了,判断栈是否为空,如果为空就表示没有路径,如果不为空,就取栈顶元素,栈顶元素为最小路径
**/
//判断当前点是不是在地图上
while (CanStay(&pos, Maze)) {
/*上*/
--pos._Row;
/*如果该点在地图上*/
if (CanStay(&pos, Maze)) {
/*该点可以形成通路*/
if (CanWalk(&pos, Maze)) {
/*
**检查是不是出口,如果是出口,就把pospath++,
**如果栈stack2是空栈,就直接入栈pos和pospath
**如果不是空栈,就把pospath和当前栈顶元素比较,如果小的话就入栈pospath
**然后继续走下去,判断pos上一个位置的下一个方向
*/
/*如果可以走,就标记*/
MarkPos(&pos, Maze);
if (Check_Export(&pos, Maze)) {
/*是出口*/
++pos_path._Row;
++pos_path._COL;
SeqStackPush(&stack1, pos);
/*判断当前栈是不是空栈然后判断通路的长短要不要入栈*/
if (SeqStackEmpty(&stack2)) {
/*是空栈把pos和pospath直接入栈*/
SeqStackPush(&stack2, pos);
SeqStackPush(&stack2, pos_path);
/*然后继续判断当前点的下一个方向*/
}
else {
/*不是空栈,比较当前路径和栈顶元素的row的大小*/
Pos top_path = SeqStackTopValue(&stack2);
if (pos._Row < top_path._Row) {
/*当前路径短*/
SeqStackPush(&stack2, pos);
SeqStackPush(&stack2, pos_path);
}
/*如果当前路径比已经找到的长,那就继续判断*/
}
}
/*
**如果不是出口,把当前pos入栈,继续循环
*/
else {
SeqStackPush(&stack1, pos);
pos_path._Row++;
continue;
}
}
}
++pos._Row;
/*下*/
++pos._Row;
if (CanStay(&pos, Maze)) {
if (CanWalk(&pos, Maze)) {
/*如果可以走,就标记*/
MarkPos(&pos, Maze);
if (Check_Export(&pos, Maze)) {
SeqStackPush(&stack1, pos);
/*如果是出口*/
//row代表路径的长度
++pos_path._Row;
++pos_path._COL;
if (SeqStackEmpty(&stack2)) {
/*如果是空栈,直接入栈*/
SeqStackPush(&stack2, pos);
SeqStackPush(&stack2, pos_path);
}
else {
/*不是空栈*/
Pos path = SeqStackTopValue(&stack2);
if (pos_path._Row < path._Row) {
/*如果小于*/
SeqStackPush(&stack2, pos);
SeqStackPush(&stack2, pos_path);
}
/*如果不小于就不管,继续判断当前点的下一个方向*/
}
}
else {
/*这个点可以走,但是不是出口点*/
SeqStackPush(&stack1, pos);
++pos_path._Row;
continue;
}
}
}
--pos._Row;
/*左*/
--pos._COL;
if (CanStay(&pos, Maze)) {
if (CanWalk(&pos, Maze)) {
/*如果可以走,就标记*/
MarkPos(&pos, Maze);
if (Check_Export(&pos, Maze)) {
SeqStackPush(&stack1, pos);
++pos_path._Row;
++pos_path._COL;
/*判断是不是空栈*/
if (SeqStackEmpty(&stack2)) {
/*是空栈*/
SeqStackPush(&stack2, pos);
SeqStackPush(&stack2, pos_path);
}
else {
/*判断长短*/
Pos path = SeqStackTopValue(&stack2);
if (pos_path._Row < path._Row) {
/*当前出口是路径较短的*/
SeqStackPush(&stack2, pos);
SeqStackPush(&stack2, pos_path);
}
/*如果不是短的就不管了,继续下一个方向*/
}
}
else {
/*是通路但是不是出口点*/
SeqStackPush(&stack1, pos);
pos_path._Row++;
continue;
}
}
}
++pos._COL;
/*右*/
++pos._COL;
if (CanStay(&pos, Maze)) {
if (CanWalk(&pos, Maze)) {
/*如果可以走,就标记*/
MarkPos(&pos, Maze);
if (Check_Export(&pos, Maze)) {
SeqStackPush(&stack1, pos);
pos_path._Row++;
pos_path._COL++;
if (SeqStackEmpty(&stack2)) {
SeqStackPush(&stack2, pos);
SeqStackPush(&stack2, pos_path);
}
else {
Pos path = SeqStackTopValue(&stack2);
if (pos_path._Row < path._Row) {
SeqStackPush(&stack2, pos);
SeqStackPush(&stack2, pos_path);
}
}
}
else {
SeqStackPush(&stack1, pos);
pos_path._Row++;
continue;
}
}
}
--pos._COL;
/*该循环的出口是,如果该点判断了上下左右了,不管走不走的通了,该点是入口点,就可以结束循环了*/
if (pos._Row == entry->_Row && pos._COL == entry->_COL) {
/*当前节点是入口点,而且四个方向都走不同*/
break;
}
/*当前点走不通了,而且还不是入口点*/
SeqStackPop(&stack1);
Pos pos2 = SeqStackTopValue(&stack1);
pos = pos2;
pos_path._Row--;
}
/*如果有出口,那么此时最短路径是stack2的栈顶元素的row值,最短路径的出口是*/
if (SeqStackEmpty(&stack2)) {
/*如果此时stack2是空的,表示没有找到迷宫的出口*/
return 0;
}
Pos len = SeqStackTopValue(&stack2);
return len._Row;
}
Pos GetPath(SeqStack* stack) {
if (stack == NULL) {
return;
}
/*
**获取最短路径
*/
SeqStackPop(stack);
return SeqStackTopValue(stack);
}
int main() {
/*求多出口迷宫的最短路径,非递归求法*/
Pos entry;
entry._Row = 0;
entry._COL = 1;
int maze[5][5] = { { 0, 1, 0, 0, 0 },
{ 0, 1, 1, 1, 0 },
{ 0, 1, 0, 1, 1 },
{ 1, 1, 0, 1, 0 },
{ 0, 0, 0, 1, 0 },
};
int i = GetShortPath(&entry, maze);
if (i == 0) {
printf("未找到路径");
}
else {
printf("最短路径为:%d", i);
}
system("pause");
return 0;
}