您的位置:首页 > 其它

迷宫基于栈的实现--最短路径的非递归实现

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);

{
/*下*/
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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: