迷宫基于栈的实现--最短路径的非递归实现
2018-04-02 14:41
357 查看
一个 Datatype arr
= {
{ 0,0,0,0,0,0 },
{ 0,0,1,1,1,1 },
{ 0,0,1,0,1,0 },
{ 0,0,1,0,1,0 },
{ 0,0,1,1,1,1 },
{ 0,0,1,0,0,0 },
};这样6×6的二位数组就是一个最简单的最基础的迷宫模型。我们知道入口,利用暴力求解,很容易找到出口,判断是否有出路。我们很容易想到利用压栈的方法,找到出口。while循环找满足条件的下一步。找到出口返回。
但如果是多个出口呢。我们很容易想到递归,递归可以天然的可以返回到上一层。也就是说,递归函数在找到出口后并不是结束了,而是返回到上一层栈帧,继续尝试其他路是否可行。知道返回到最后一层结束。
我想用非递归模拟递归实现,我思考了下递归所要完成的具体步骤,递归函数实现了走的尾在退回头的过程,栈一样可以实现这个功能。
int MazeGetPath(Maze *pmaze)
{
Pos *cur = pmaze->_entry;
Pos next = (Pos)malloc(sizeof(Pos));
Stack path=(Stack )malloc(sizeof(Stack));
StackInit(&path,10);
StackPush(&path, cur);
int flag = 0;
while (StackEmpty(path) != 0)
{
(*cur) = StackTop(path);
StackPop(path);
pmaze->_mz[cur->_col][cur->_row] = 2;
if (cur->_row == N - 1)
{
flag = 1;
printf(“找到了\n”);//不退出继续找其他的
MazePrint(pmaze);
}
{
/下/
next->_col = cur->_col + 1;
next->_row = cur->_row;
if (MazeCheckIsAccess(pmaze, next))
{
StackPush(&path, next);
}
//上
next->_col = cur->_col - 1;
next->_row = cur->_row;
if (MazeCheckIsAccess(pmaze, next))
{
StackPush(&path, next);
}
//左
next->_col = cur->_col;
next->_row = cur->_row - 1;
if (MazeCheckIsAccess(pmaze, next))
{
StackPush(&path, next);
}
//右
next->_col = cur->_col;
next->_row = cur->_row + 1;
if (MazeCheckIsAccess(pmaze, next))
{
StackPush(&path, next);
}
//无论那个方向都通路都压栈,然后当走不通时会自然的返回到岔口的另一个口继续走。栈是第一次便利这个点的时候就把所有通路存入栈中,而递归是返回后在寻找其他的路
}
}
if (flag == 0)
printf(“没有出口\n”);
free(next);
return 1;
}
但是这依然没有解决我们环的情况,我们采用走一步记一步的方法,数值++,只有比自己数值大的路或者走没有走过的通路。当我们遍历过一遍,出口测的非0,最小只-1就是长度,这个横纵坐标就是最出口。
倒着走比自己数值少一的点,存入栈,就倒着走万这条路了。
void StackShortPath(Maze *pmaze, Stack *path)
{
int i = 0, j = N - 1;
int shortcount = N*N;
Pos cur;
for (i = 0; i < N; i++)
{
if (pmaze->_mz[i][j] != 0 && pmaze->_mz[i][j] < shortcount)
{
shortcount = pmaze->_mz[i][j];
cur._col = i;
cur._row = j;
}
}
printf(“the short path size is:%3d\n”, shortcount - 1);
printf(“the short path out is:(%d,%d)\n”, cur._col + 1, cur._row + 1);
Pos next = (Pos)malloc(sizeof(Pos));
StackPush(&path, &cur);
while (cur._col != pmaze->_entry->_col || cur._row != pmaze->_entry->_row)
{
cur = StackTop(path);
{
/下/
next->_col = cur._col + 1;
next->_row = cur._row;
if (pmaze->_mz[next->_col][next->_row] == pmaze->_mz[cur._col][cur._row] - 1)
{
StackPush(&path, next);
}
//上
next->_col = cur._col - 1;
next->_row = cur._row;
if (pmaze->_mz[next->_col][next->_row] == pmaze->_mz[cur._col][cur._row] - 1)
{
StackPush(&path, next);
}
//左
next->_col = cur._col;
next->_row = cur._row - 1;
if (pmaze->_mz[next->_col][next->_row] == pmaze->_mz[cur._col][cur._row] - 1)
{
StackPush(&path, next);
}
//右
next->_col = cur._col;
next->_row = cur._row + 1;
if (pmaze->_mz[next->_col][next->_row] == pmaze->_mz[cur._col][cur._row] - 1)
{
StackPush(&path, next);
}
}
}
StackPrint(path);
}
void MazeGetShortPath(Maze *pmaze)
{
Pos cur = *pmaze->_entry;
Pos next = (Pos)malloc(sizeof(Pos));
Stack path = (Stack )malloc(sizeof(Stack));
StackInit(&path, 10);
Stack shortpath = (Stack )malloc(sizeof(Stack));
StackInit(&shortpath, 10);
StackPush(&path, &cur);
pmaze->_mz[cur._col][cur._row] = 2;
int flag = 0;
while (StackEmpty(path) != 0)
{
if (cur._row == N - 1)
{
MazePrint(pmaze);
printf(“找到了\n”);
flag = 1;
}
cur = StackTop(path);
StackPop(path);
}
typedef struct Stack{
Pos *_mz;
size_t _size;
size_t _capacity;
}Stack;
void StackInit(Stack** ps,size_t capacity)
{
assert(*ps);
(*ps)->_size = 0;
(*ps)->_capacity = capacity;
(ps)->_mz = (Pos )malloc(sizeof(Pos)*(*ps)->_capacity);
return;
}
Pos StackTop(Stack *s)
{
return s->_mz[s->_size-1];
}
void StackPush(Stack **pps, Pos *x)
{
assert(pps);
assert(*pps);
if ((*pps)->_size == (*pps)->_capacity)
{
(pps)->_capacity = 2;
(pps)->_mz = (Pos)realloc((pps)->_mz,(sizeof(Pos))(*pps)->_capacity);
}
assert(*pps);
((*pps)->_mz[(*pps)->_size])._col = x->_col;
((*pps)->_mz[(*pps)->_size])._row = x->_row;
(*pps)->_size++;
}
Pos *StackPop(Stack *ps)
{
return ps->_mz+(–ps->_size);
}
int StackEmpty(Stack *ps)
{
assert(ps);
return ps->_size;
}
void StackPrint(Stack *ps)
{
int i = 0;
for (i = ps->_size-1; i >= 0; i–)
printf(“(%d,%d)->”, ps->_mz[i]._col + 1, ps->_mz[i]._row + 1);
printf(“\n”);
}
以及迷宫的初始化等辅助函数
#pragma once
#include”Stack.h”
#define N 6
typedef struct Maze
{
Datatype _mz
;
Pos *_entry;
}Maze;
void MazeInit(Maze **pmaze,Datatype a
)
{
int i = 0,j = 0;
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
(*pmaze)->_mz[i][j] = a[i][j];
}
}
}
void MazePrint(Maze *pmaze) {
int i = 0, j = 0;
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
printf(“%3d”, pmaze->_mz[i][j]);
}
printf(“\n”);
}
printf(“\n”);
}
int MazeCheckIsAccess(Maze pmaze ,Pos pos)
{
if (pos->_col >= 0 && pos->_col < N && pos->_row >= 0 && pos->_row < N)
{
if (pmaze->_mz[pos->_col][pos->_row] == 1)
return 1;
}
return 0;
}
= {
{ 0,0,0,0,0,0 },
{ 0,0,1,1,1,1 },
{ 0,0,1,0,1,0 },
{ 0,0,1,0,1,0 },
{ 0,0,1,1,1,1 },
{ 0,0,1,0,0,0 },
};这样6×6的二位数组就是一个最简单的最基础的迷宫模型。我们知道入口,利用暴力求解,很容易找到出口,判断是否有出路。我们很容易想到利用压栈的方法,找到出口。while循环找满足条件的下一步。找到出口返回。
但如果是多个出口呢。我们很容易想到递归,递归可以天然的可以返回到上一层。也就是说,递归函数在找到出口后并不是结束了,而是返回到上一层栈帧,继续尝试其他路是否可行。知道返回到最后一层结束。
我想用非递归模拟递归实现,我思考了下递归所要完成的具体步骤,递归函数实现了走的尾在退回头的过程,栈一样可以实现这个功能。
int MazeGetPath(Maze *pmaze)
{
Pos *cur = pmaze->_entry;
Pos next = (Pos)malloc(sizeof(Pos));
Stack path=(Stack )malloc(sizeof(Stack));
StackInit(&path,10);
StackPush(&path, cur);
int flag = 0;
while (StackEmpty(path) != 0)
{
(*cur) = StackTop(path);
StackPop(path);
pmaze->_mz[cur->_col][cur->_row] = 2;
if (cur->_row == N - 1)
{
flag = 1;
printf(“找到了\n”);//不退出继续找其他的
MazePrint(pmaze);
}
{
/下/
next->_col = cur->_col + 1;
next->_row = cur->_row;
if (MazeCheckIsAccess(pmaze, next))
{
StackPush(&path, next);
}
//上
next->_col = cur->_col - 1;
next->_row = cur->_row;
if (MazeCheckIsAccess(pmaze, next))
{
StackPush(&path, next);
}
//左
next->_col = cur->_col;
next->_row = cur->_row - 1;
if (MazeCheckIsAccess(pmaze, next))
{
StackPush(&path, next);
}
//右
next->_col = cur->_col;
next->_row = cur->_row + 1;
if (MazeCheckIsAccess(pmaze, next))
{
StackPush(&path, next);
}
//无论那个方向都通路都压栈,然后当走不通时会自然的返回到岔口的另一个口继续走。栈是第一次便利这个点的时候就把所有通路存入栈中,而递归是返回后在寻找其他的路
}
}
if (flag == 0)
printf(“没有出口\n”);
free(next);
return 1;
}
但是这依然没有解决我们环的情况,我们采用走一步记一步的方法,数值++,只有比自己数值大的路或者走没有走过的通路。当我们遍历过一遍,出口测的非0,最小只-1就是长度,这个横纵坐标就是最出口。
倒着走比自己数值少一的点,存入栈,就倒着走万这条路了。
void StackShortPath(Maze *pmaze, Stack *path)
{
int i = 0, j = N - 1;
int shortcount = N*N;
Pos cur;
for (i = 0; i < N; i++)
{
if (pmaze->_mz[i][j] != 0 && pmaze->_mz[i][j] < shortcount)
{
shortcount = pmaze->_mz[i][j];
cur._col = i;
cur._row = j;
}
}
printf(“the short path size is:%3d\n”, shortcount - 1);
printf(“the short path out is:(%d,%d)\n”, cur._col + 1, cur._row + 1);
Pos next = (Pos)malloc(sizeof(Pos));
StackPush(&path, &cur);
while (cur._col != pmaze->_entry->_col || cur._row != pmaze->_entry->_row)
{
cur = StackTop(path);
{
/下/
next->_col = cur._col + 1;
next->_row = cur._row;
if (pmaze->_mz[next->_col][next->_row] == pmaze->_mz[cur._col][cur._row] - 1)
{
StackPush(&path, next);
}
//上
next->_col = cur._col - 1;
next->_row = cur._row;
if (pmaze->_mz[next->_col][next->_row] == pmaze->_mz[cur._col][cur._row] - 1)
{
StackPush(&path, next);
}
//左
next->_col = cur._col;
next->_row = cur._row - 1;
if (pmaze->_mz[next->_col][next->_row] == pmaze->_mz[cur._col][cur._row] - 1)
{
StackPush(&path, next);
}
//右
next->_col = cur._col;
next->_row = cur._row + 1;
if (pmaze->_mz[next->_col][next->_row] == pmaze->_mz[cur._col][cur._row] - 1)
{
StackPush(&path, next);
}
}
}
StackPrint(path);
}
void MazeGetShortPath(Maze *pmaze)
{
Pos cur = *pmaze->_entry;
Pos next = (Pos)malloc(sizeof(Pos));
Stack path = (Stack )malloc(sizeof(Stack));
StackInit(&path, 10);
Stack shortpath = (Stack )malloc(sizeof(Stack));
StackInit(&shortpath, 10);
StackPush(&path, &cur);
pmaze->_mz[cur._col][cur._row] = 2;
int flag = 0;
while (StackEmpty(path) != 0)
{
if (cur._row == N - 1)
{
MazePrint(pmaze);
printf(“找到了\n”);
flag = 1;
}
cur = StackTop(path);
StackPop(path);
{ /*下*/ next->_col = cur._col + 1; next->_row = cur._row; if (MazeCheckIsAccess(pmaze, next)) { pmaze->_mz[next->_col][next->_row] = pmaze->_mz[cur._col][cur._row] + 1; StackPush(&path, next); } //上 next->_col = cur._col - 1; next->_row = cur._row; if (MazeCheckIsAccess(pmaze, next)) { pmaze->_mz[next->_col][next->_row] = pmaze->_mz[cur._col][cur._row] + 1; StackPush(&path, next); } //左 next->_col = cur._col; next->_row = cur._row - 1; if (MazeCheckIsAccess(pmaze, next)) { pmaze->_mz[next->_col][next->_row] = pmaze->_mz[cur._col][cur._row] + 1; StackPush(&path, next); } //右 next->_col = cur._col; next->_row = cur._row + 1; if (MazeCheckIsAccess(pmaze, next)) { pmaze->_mz[next->_col][next->_row] = pmaze->_mz[cur._col][cur._row] + 1; StackPush(&path, next); } } } free(next); if (flag == 0) { printf("没有出口\n"); } else { StackShortPath(pmaze, shortpath); } return ;
}
这里我们先引入所需要使用基本的函数 #include<stdio.h> #include<windows.h> #include <assert.h> typedef struct Pos { * int _col; int _row**; }Pos; typedef int Datatype;
typedef struct Stack{
Pos *_mz;
size_t _size;
size_t _capacity;
}Stack;
void StackInit(Stack** ps,size_t capacity)
{
assert(*ps);
(*ps)->_size = 0;
(*ps)->_capacity = capacity;
(ps)->_mz = (Pos )malloc(sizeof(Pos)*(*ps)->_capacity);
return;
}
Pos StackTop(Stack *s)
{
return s->_mz[s->_size-1];
}
void StackPush(Stack **pps, Pos *x)
{
assert(pps);
assert(*pps);
if ((*pps)->_size == (*pps)->_capacity)
{
(pps)->_capacity = 2;
(pps)->_mz = (Pos)realloc((pps)->_mz,(sizeof(Pos))(*pps)->_capacity);
}
assert(*pps);
((*pps)->_mz[(*pps)->_size])._col = x->_col;
((*pps)->_mz[(*pps)->_size])._row = x->_row;
(*pps)->_size++;
}
Pos *StackPop(Stack *ps)
{
return ps->_mz+(–ps->_size);
}
int StackEmpty(Stack *ps)
{
assert(ps);
return ps->_size;
}
void StackPrint(Stack *ps)
{
int i = 0;
for (i = ps->_size-1; i >= 0; i–)
printf(“(%d,%d)->”, ps->_mz[i]._col + 1, ps->_mz[i]._row + 1);
printf(“\n”);
}
以及迷宫的初始化等辅助函数
#pragma once
#include”Stack.h”
#define N 6
typedef struct Maze
{
Datatype _mz
;
Pos *_entry;
}Maze;
void MazeInit(Maze **pmaze,Datatype a
)
{
int i = 0,j = 0;
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
(*pmaze)->_mz[i][j] = a[i][j];
}
}
(*pmaze)->_entry = (Pos*)malloc(sizeof(Pos)); (*pmaze)->_entry->_col = 5; (*pmaze)->_entry->_row = 2;
}
void MazePrint(Maze *pmaze) {
int i = 0, j = 0;
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
printf(“%3d”, pmaze->_mz[i][j]);
}
printf(“\n”);
}
printf(“\n”);
}
int MazeCheckIsAccess(Maze pmaze ,Pos pos)
{
if (pos->_col >= 0 && pos->_col < N && pos->_row >= 0 && pos->_row < N)
{
if (pmaze->_mz[pos->_col][pos->_row] == 1)
return 1;
}
return 0;
}
相关文章推荐
- 复杂迷宫问题的递归实现以及最短路径
- 3.10 用栈实现解决迷宫问题(输出一条路径(非最短路径))
- 基于java最短路径算法公交查询系统的设计与实现
- 递归和栈求解迷宫的最短路径
- 关于栈与递归求解迷宫与迷宫最短路径问题
- 迷宫最短路径的C++实现(队列:广度优先)
- 迷宫最短路径的C++实现(队列:广度优先)
- BFS和DFS的差别,BFS实现迷宫最短路径
- 基于无向图且权重单一的最短路径Dijkstra算法——JAVA实现
- 使用opengl和c++实现迷宫地图的路径搜索和显示(基于DFS)
- 用并查集(find-union)实现迷宫算法以及最短路径求解
- 基于矩阵实现的最短路径算法
- 【数据结构】求多出口带环迷宫的最短路径(递归版本)
- 【数据结构】求多出口迷宫的最短路径(递归版本)
- java基础实践---非递归用栈实现查找迷宫路径
- 基于bfs搜索算法的迷宫最短路径游戏
- 基于队列的最短路径搜索算法(A*算法)实现
- 初学图论-Dijkstra单源最短路径算法基于优先级队列(Priority Queue)的实现
- A*算法--迷宫找最短路径(JAVA实现)
- 实现迷宫问题的所有路径及最短路径程序