数据结构应用实例#栈#迷宫寻路

使用数据结构 栈(Stack)来实现一种低级的迷宫寻路的功能。
低级是因为无法判断路径是不是最短的。

这里使用的栈结构如图 (这图我选择死亡...)


注意结构体里DataType的实际含义,是另外一个结构体,用于储存二维位置x,y

地图使用一个10x10的二维数组来表示,数字1表示该点是墙壁,0表示可以行走,2表示已经走过的地方。

我们用栈来储存走过的位置,比如我们从起点(4,0)出发,就把(4,0)压入栈,并把该点数值改为2,意为已经来过了。
如果遇到死路,那就不停地出栈,直到栈顶的这个点周围有路可走为止。

逻辑部分伪代码如下

while(没有到达终点)
{
  if(上下左右四个方向有路可走)
  {
    将可以走的那个位置(不是当前位置!)压入栈
  }
  else
  {
    出栈
  }
}

首先是栈的头文件,注意栈结构体内容的具体定义

Stack.h

 1 #ifndef _STACK_H_
 2 #define _STACK_H_
 3
 4 #include<stdio.h>
 5 #include<stdlib.h>
 6
 7 //以下两个数据大小视实际情况而定
 8 //初始栈容量
 9 #define STACK_INIT_SIZE 20
10 //每次扩容的增量
11 #define STACKINCREMENT 10
12
13 //迷宫地图
14 int Maze[10][10];
15
16 //表示位置
17 struct xy
18 {
19     int x, y;
20 };
21 typedef struct xy XY;
22 typedef  XY DataType;
23
24 struct stack
25 {
26     //指向栈最顶上的元素的接下来一个位置
27     //表示新入栈的值可以放在指向的地方
28     DataType *Top;
29     //指向栈底部,最里面的元素
30     DataType *Bottom;
31     //表示了当前栈的容量
32     int stacksize;
33 };
34 typedef struct stack STACK;
35
36 //新建栈
37 int InitStack(STACK *S);
38
39 //销毁栈
40 int DestroyStack(STACK *S);
41
42 //返回顶层元素
43 int GetTop(STACK S,int *x,int *y);
44
45 //Push操作,入栈,压栈
46 int Push(STACK *S, int x,int y);
47
48 //Pop操作,出栈
49 int Pop(STACK *S);
50
51 #endif

然后是定义

Stack.c

 1 #include"Stack.h"
 2
 3 int InitStack(STACK *S)
 4 {
 5     //创建出设定长度的顺序表,地址赋给bottom指针
 6     S->Bottom = (DataType*)malloc(STACK_INIT_SIZE*sizeof(DataType));
 7     if (!S->Bottom)
 8     {
 9         return 0;
10     }
11     S->stacksize = STACK_INIT_SIZE;
12     S->Top = S->Bottom;
13     return 1;
14 }
15
16 int DestroyStack(STACK *S)
17 {
18     S->Top = NULL;
19     free(S->Bottom);
20     S->Bottom = NULL;
21     return 1;
22 }
23
24 int GetTop(STACK S, int *x, int *y)
25 {
26     if (S.Bottom != S.Top)
27     {
28         //由于top指向的是最顶上元素的下一个位置
29         //所以取出最顶上元素的时候
30         //要把top减去1
31         *x = ((S.Top - 1)->x);
32         *y = ((S.Top - 1)->y);
33         return 1;
34     }
35     return 0;
36 }
37
38 int Push(STACK *S, int x,int y)
39 {
40     //当超出当前栈的容量时
41     //这里应该只有等于的情况
42     //而不会大于
43     if ((S->Top - S->Bottom) >= S->stacksize)
44     {
45         //realloc函数将开辟指定的储存空间
46         //并将原来的数据全部移到这个新的储存空间
47         S->Bottom = (DataType*)realloc(S->Bottom, (S->stacksize + STACKINCREMENT)*sizeof(DataType));
48         if (!S->Bottom)
49         {
50             return 0;
51         }
52         //由于重新开辟了空间
53         //需要重新根据bottom指针的位置指定top
54         S->Top = S->Bottom + S->stacksize;
55         //最后增加当前栈容量
56         S->stacksize += STACKINCREMENT;
57     }
58     //再把入栈的数据存放好
59     (S->Top)->x = x;
60     (S->Top)->y = y;
61     S->Top++;
62
63     //在地图上将该点标为2
64     Maze[x][y] = 2;
65     return 1;
66 }
67
68 //将该点丢弃
69 int Pop(STACK *S)
70 {
71     if (S->Bottom == S->Top)
72     {
73         printf("Empty Stack!Can not pop!\n");
74         return 0;
75     }
76     //top指针先减1再取值
77     --S->Top;
78     return 1;
79 }

寻路的逻辑放在了main函数里,迷宫地图的定义也在这里

