数据结构算法C语言实现--- 3.2栈的应用举例:迷宫求解与表达式求值

Posted 苟不利包子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构算法C语言实现--- 3.2栈的应用举例:迷宫求解与表达式求值相关的知识,希望对你有一定的参考价值。

  一.简介

  迷宫求解:类似图的DFS。具体的算法思路可以参考书上的50、51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意。大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚,所以很多需要自己揣摩。这也体现了算法和程序设计语言的特点,算法更侧重本质的描述,而任何编程语言都要照顾到实现的细节以及数据类型等语法方面的需求。

  表达式求值:

  由于数据的读入是按照字符读入的,所以这个简单的小程序只能计算个位数的运算。

  二.头文件

  迷宫求解:

  1 //3_2_maze.h
  2 /**
  3 author:zhaoyu
  4 email:zhaoyu1995.com@gmail.com
  5 date:2016-6-8
  6 note:realize my textbook <<数据结构(C语言版)>>
  7 */
  8 //Page 51
  9 #ifndef _3_2_MAZE_H
 10 #define _3_2_MAZE_H 
 11 #include <cstdio>
 12 #include <cstdlib>
 13 #include <cstring>
 14 #include "head.h"
 15 #define STACK_INIT_SIZE 200//存储空间的初始分配值
 16 #define STACKINCREMENT 10//存储空间分配增量
 17 #define WALL -1
 18 #define PATH 1
 19 #define PASSED -2
 20 #define UNREACHABLE -3 
 21 #define FINALPATH -4 
 22 #define NMAX 50
 23 char Map[NMAX][NMAX];
 24 typedef struct{
 25     int x;
 26     int y;
 27 }PosType;
 28 typedef struct node_1{
 29     int x, y;
 30     struct node_1 *next;
 31 }MazeType;
 32 typedef struct{
 33     int ord;//通道块在路径上的序号
 34     PosType seat;//通道块在迷宫中的位置
 35     int direction;//从此通道块走向下一通道块的方向
 36 }SElemType;
 37 typedef struct{
 38     SElemType *base;//在栈构造之前和销毁之后,base 值为 NULL
 39     SElemType *top;//栈顶指针
 40     int stacksize;//当前已分配的存储空间,以元素为单位
 41 }SqStack;
 42 Status InitStack(SqStack &S)
 43 {
 44     //构造一个空栈 S
 45     S.base = (SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
 46     if (!S.base)
 47     {
 48         exit(OVERFLOW);
 49     }
 50     S.top = S.base;
 51     S.stacksize = STACK_INIT_SIZE;
 52     return OK;
 53 }//InitStack
 54 void Assign_PosType(PosType &a, PosType b)
 55 {
 56     a.x = b.x;
 57     a.y = b.y;
 58 }//Assign_PosType
 59 Status Pass(PosType pos)
 60 {//可能写的不对,注意
 61     if (PATH == Map[pos.x][pos.y])
 62     {
 63         return TRUE;
 64     }
 65     else
 66     {
 67         return FALSE;
 68     }
 69 }//Pass
 70 void FoorPrint(PosType pos)
 71 {
 72     Map[pos.x][pos.y] = PASSED;
 73 }
 74 void Assign_SELemType(SElemType &e, int x, PosType pos, int y)
 75 {
 76     e.ord = x;
 77     Assign_PosType(e.seat, pos);
 78     e.direction = y;
 79 }
 80 Status Push(SqStack &S, SElemType e)
 81 {
 82     //插入元素 e 为新的栈顶元素
 83     if (S.top - S.base >= S.stacksize)
 84     {//栈满,追加存储空间
 85         S.base = (SElemType *)realloc(S.base,
 86             (S.stacksize+STACKINCREMENT)*sizeof(SElemType));
 87         if (!S.base)
 88         {
 89             exit(OVERFLOW);
 90         }
 91         S.top = S.base + S.stacksize;
 92         S.stacksize += STACKINCREMENT;
 93     }
 94     //*S.top++ = e;
 95     Assign_SELemType(*S.top++, e.ord, e.seat, e.direction);
 96     return OK;
 97 }//Push
 98 PosType NextPos(PosType pos, int direction)
 99 {
100     PosType temp;
101     switch (direction)
102     {
103         case 1:
104         {
105             temp.x = pos.x;
106             temp.y = pos.y+1;
107             break;
108         }
109         case 2:
110         {
111             temp.x = pos.x + 1;
112             temp.y = pos.y;
113             break;
114         }
115         case 3:
116         {
117             temp.x = pos.x;
118             temp.y = pos.y - 1;
119             break;
120         }
121         case 4:
122         {
123             temp.x = pos.x - 1;
124             temp.y = pos.y;
125             break;
126         }
127     }
128     //加一个越界检查
129     return temp;
130 }
131 Status StackEmpty(SqStack S)
132 {
133     //若 S 为空栈, 则返回 TRUE, 否则返回 FALSE
134     if (S.base == S.top)
135     {
136         return TRUE;
137     }
138     else
139     {
140         return FALSE;
141     }
142 }
143 Status Pop(SqStack &S, SElemType &e)
144 {
145     //若栈不空,则删除 S 的栈顶元素,用 e 返回其
146     //值,并返回OK;否则返回ERROR
147     if (S.top == S.base)
148     {
149         return ERROR;
150     }
151     //e = *--S.top;
152     S.top--;
153     Assign_SELemType(e, (*S.top).ord, (*S.top).seat, (*S.top).direction);
154     return OK;
155 }//Pop
156 void FootPrint(PosType pos)
157 {
158     Map[pos.x][pos.y] = PASSED;    
159 }
160 void MarkPrint(PosType pos)
161 {
162     Map[pos.x][pos.y] = UNREACHABLE;
163 }
164 void MakeMap(int size)
165 {
166     memset(Map, 0, sizeof(Map));
167     char ch;
168     getchar();
169     for (int i = 1; i <= size; i++)
170     {
171         for (int j = 1; j <= size; j++)
172         {
173             scanf("%c", &ch);
174             if (\'X\' == ch)
175             {
176                 Map[i][j] = UNREACHABLE;
177             }
178             else
179             {
180                 Map[i][j] = PATH;
181             }
182         }
183         //attention \'\\n\'
184         getchar();
185     }
186     //Print maze
187     for (int i = 1; i <= size; i++)
188     {
189         for (int j = 1; j <= size; j++)
190         {
191             if (UNREACHABLE == Map[i][j])
192             {
193                 printf("X");
194             }
195             else
196             {
197                 printf(" ");
198             }
199         }
200         printf("\\n");
201     }
202 }
203 void PrintPath(SqStack S, int size)
204 {
205     SElemType e;
206     SqStack temp;
207     while (!StackEmpty(S))
208     {
209         Pop(S, e);
210         Map[e.seat.x][e.seat.y] = FINALPATH;
211     }
212     for (int i = 1; i <= size; i++)
213     {
214         for (int j = 1; j <= size; j++)
215         {
216             if (UNREACHABLE == Map[i][j])
217             {
218                 printf("X");
219             }
220             else if (FINALPATH == Map[i][j])
221             {
222                 printf("O");
223             }
224             else
225             {
226                 printf(" ");
227             }
228         }
229         printf("\\n");
230     }
231 }
232 Status MazePath(MazeType maze, PosType start, PosType end, int size)
233 {
234     //若迷宫 maze 中存在从入口 start 到出口 end 的通道,
235     //则求得一条存放在栈中(从栈底到栈顶),并返回 TRUE,
236     //否则返回 FALSE
237     SqStack S;
238     InitStack(S);
239     //curpos = start
240     PosType curpos;
241     Assign_PosType(curpos, start);//设定当前位置为入口位置
242     int curstep = 1;//探索第一步
243     SElemType e;
244     do{
245         if (TRUE == Pass(curpos))
246         {//当前位置可以通过
247             FootPrint(curpos);//留下足迹
248             //e = (curstep, curpos, 1);
249             Assign_SELemType(e, curstep, curpos, 1);
250             Push(S, e);//加入路径
251             if (curpos.x == end.x && curpos.y == end.y)
252             {
253                 //打印路径
254                 printf("PATH EXIST\\n");
255                 PrintPath(S ,size);
256                 return TRUE;
257             }
258             curpos = NextPos(curpos, 1);//下一位置是当前位置的东邻
259             curstep++;//探索下一步
260         }
261         else
262         {
263             if (!StackEmpty(S))
264             {
265                 Pop(S, e);
266                 while (4 == e.direction && !StackEmpty(S))
267                 {
268                     MarkPrint(e.seat);
269                     Pop(S, e);//留下不能通过的标记,并退回一步
270                 }
271                 if (e.direction < 4)
272                 {
273                     e.direction++;
274                     Push(S, e);
275                     curpos = NextPos(e.seat, e.direction);
276                 }
277             }
278         }
279     }while (!StackEmpty(S));
280 
281 }
282 #endif
3_2_maze.h

  表达式求值:

  1 //3_2_maze.h
  2 /**
  3 author:zhaoyu
  4 email:zhaoyu1995.com@gmail.com
  5 date:2016-6-8
  6 note:realize my textbook <<数据结构(C语言版)>>
  7 */
  8 //Page 53
  9 #ifndef _3_2_EXPRESSION_H_
 10 #define _3_2_EXPRESSION_H_
 11 #include "head.h"
 12 
 13 #define SElemType char
 14 #define OperandType float
 15 #define STACK_INIT_SIZE 100//存储空间的初始分配值
 16 #define STACKINCREMENT 10//存储空间分配增量
 17 typedef struct{
 18     SElemType *base;//在栈构造之前和销毁之后,base 值为 NULL
 19     SElemType *top;//栈顶指针
 20     int stacksize;//当前已分配的存储空间,以元素为单位
 21 }SqStack_Char;
 22 typedef struct{
 23     OperandType *base;//在栈构造之前和销毁之后,base 值为 NULL
 24     OperandType *top;//栈顶指针
 25     int stacksize;//当前已分配的存储空间,以元素为单位
 26 }SqStack_Float;
 27 Status InitStack_Char(SqStack_Char &S)
 28 {
 29     //构造一个空栈 S
 30     S.base = (SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
 31     if (!S.base)
 32     {
 33         exit(OVERFLOW);
 34     }
 35     S.top = S.base;
 36     S.stacksize = STACK_INIT_SIZE;
 37     return OK;
 38 }//InitStack
 39 Status InitStack_Float(SqStack_Float &S)
 40 {
 41     //构造一个空栈 S
 42     S.base = (OperandType *)malloc(STACK_INIT_SIZE*sizeof(OperandType));
 43     if (!S.base)
 44     {
 45         exit(OVERFLOW);
 46     }
 47     S.top = S.base;
 48     S.stacksize = STACK_INIT_SIZE;
 49     return OK;
 50 }//InitStack
 51 Status Push_Char(SqStack_Char &S, SElemType e)
 52 {
 53     //插入元素 e 为新的栈顶元素
 54     if (S.top - S.base >= S.stacksize)
 55     {//栈满,追加存储空间
 56         S.base = (SElemType *)realloc(S.base,
 57             (S.stacksize+STACKINCREMENT)*sizeof(SElemType));
 58         if (!S.base)
 59         {
 60             exit(OVERFLOW);
 61         }
 62         S.top = S.base + S.stacksize;
 63         S.stacksize += STACKINCREMENT;
 64     }
 65     *S.top++ = e;
 66     return OK;
 67 }//Push
 68 SElemType GetTop_Char(SqStack_Char S)
 69 {
 70     //若栈不空,则用 e 返回 S 的栈顶元素,并返回 OK;
 71     //否则返回ERROR
 72     if (S.top == S.base)
 73     {
 74         return ERROR;
 75     }
 76     return *(S.top - 1);
 77 }//GetTop
 78 Status isInOPTR(SElemType c)
 79 {
 80     switch (c)
 81     {
 82         case \'+\':
 83         case \'-\':
 84         case \'*\':
 85         case \'/\':
 86         case \'(\':
 87         case \')\':
 88         case \'#\':
 89         {
 90             return TRUE;
 91             break;
 92         }
 93         default:
 94         {
 95             return FALSE;
 96             break;
 97         }
 98     }
 99 }
100 Status Push_Float(SqStack_Float &S, OperandType e)
101 {
102     //插入元素 e 为新的栈顶元素
103     if (S.top - S.base >= S.stacksize)
104     {//栈满,追加存储空间
105         S.base = (OperandType *)realloc(S.base,
106             (S.stacksize+STACKINCREMENT)*sizeof(OperandType));
107         if (!S.base)
108         {
109             exit(OVERFLOW);
110         }
111         S.top = S.base + S.stacksize;
112         S.stacksize += STACKINCREMENT;
113     }
114     *S.top++ = e;
115     return OK;
116 }//Push
117 char Precede(SElemType a, SElemType b)
118 {
119     char R[7][7] =  {{\'>\',\'>\',\'<\',\'<\',\'<\',\'&g

以上是关于数据结构算法C语言实现--- 3.2栈的应用举例:迷宫求解与表达式求值的主要内容,如果未能解决你的问题,请参考以下文章

C语言实现顺序栈的基本操作举例

数据结构与算法栈与队列C语言版

数据结构算法C语言实现--- 3.1 的线性实现及应用举例

Python数据结构与算法(3.2)——栈相关应用与习题

栈的应用(括号匹配算法实战)

栈的实现(c语言)--- 数据结构