【資料結構】棧 實現迷宮演算法
阿新 • • 發佈:2019-02-16
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> using namespace std; #define STACK_INIT_SIZE 100 #define STACKINCREMENT 10 #define TURE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 #define MAZE_X 20 #define MAZE_Y 20 typedef int Status; typedef struct{ int x; int y; }PosType;//座標位置 typedef struct{ int maze[MAZE_X][MAZE_Y];//迷宮地圖 PosType size;//實際的迷宮長、寬 PosType start;//起點的座標 PosType end;//重點的座標 }MazeType; typedef struct{ int ord; //通道塊在路徑上的序號; PosType seat; int di ;//通道塊走向下一個通道塊的方向 }SElemType;// 棧的元素型別 typedef struct{ SElemType* base; SElemType* top; int stacksize; }SqStack; int InitStack(SqStack &s){ //構造一個空棧 s.base = (SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType)); if(!s.base) exit(OVERFLOW); s.top=s.base; s.stacksize=STACK_INIT_SIZE; return OK; } int GetTop(SqStack s,SElemType &sElem){ //如果棧不空,用sElem返回s的棧頂元素,並返回OK if(s.top==s.base) return ERROR; sElem = *(s.top-1); return OK; } int Push(SqStack &s,SElemType sElem){ //插入sElem元素為新的棧頂元素 if(s.top-s.base>=s.stacksize){ //棧滿,追加儲存空間 s.base = (SElemType*) realloc(s.base,(s.stacksize+STACKINCREMENT)*sizeof(SElemType)); if(!s.base) return OVERFLOW; s.top = s.base+s.stacksize;//重新使top指向棧頂 s.stacksize+=STACKINCREMENT; } *s.top=sElem; s.top++; return OK; } int Pop(SqStack &s,SElemType &sElem){ //出棧操作 //若棧不空,則刪除棧頂元素,並用sElem返回其值 //失敗返回ERROR,成功返回OK if(s.base==s.top) return ERROR; sElem=*(--s.top); return OK; } int StackLength(SqStack s){//向下方向:1 //返回棧的元素個數,即棧的長度 return s.top-s.base; } int StackEmpty(SqStack s){ if(StackLength(s)==0) return TURE; else return FALSE; } int FootPrint(MazeType &m,PosType seat){//留下走過的標記 m.maze[seat.x][seat.y]=2;//將走過的位置標記為2 return TURE; } int MazeInit(MazeType &m){ // 初始化迷宮 int x,y; printf("輸入迷宮的長和寬(不超過%d): ",MAZE_X); scanf("%d%d",&x,&y);//迷宮的實際長寬 if(x>MAZE_X||x<0||y>MAZE_Y||y<0){ printf("x,y範圍不合法"); return ERROR;} printf("\n請輸入%d * %d 的迷宮,1代表通路,0代表牆\n",x,y); for(int i=0;i<x;i++){ for(int j=0;j<y;j++){ scanf("%d",&m.maze[i][j]);//初始化迷宮 } } printf("\n請輸入起點座標:"); scanf("%d%d",&(m.start.x),&(m.start.y));//設定起點 printf("\n請輸入終點座標: "); scanf("%d%d",&(m.end.x),&(m.end.y));// 重點 m.size.x=x;m.size.y=y; return OK; } int NextPos(MazeType m,SElemType &e,SqStack &s){//看上下左右方向是否可以走, 並且用 e 返回下一個通道的座標 //向下方向:1 //向右方向:2 //向上方向:3 //向左方向:4 if(e.seat.x<MAZE_X-1&&m.maze[e.seat.x+1][e.seat.y]==1){//如果可以向下走 (s.top-1)->di=1;//告訴棧頂元素下一個元素的位置 e.seat.x++;//向下走 return TURE;} if(e.seat.y<MAZE_Y-1&&m.maze[e.seat.x][e.seat.y+1]==1){//向右 (s.top-1)->di=2; e.seat.y++; return TURE;} if(e.seat.x>0&&m.maze[e.seat.x-1][e.seat.y]==1){// 向上 (s.top-1)->di=3; e.seat.x--; return TURE;} if(e.seat.y>0&&m.maze[e.seat.x][e.seat.y-1]==1){ //向左 (s.top-1)->di=4; e.seat.y--; return TURE;} return FALSE; //如果都不滿足,說明當前通道是死路 } int MazePath(MazeType &maze , SqStack &s){ InitStack(s);//構建一個空棧 SElemType e; e.seat.x = maze.start.x; //獲得初始座標 e.seat.y = maze.start.y; e.ord=1; Push(s,e); FootPrint(maze,e.seat); do{ if(NextPos(maze,e,s)){ //當前路徑可以繼續往下走,e 返回下一個路徑的座標 e.ord=s.top-s.base+1;//當前步數 Push(s,e);// 將下一個路徑作為當前路徑 FootPrint(maze,e.seat);//留下痕跡 if((e.seat.x==maze.end.x)&&(e.seat.y==maze.end.y)) return TURE;//如果到達終點,則停止 }else{//當前路徑不能往下走,死路 Pop(s,e);//後退一步 GetTop(s,e);//把後一步當作當前路徑 } }while(!StackEmpty(s)); //如果棧不為空,說明還有通道可以走 return FALSE; } void visitmaze(MazeType m){ //檢視走過後的迷宮 for(int i=0;i<m.size.x;i++){ printf("\n"); for(int j=0;j<m.size.y;j++){ printf("%d ",m.maze[i][j]); } } } int StackTraverse(SqStack s){ SElemType* p=s.base; for(;p<s.top;p++){ printf("第%d步 當前座標:(%d,%d) 下一方向:%d \n",p->ord,(p->seat.x),(p->seat.y),p->di); } } int main() { MazeType maze; SqStack s; MazeInit(maze); int i=MazePath(maze,s); printf("%d",i); visitmaze(maze); printf("\n"); StackTraverse(s); }