main.c

二维数组Maze存放了迷宫的信息,你也可以自己改改*。

  1 #include"Stack.h"
  2
  3 #define Up 1
  4 #define Right 2
  5 #define Down 3
  6 #define Left 4
  7 //代表已无路可走
  8 //End of Road
  9 #define EOR 5
 10
 11 //迷宫的地图
 12 //墙壁表示为1,可走的地方表示为0,走过的地方表示为2
 13 //入口为(4,0),出口为(0,8)
 14 //可自行更改,但请确保有通路
 15
 16 Maze[10][10] = {
 17 //0,1,2,3,4,5,6,7,8,9
 18 1,1,1,1,1,1,1,1,0,1,     //0
 19 1,0,0,0,0,0,0,1,0,1,     //1
 20 1,0,1,0,1,1,1,1,0,1,     //2
 21 1,0,1,0,1,0,0,0,0,1,     //3
 22 0,0,1,0,1,0,1,0,1,1,     //4
 23 1,0,1,0,1,0,1,0,1,1,     //5
 24 1,1,0,0,1,0,1,0,1,1,     //6
 25 1,0,0,1,1,0,1,0,1,1,     //7
 26 1,0,0,0,0,0,1,0,0,1,     //8
 27 1,1,1,1,1,1,1,1,1,1 };  //9
 28
 29 //打印结果
 30 int Print()
 31 {
 32     int lop, lop2;
 33     for (lop = 0; lop < 10; lop++)
 34     {
 35         for (lop2 = 0; lop2 < 10; lop2++)
 36         {
 37             if (Maze[lop][lop2] == 2)
 38             {
 39                 printf("1");
 40             }
 41             else
 42             {
 43                 printf(" ");
 44             }
 45         }
 46         printf("\n");
 47     }
 48     return 1;
 49 }
 50
 51 int GameOver(STACK s, XY *loc,XY End)
 52 {
 53     GetTop(s, &(loc->x), &(loc->y));
 54     if (loc->x == End.x && loc->y == End.y)
 55     {
 56         return 1;
 57     }
 58     else
 59     {
 60         return 0;
 61     }
 62 }
 63
 64 //1 up.2 right.3 down.4 left
 65 //看看当前位置的上下左右还有没有能走的地方
 66 int SearchPath(STACK s, XY loc)
 67 {
 68     int x, y;
 69     x = loc.x;
 70     y = loc.y;
 71
 72     //Up Available?
 73     if (x != 0)
 74     {
 75         if (!Maze[x - 1][y])
 76         {
 77             return Up;
 78         }
 79     }
 80     //Right ?
 81     if (y != 9)
 82     {
 83         if (!Maze[x][y + 1])
 84         {
 85             return Right;
 86         }
 87     }
 88     //Down?
 89     if (x != 9)
 90     {
 91         if (!Maze[x + 1][y])
 92         {
 93             return Down;
 94         }
 95     }
 96     //Left?
 97     if (y != 0)
 98     {
 99         if (!Maze[x][y - 1])
100         {
101             return Left;
102         }
103     }
104     return EOR;
105 }
106
107 int main()
108 {
109     //储存走出迷宫的路径
110     STACK Path;
111     //储存当前位置
112     XY loc;
113     //起点终点的位置
114     XY Start = { 4,0 }, End = { 0,8 };
115
116     InitStack(&Path);
117     //将起点入栈
118     Push(&Path, Start.x, Start.y);
119
120     //开始
121     while (!GameOver(Path, &loc, End))
122     {
123         switch (SearchPath(Path, loc))
124         {
125         case Up:
126             Push(&Path, loc.x - 1, loc.y);
127             break;
128         case Right:
129             Push(&Path, loc.x, loc.y + 1);
130             break;
131         case Down:
132             Push(&Path, loc.x + 1, loc.y);
133             break;
134         case Left:
135             Push(&Path, loc.x, loc.y - 1);
136             break;
137         case EOR:
138             Pop(&Path);
139             break;
140         default:
141             printf("Shit Happened! Check your code!\n");
142             break;
143         }
144     }
145     Print();
146     DestroyStack(&Path);
147     return 0;
148 }

最后运行结果如图

有一行多出来的1,因为打印的是走过的路径。

*如果你想自己更改迷宫地图的话,请务必记得更改相应的起点和终点(114行)

时间: 2024-09-27 01:17:24

数据结构应用实例#栈#迷宫寻路的相关文章

数据结构应用实例#栈&amp;单链表#简易计算器

