跪求高手 数据结构迷宫问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了跪求高手 数据结构迷宫问题相关的知识,希望对你有一定的参考价值。

一个以链表作存储结构的栈类型,然后编写一个求解迷宫的非递归程序。求得的通路以三元组(i,j,d)的形式输出,其中:(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。如:对于下列数据的迷宫,输出的一条通路为:(1,1,1),(1,2,2),(2,2,2)(3,2,3),(3,1,2)……
【测试数据之一】
迷宫的测试数据如下:左上角(1,1)为入口,右下角(9,8)为出口。

0 0 1 0 0 0 1 0
0 0 1 0 0 0 1 0
0 0 0 0 1 1 0 1
0 1 1 1 0 0 1 0
0 0 0 1 0 0 0 0
0 1 0 0 0 1 0 1
0 1 1 1 1 0 0 1
1 1 0 0 0 1 0 1
1 1 0 0 0 0 0 0

#define N 7 /*地图的第一维长度*/
#include <iostream.h>
#include <stdlib.h>
#include"ds.h"
#define O 5
#define P 5
typedef struct

int x;/* 行下标 */
int y;/* 列下标 */
int d;/* 运动方向 */
DataType;

struct StackNode /* 链栈类型定义 */

struct StackNode *next;
DataType s;
;

typedef struct StackNode *LinkStack; /* 链栈类型的指针类型 */

int createEmptyStack_seq(LinkStack &S)

S=NULL;
return OK;


int isEmptyStack_seq( LinkStack pastack )

if(pastack==NULL)
return TRUE;
else return FALSE;


/* 在栈顶压入一元素x */
void push_seq( LinkStack &pastack, DataType x )

LinkStack p;
p = (LinkStack)malloc(sizeof(struct StackNode));
p->s=x;
p->next=pastack;
pastack=p;


/* 删除栈顶元素 */
void pop_seq( LinkStack &pastack )

LinkStack p;
if (!isEmptyStack_seq(pastack) )

p=pastack;
pastack=pastack->next;
free(p);


else

cout<<"栈已空,没有元素出栈!\n";




/* 当pastack所指的栈不为空栈时,求栈顶元素的值 */
DataType top_seq( LinkStack pastack )

if (!isEmptyStack_seq(pastack) )
return (pastack->s);


void pushtostack(LinkStack &st, int x, int y, int d)
DataType element;
element.x = x;
element.y = y;
element.d = d;
push_seq(st, element);


void printpath(LinkStack st)

DataType element;
LinkStack S;
createEmptyStack_seq(S );
cout<<"The revers path is:\n"; /* 打印路径上的每一点 */
while(!isEmptyStack_seq(st))

element = top_seq(st);
pop_seq(st);
push_seq(S,element);


while(!isEmptyStack_seq(S))

element = top_seq(S);
pop_seq(S);
cout<<"("<<element.x<<","<<element.y<<","<<element.d+1<<")"<<endl;



/* 迷宫maze[M][N]中求从入口maze[x1][y1]到出口maze[x2][y2]的一条路径 */
/* 其中 1<=x1,x2<=M-2 , 1<=y1,y2<=N-2 */
void mazePath(int maze[][N], int direction[][2], int x1, int y1, int x2, int y2)

int i, j, k, g, h;
LinkStack st;
DataType element;
createEmptyStack_seq(st );
maze[x1][y1] = 2; /* 从入口开始进入,作标记 */
pushtostack(st, x1, y1, -1); /* 入口点进栈 */

while ( !isEmptyStack_seq(st)) /* 走不通时,一步步回退 */

element = top_seq(st);
pop_seq(st);
i = element.x; j = element.y;
for (k = element.d + 1; k <= 3; k++) /* 依次试探每个方向 */

g = i + direction[k][0];h = j + direction[k][1];
if (g == x2 && h == y2 && maze[g][h] == 0) /* 走到出口点 */

pushtostack(st, i, j, k);
printpath(st); /* 打印路径 */
return;


if (maze[g][h] == 0) /* 走到没走过的点 */

maze[g][h] = 2; /* 作标记 */
pushtostack(st, i, j, k); /* 进栈 */
i = g; j = h; k = -1; /* 下一点转换成当前点 */



cout<<"The path has not been found.\n";/* 栈退完未找到路径 */


int main()

int direction[][2]=0,1,1,0,0,-1,-1,0;
int i,j;
int a[O][P],maze[O+2][P+2];
cout<<"请用0,1来设置"<<O<<"*"<<P<<"阶的矩阵迷宫"<<endl;
for(i=0;i<O;i++)

for(j=0;j<P;j++)
cin>>a[i][j];

for(i=1;i<=O;i++)
for(j=1;j<=P;j++)
maze[i][j]=a[i-1][j-1];
for(j=0;j<P+2;j++)
maze[0][j]=maze[O+1][j]=1;
for(i=0;i<O+2;i++)
maze[i][0]=maze[i][P+1]=1;
mazePath(maze,direction,1,1,O,P);

return 0;

这是我做的,完全符合要求,迷宫大小可以宏定义的时候设定,“ds.h”文件自己加一下就好了啊!
参考技术A #include<iostream>
using namespace std;

const int MAP_SIZE = 100;

template<typename Comparable>
class Stack

public:
Stack() sPtr = NULL;
bool isEmpty() return sPtr == NULL;
void push( const Comparable &x ) sPtr = new Node( x, sPtr );
bool pop( Comparable &x )

if ( sPtr == NULL )
return false;
x = sPtr->data;
Node *tmp = sPtr;
sPtr = sPtr->next;
delete tmp;

return true;

~Stack()

Node *next = NULL;
for( Node *itr = sPtr; itr != NULL; itr = next )

next = itr->next;
delete itr;


private:
struct Node

Comparable data;
Node *next;
Node( const Comparable &d, Node *n = NULL )
: data( d ), next( n )
;
Node *sPtr;
;

enum Direction Right, Down, Left, Up, Begin ;
struct Position

int x, y;
Direction d;
Position( int _x = 0, int _y = 0, Direction _d = Begin )
: x( _x ), y( _y ), d( _d )
;

int map[ MAP_SIZE ][ MAP_SIZE ];
bool visited[ MAP_SIZE ][ MAP_SIZE ];
int mapHeight, mapWidth;
int move_x[] = 0, 1, 0, -1 ;
int move_y[] = 1, 0, -1, 0 ;

void readMap()

cout << "输入迷宫的高度和宽度" << endl;
cin >> mapHeight >> mapWidth;
cout << "输入地图" << endl;
int i, j;
for( i = 1; i <= mapHeight; i ++ )
for( j = 1; j <= mapWidth; j ++ )
cin >> map[ i ][ j ];

for( i = 1; i <= mapHeight; i ++ )
for( j = 1; j <= mapWidth; j ++ )
map[ i ][ j ] = false;


bool exitMaze( int bx, int by, int ex, int ey, int M, int N )

Position p( bx, by );
Position newPos;
Stack<Position> s;
s.push( p );
bool first = true;
while( !s.isEmpty() )

s.pop( p );
if ( first )
first = false;
else
cout << "," << p.d << ")" << endl;
cout << "(" << p.x << "," << p.y;
visited[ p.x ][ p.y ] = true;
if ( p.x == ex && p.y == ey )

cout << ")" << endl;
return true;

for( int i = 0; i < 4; i ++ )

newPos.x = p.x + move_x[ i ];
newPos.y = p.y + move_y[ i ];
newPos.d = (Direction)i;
if ( newPos.x >= 1 && newPos.x <= M
&& newPos.y >= 1 && newPos.y <= N
&& !visited[ newPos.x ][ newPos.y ]
&& map[ newPos.x ][ newPos.y ] == 0 )
s.push( newPos );



return false;


int main()

readMap();
int sx, sy, ex, ey;
cout << "请输入迷宫的起始坐标" << endl;
cin >> sx >> sy;
cout << "请输入迷宫的出口坐标" << endl;
cin >> ex >> ey;
if( exitMaze( sx, sy, ex, ey, mapHeight, mapWidth ) )
cout << "成功!" << endl;
else
cout << "失败!" << endl;

return 0;


/*
测试数据
9 8
0 0 1 0 0 0 1 0
0 0 1 0 0 0 1 0
0 0 0 0 1 1 0 1
0 1 1 1 0 0 1 0
0 0 0 1 0 0 0 0
0 1 0 0 0 1 0 1
0 1 1 1 1 0 0 1
1 1 0 0 0 1 0 1
1 1 0 0 0 0 0 0
1 1
9 8
*/

C语言 栈 迷宫 的一个疑问

if(Pass(curpos))
...
Push(S,e);
...
if(!StackEmpty(S))
Pop(S,e); curstep--;
...

如果下一步 未通过pass函数
即是未入栈,为何还要出栈,这样不是让上一个入的栈出栈了吗?
求高手解答,谢谢!

全部程序分几个文件,看清楚了,每段程序放入一个文件,每段程序前面都有文件名: //stackoperation.cpp Status InitStack(SqStack &S) //构造一个空栈S S.base = (SElemType *)malloc(RANGE*sizeof(SElemType)); if(!S.base) exit(OVERFLOW); //存储分配失败 S.top = S.base; S.stacksize = RANGE; return OK; //Initstack Status Push(SqStack &S,SElemType e) //插入元素e为新的栈顶元素 if(S.top - S.base >= S.stacksize)//栈满,追加存储空间 S.base = (SElemType*)realloc(S.base,(S.stacksize + STACKINCREMENT) * sizeof(SElemType)); if(!S.base) exit(OVERFLOW); //存储分配失败 S.top = S.base + S.stacksize; S.stacksize += STACKINCREMENT; *S.top++ = e; return OK; //Push Status Pop(SqStack &S,SElemType &e) /*若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK; 否则返回ERROR*/ if(S.top == S.base) return ERROR; e = * --S.top; return OK; //Pop bool StackEmpty(SqStack S) //判断栈是否为空并返回TURN或FALSE if(S.top == S.base) return TURE; return FALSE; //StackEmpty void PrintStack() SqStack ST; SElemType e; InitStack(ST); do Pop(SqS,e); Push(ST,e); while(!StackEmpty(SqS)); do Pop(ST,e); printf("(%d,%d,%d)",e.seat.i,e.seat.j,e.di); while(!StackEmpty(ST)); //migong.cpp #include "Basetype.h" #include "stackoperation.cpp" #include "Mazeoperation.cpp" void main() char filename[15]; FILE *fp; printf("请输入迷宫数据文件名(长度不超过15个字符):"); scanf("%s",&filename); //如找不到文件,则要求重新输入(最多三次机会) for(int i=0;i<3;i++) if((fp = fopen(filename,"r")) == NULL) printf("不能打开文件,请重新输入文件名(长度不超过15个字符):\n"); scanf("%s",filename); //if break; //for //读取迷宫的行数和列数 int rnum,cnum; fscanf(fp,"%d,%d",&rnum,&cnum); printf("这个迷宫有%d行,%d列\n",rnum,cnum); if(rnum>RANGE-2 || cnum>RANGE-2) printf("迷宫太大,无法求解\n"); return; //判断迷宫的大小是否符合要求 //初始化一个迷宫变量 MazeType maze; for(i=0;i<=rnum+1;i++) for(int j=0;j<=cnum+1;j++) maze.arr[i][j] = '#'; CreatMaze(maze,rnum,cnum,fp);//创建迷宫 fclose(fp);//关闭迷宫文件 //打印当前迷宫 printf("当前迷宫为:\n"); for(i=0;i<=rnum+1;i++) for(int j=0;j<=cnum+1;j++) printf("%c",maze.arr[i][j]); printf("\n"); printf("其中'#'表示障碍,外围一圈'#'为围墙\n"); //读取入口及出口位置 PosType startp,endp; printf("请输入入口位置(两数中间以逗号相隔):"); scanf("%d,%d",&startp.i,&startp.j); printf("请输入出口位置(两数中间以逗号相隔):"); scanf("%d,%d",&endp.i,&endp.j); if(MazePath(maze,startp,endp)) PrintMaze(maze,rnum,cnum);//将求解的迷宫输出到文件保存,并打印到屏幕 PrintStack();//如果存在路径则打印之 else printf("此迷宫不存在路径\n"); //main //Mazeoperation.cpp bool Pass(MazeType maze,PosType curpos) //判断当前位置是否可通,并返回值 switch(char ch = maze.arr[curpos.i][curpos.j]) case' ': return(FALSE); case'#': case'@': case'*': return(TURE); default: printf("迷宫中第%d行,第%d列出现不明字符%c\n", curpos.i,curpos.j,ch);exit(0); //switch //pass void FootPrint(MazeType &maze,PosType curpos) maze.arr[curpos.i][curpos.j] = '*'; //FootPrint void MarkPrint(MazeType &maze,PosType curpos) maze.arr[curpos.i][curpos.j] = '@'; //MarkPrint void NextPos(PosType &curpos,int di) switch(di) case 1: curpos.j++;break; case 2: curpos.i++;break; case 3: curpos.j--;break; case 4: curpos.i--;break; default: printf("当前方向%d无效\n",di); exit(0); //switch //NextPos bool MazePath(MazeType &maze,PosType start,PosType end) SElemType e; InitStack(SqS); PosType curpos = start; int curstep = 1; do if(!Pass(maze,curpos)) FootPrint(maze,curpos); e.order = curstep; e.seat.i = curpos.i;e.seat.j = curpos.j; e.di = 1; Push(SqS,e); if(curpos.i == end.i && curpos.j == end.j) return(TURE); NextPos(curpos,1); curstep++; //if else if(!StackEmpty(SqS)) Pop(SqS,e); while(e.di == 4 && !StackEmpty(SqS)) MarkPrint(maze,e.seat); Pop(SqS,e); //while if(e.di<4) e.di++; Push(SqS,e); NextPos(e.seat,e.di); curpos.i = e.seat.i;curpos.j = e.seat.j; //if //if //else while(!StackEmpty(SqS)); return(FALSE); //Mazepath void CreatMaze(MazeType &maze,int row,int col,FILE *fp) //建立迷宫 char ch = fgetc(fp); for(int i=1;i<=row;i++) for(int j=1;j<=col;j++) switch( ch = fgetc(fp)) case'0': maze.arr[i][j]=' ';break; case'1': maze.arr[i][j]='#';break; default: printf("迷宫第%d行第%d列数据为%c有错误",i,j,ch);exit(0); //switch //for fseek(fp,2,1); //for fclose(fp); //CreatMaze void PrintMaze(MazeType maze,int row,int col) //打印结果并输出到文件保存 FILE *out; if((out = fopen("outfile","w"))==NULL) printf("不能打开文件\n"); exit(0); //if for(int i=0;i<=row+1;i++) for(int j=0;j<=col+1;j++) fputc(maze.arr[i][j],out); printf("%c",maze.arr[i][j]); printf("\n"); printf("其中'*'号代表路径,'#'代表障碍,'@'代表死胡同\n"); fclose(out);//关闭文件 //Basetype.h #include <stdio.h> #include "stdlib.h" #define RANGE 30 //栈的存储空间初始分配量, //以及用来存放迷宫的字符数组的最大维数 #define TURE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define OVERFLOW -1 #define STACKINCREMENT 5 //栈的存储空间分配增量 typedef struct int i; //行坐标 int j; //列坐标 PosType; //迷宫中坐标位置类型 //栈的定义 typedef struct int order; //通道块在路径上的“方向” PosType seat; //通道块在迷宫中的“坐标位置” int di; //从此通道块走向下一通道块的“方向” SElemType; //栈的元素类型 typedef struct SElemType *base; //栈底指针 SElemType *top; //栈顶指针 int stacksize; //当前已分配的存储空间,以元素为单位 SqStack; //迷宫的定义 typedef struct int m,n; char arr[RANGE][RANGE]; MazeType; typedef int Status; SqStack SqS; //定义一个栈~ 参考技术A 下一步,未通过pass函数说明,这条路径是不可行的,是一个死胡同。
所以就出栈,这是回溯法啊。
当前入栈的位置是到达不了终点的,所以就出栈。返回上一位置,寻找不同路径。本回答被提问者采纳
参考技术B 是这样的
如果Pass返回值=false 代表不通过,则需要退一格 也就是退栈一次pop(),再判断Pass
不知道你的问题在哪里追问

可既然未通过,那么就不会执行NextPos函数了,就是在原地保持不动啊,退一格不是退回上一个位置了?

追答

你的Pass函数只判单方向吗 还是判断该位置是不是死路

贴一些你想问问题的代码段

追问

代码是对的,能实现,但是我对它的实现过程有些不理解
我就是问
当下一个位置不能通过Pass函数时,那么此时栈里面的元素仍然是原来的元素,没有增加。那么进入else,既然未增加元素,为何还要Push?这样不是把上一个元素出栈了吗?

以上是关于跪求高手 数据结构迷宫问题的主要内容,如果未能解决你的问题,请参考以下文章

迷宫问题

迷宫问题

数据结构之迷宫问题求解迷宫的最短路径

数据结构设计——用栈实现迷宫问题的求解

数据结构设计——用队列实现迷宫问题的求解

数据结构小设计--(迷宫问题Python版本)