利用栈实现迷宫求解
-
前言:众所周知,栈是(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