使用数据结构中的栈以及链表来制作一个能够处理中缀表达式的计算程序. 在该程序中输入的数字可以是任意正数.小数.(忘了添加对负数的支持,尽快补上) 输入的运算符可以是 + - * / ( ) 但请确保输入的表达式合法. 中缀表达式: 形如 9+(3-1)*3+10/2 的数学表达式.特点是运算符在被运算的两个数字中间,也就是我们日常接触的算式. 后缀表达式: 以上面的中缀表达式 9+(3-1)*3+10/2 为例 转换成后缀表达式为 9 3 1-3*+ 10 2/+ 特点是运算符紧跟在被运算的两个

SDUT 2449 数据结构实验之栈与队列十:走迷宫

数据结构实验之栈与队列十:走迷宫 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 一个由n * m 个格子组成的迷宫,起点是(1, 1), 终点是(n, m),每次可以向上下左右四个方向任意走一步,并且有些格子是不能走动,求从起点到终点经过每个格子至多一次的走法数. Input 第一行一个整数T 表示有T 组测试数据.(T <= 110) 对于每组测试数据: 第一行两个整数n, m,表示迷宫有n * m 个格子.(1

SDUT-2449_数据结构实验之栈与队列十:走迷宫

数据结构实验之栈与队列十:走迷宫 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 一个由n * m 个格子组成的迷宫,起点是(1, 1), 终点是(n, m),每次可以向上下左右四个方向任意走一步,并且有些格子是不能走动,求从起点到终点经过每个格子至多一次的走法数. Input 第一行一个整数T 表示有T 组测试数据.(T <= 110) 对于每组测试数据: 第一行两个整数n, m,表示迷宫有n * m 个格子.(1

数据结构快速回顾——栈

堆栈,也可直接称栈,是一种特殊的串行形式的数据结构,它的特殊之处在于只能允许在链结串行或阵列的一端进行加入资料和输出资料的运算.另外堆栈也可以用一维阵列或连结串行的形式来完成. 1 #define STACK_INIT_SIZE 100 2 #define STACKINCREMENT 10 3 4 typedef struct 5 { int* top; 6 int* base; 7 int stacksize; 8 }SqStack; 9 10 int InitStack(SqStack &

javascript数据结构与算法---栈

在上一遍博客介绍了下列表,列表是最简单的一种结构,但是如果要处理一些比较复杂的结构,列表显得太简陋了,所以我们需要某种和列表类似但是更复杂的数据结构---栈.栈是一种高效的数据结构,因为数据只能在栈顶添加或删除,所以这样操作很快,而且容易实现. 一:对栈的操作. 栈是一种特殊的列表,栈内的元素只能通过列表的一端访问,这一端陈为栈顶.比如餐馆里面洗盘子,只能先洗最上面的盘子,盘子洗完后,也只能螺到这一摞盘子的最上面.栈被称为 "后入先出"(LIFO)的数据结构. 由于栈具有后入先出的特点

两种特殊的数据结构:队列和栈

一.队列 队列(Queue:本文要介绍的第一种数据结构):只能从线性表的一端添加(offer)元素,从另一端取出(poll)元素,并遵循FIFO(先进先出) 选择LinkedList来实现Queue接口,因为LinkedList在插入删除的操作方面效率较高 相关操作: boolean offer(E e):将元素追加到队列末尾 E poll():删除并返回队首元素 E peek():仅返回队首元素,不删除 实例编程: 1 package Java20170331; 2 3 import java

数据结构实验之栈:进制转换

            数据结构实验之栈:进制转换 输入一个十进制整数,将其转换成对应的R(2<=R<=9)进制数,并输出. 输入 第一行输入需要转换的十进制数:第二行输入R. 输出 输出转换所得的R进制数. 模板: while(n!=0) { mod = n%r; q[i++] = mod;//i初始化为0 n/=r; }  

数据结构实验之栈:行编辑器

数据结构实验之栈:行编辑器 题目描述 一个简单的行编辑程序的功能是:接受用户从终端输入的程序或数据,并存入用户的数据区. 由于用户在终端上进行输入时,不能保证不出差错,因此,若在编辑程序中,“每接受一个字符即存入用户数据区”的做法显然不是最恰当的.较好的做 法是,设立一个输入缓冲区,用以接受用户输入的一行字符,然后逐行存入用户数据区.允许用户输入出差错,并在发现有误时可以及时更正.例如,当用户发现刚 刚键入的一个字符是错的时,可补进一个退格符"#",以表示前一个字符无效: 如果发现当前

SDUT OJ 1479 数据结构实验之栈:行编辑器

数据结构实验之栈:行编辑器 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 一个简单的行编辑程序的功能是:接受用户从终端输入的程序或数据,并存入用户的数据区. 由于用户在终端上进行输入时,不能保证不出差错,因此,若在编辑程序中,“每接受一个字符即存入用户数据区”的做法显然不是最恰当的.较好的做 法是,设立一个输入缓冲区,用以接受用户输入的一行字符,然后逐行存入用户数据区.允许用户输入出差错,并在发现有误时可以及时更正.例如,当