利用栈实现迷宫求解
-
前言:众所周知,栈是(First in last out)先进后出的数据结构,利用这个属性可以实现类似与回溯的方式,比如当前数据满足条件,则入栈,否则出栈返回上一级,依次循环。
-
在本题中,将每个迷宫路径上的点封装成上下左右四个方向数节点,先入栈迷宫入口节点,如果上下左右没被使用,则将其上下左右的点入栈,否则出栈。如果最终达到迷宫终点则成功,否则失败。
如下是每个节点的数据结构
1 typedef struct{ 2 int top; 3 int bottom; 4 int left; 5 int right; 6 }direction; //方向 7 8 typedef struct{ 9 int x; 10 int y; 11 }point; //位置 12 13 14 typedef struct StackNode{ 15 direction direct; 16 point position; 17 struct StackNode *next;//指向下一个节点 18 }*LinkStackPtr;//节点数据结构
链栈及基本操作实现
1 typedef struct{ 2 LinkStackPtr top;//指向链栈头 3 int count;//节点个数 4 }LinkStack;//定义链栈 5 6 7 bool isEmpty(LinkStack L){ 8 if(L.count==1)return true; 1表示迷宫入口 9 return false; 10 } 11 12 Status createLink(LinkStack &L){ 13 L.top=(LinkStackPtr)malloc(sizeof(StackNode)); 14 if(!L.top)exit(OVERFLOW);// L.top=NULL; //创建链表 15 L.count++; 16 return OK; 17 } 18 19 LinkStackPtr GetTop(LinkStack L){ 20 return L.top; //放回头结点 21 } 22 23 24 Status Push(LinkStack &L,LinkStackPtr s){ 25 s->next=L.top; 26 L.top=s; 27 L.count++; //入栈 28 return OK; 29 } 30 31 32 Status Pop(LinkStack &L){ 33 LinkStackPtr p; 34 if(isEmpty(L)){ 35 return ERROR; 36 } 37 p=L.top; //出栈 38 L.top=L.top->next; 39 free(p); 40 L.count--; 41 return OK; 42 }
以下是预定义及用数组实现的迷宫地图:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<malloc.h> 4 5 6 #define OK 1 7 #define ERROR 0 8 #define OVERFLOW -2 9 10 #define size 8 11 12 13 int enterx,entery;//入口坐标 14 int exitx,exity;//出口坐标 15 16 17 int map[size][size]={ 18 {1,1,1,0,1,1,1,1}, 19 {1,1,1,0,1,1,1,1}, 20 {1,0,0,0,1,0,1,1}, 21 {1,1,1,0,1,0,1,1}, 22 {1,1,1,0,0,0,1,1}, 23 {1,1,1,0,1,1,1,1}, 24 {1,1,1,0,0,0,0,0}, 25 {1,1,1,1,1,1,1,1} 26 };//迷宫地图,1代表墙壁 0代表路 27 28 29 void findMap(int map[][size]){ 30 enterx=entery=0; 31 exitx=exity=0; 32 for(int i=0;i<size;i++){ 33 for(int j=0;j<size;j++){ 34 if((i==0||i==size-1)&&map[i][j]==0){ 35 enterx=i; 36 entery=j; 37 } 38 if((j==0||j==size-1)&&map[i][j]==0){ 39 exitx=i; 40 exity=j; 41 } 42 } 43 }//搜寻地图的入口和出口 44 if((enterx==exitx)&&(entery==exity)){//出入口相同或者没有出入口则迷宫无解 45 printf("该迷宫无解"); 46 system("pause"); 47 exit(ERROR); 48 } 49 } 50 51 void printMap(int a[][size]){ 52 for(int i=-0;i<size;i++){ 53 for(int j=0;j<size;j++){ 54 printf("%d ",a[i][j]);//打印迷宫 55 } 56 printf("\n");// 57 } 58 }
以下是主函数和实现:
1 bool panduan(int x,int y){ 2 if(map[x][y]==0){ 3 return true; 4 }return false; 5 } //判断是否是没走过的迷宫快 6 7 8 9 main(){ printMap(map); 10 bool flag=false; 11 LinkStack L; 12 createLink(L);//创建链表 13 14 15 LinkStackPtr p; 16 p=(LinkStackPtr)malloc(sizeof(struct StackNode)); 17 p->position.x=enterx; 18 p->position.y=entery; 19 p->direct.top=1; 20 p->direct.right=0; 21 p->direct.left=0; 22 p->direct.bottom=0;//插入迷宫的入口 23 map[p->position.x][p->position.y]=2; 24 Push(L,p); 25 26 27 while(!isEmpty(L)){ 28 LinkStackPtr q; 29 q=GetTop(L); 30 if(q->position.x==exitx&&q->position.y==exity){ 31 flag=true; 32 break; 33 } //到达迷宫终点,结束返回 34 35 36 37 if(q->direct.top==0){//向上走 38 if(q->position.x-1>=0){//如果在迷宫范围内 39 if(panduan(q->position.x-1,q->position.y)){//判断走否是没走过的迷宫快 40 q->direct.top=1;//向上置为1,表示已经走过 41 LinkStackPtr m=(LinkStackPtr)malloc(sizeof(struct StackNode)); 42 43 m->position.x=q->position.x-1; 44 m->position.y=q->position.y; 45 46 m->direct.bottom=1; 47 m->direct.left=0; 48 m->direct.right=0; 49 m->direct.top=0;//插入向上的迷宫快 50 51 map[m->position.x][m->position.y]=2; 52 Push(L,m);//迷宫快入栈 53 }else{ 54 q->direct.top=1; 55 } 56 } 57 } 58 else if(q->direct.right==0){ 59 if(q->position.y+1<8){ 60 if(panduan(q->position.x,q->position.y+1)){ 61 q->direct.right=1; 62 LinkStackPtr m=(LinkStackPtr)malloc(sizeof(struct StackNode)); 63 64 m->position.x=q->position.x; 65 m->position.y=q->position.y+1; 66 67 m->direct.bottom=0; 68 m->direct.left=1; 69 m->direct.right=0; 70 m->direct.top=0; 71 72 map[m->position.x][m->position.y]=2; 73 Push(L,m); 74 }else{ 75 q->direct.right=1; 76 } 77 } 78 } 79 else if(q->direct.bottom==0){ 80 if(q->position.x+1<8){ 81 if(panduan(q->position.x+1,q->position.y)){ 82 q->direct.bottom=1; 83 LinkStackPtr m=(LinkStackPtr)malloc(sizeof(struct StackNode)); 84 85 m->position.x=q->position.x+1; 86 m->position.y=q->position.y; 87 88 m->direct.bottom=0; 89 m->direct.left=0; 90 m->direct.right=0; 91 m->direct.top=1; 92 93 map[m->position.x][m->position.y]=2; 94 Push(L,m); 95 }else{ 96 q->direct.bottom=1; 97 } 98 } 99 } 100 else if(q->direct.left==0){ 101 if(q->position.y-1>=0){ 102 if(panduan(q->position.x,q->position.y-1)){ 103 q->direct.left=1; 104 LinkStackPtr m=(LinkStackPtr)malloc(sizeof(struct StackNode)); 105 106 m->position.x=q->position.x; 107 m->position.y=q->position.y-1; 108 109 m->direct.bottom=0; 110 m->direct.left=0; 111 m->direct.right=1; 112 m->direct.top=0; 113 114 map[m->position.x][m->position.y]=2; 115 Push(L,m); 116 }else{ 117 q->direct.left=1; 118 } 119 } 120 }else if(q->direct.left==1&&q->direct.right==1&&q->direct.top==1&&q->direct.bottom==1){ 121 map[q->position.x][q->position.y]=0; 122 Pop(L); 123 } 124 125 126 127 128 } 129 //判断是否找到路径 130 if(flag==true){ 131 132 printf("成功找到路径,0:未走路径 1:墙壁 2:迷宫路径 \n"); 133 printMap(map); 134 }else{ 135 printf("未找到路径"); 136 } 137 138 139 140 141 }
运行结果:
改进:将数组的长度以及出口和入口的坐标预定义便于改变。
来源:https://www.cnblogs.com/cxyc/p/5322406.html