求表达式的值--栈和队列的应用
Posted robin_X
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求表达式的值--栈和队列的应用相关的知识,希望对你有一定的参考价值。
1 #include<stdio.h>
2 #include<stdlib.h>
3
4 #define OK 1
5 #define ERROR 0
6 #define STACK_SIZE 20
7 #define STACK_INCREMENT 10
8 #define QUEUE_SIZE 20
9
10 typedef int Status;
11
12 typedef char StackElemtype;
13 typedef struct Stack{
14 StackElemtype* base;
15 StackElemtype* top;
16 int stackSize;
17 }Stack;
18 Status StackInit(Stack* s){
19 s->base = (StackElemtype*)malloc(sizeof(StackElemtype) * STACK_SIZE);
20 if( !s->base )
21 return ERROR;
22 s->top = s->base;
23 s->stackSize = STACK_SIZE;
24 return OK;
25 }
26 Status Pop(Stack* s,StackElemtype* value){
27 if( s->base == s->top ){
28 printf("\nstack empty\n");
29 return ERROR;
30 }
31 *value = *(--(s->top));
32 return OK;
33 }
34 Status Push(Stack* s,StackElemtype value){
35 if( s->top - s->base == s->stackSize){
36
37 s->base = (StackElemtype*)realloc(s->base,sizeof(StackElemtype) * (STACK_INCREMENT + STACK_SIZE));
38 if( !s->base )
39 return ERROR;
40 s->top = s->base + STACK_SIZE;
41 s->stackSize = STACK_SIZE + STACK_INCREMENT;
42 }
43 *(s->top) = value;
44 s->top++;
45 return OK;
46 }
47 int StackLength(Stack s){
48 return s.top - s.base;
49 }
50
51 typedef double StackElemtype_ForValueExperssion;
52 typedef struct Stack_2{
53 StackElemtype_ForValueExperssion* base;
54 StackElemtype_ForValueExperssion* top;
55 int stackSize;
56 }Stack_2;
57 Status StackInit_2(Stack_2* s){
58 s->base = (StackElemtype_ForValueExperssion*)malloc(sizeof(StackElemtype_ForValueExperssion) * STACK_SIZE);
59 if( !s->base )
60 return ERROR;
61 s->top = s->base;
62 s->stackSize = STACK_SIZE;
63 return OK;
64 }
65 Status Pop_2(Stack_2* s,StackElemtype_ForValueExperssion* value){
66 if( s->base == s->top ){
67 printf("\nstack empty\n");
68 return ERROR;
69 }
70 *value = *(--(s->top));
71 return OK;
72 }
73 Status Push_2(Stack_2* s,StackElemtype_ForValueExperssion value){
74 if( s->top - s->base == s->stackSize){
75 s->base = (StackElemtype_ForValueExperssion*)realloc(s->base,sizeof(StackElemtype_ForValueExperssion) * (STACK_INCREMENT + STACK_SIZE));
76 if( !s->base )
77 return ERROR;
78 s->top = s->base + STACK_SIZE;
79 s->stackSize = STACK_SIZE + STACK_INCREMENT;
80 }
81 *(s->top) = value;
82 s->top++;
83 return OK;
84 }
85
86 typedef double QueueElemtype;
87 typedef char QueueOperatorValue;
88 typedef struct QueueNode{
89 QueueElemtype data;
90 QueueOperatorValue operator;
91 struct QueueNode* next;
92 int flag;
93 }QueueNode,*QueueNodePtr;
94 typedef struct Queue{
95 QueueNodePtr front;
96 QueueNodePtr rear;
97 }Queue;
98
99 Status QueueInit(Queue* q){
100 q->front = (QueueNodePtr)malloc(sizeof(QueueNode));
101 if( !q->front )
102 return ERROR;
103 q->rear = q->front;
104 q->rear->next = NULL;
105 return OK;
106 }
107 Status QueueInsert(Queue* q,QueueElemtype value){
108 QueueNodePtr new;
109 new = (QueueNodePtr)malloc(sizeof(QueueNode));
110 if( !new )
111 return ERROR;
112 new->data = value;
113 new->flag = 1;
114 new->next = NULL;
115 q->rear->next = new;
116 q->rear = new;
117 return OK;
118 }
119 Status QueueInsert_operatorValue(Queue* q,QueueOperatorValue value){
120 QueueNodePtr new;
121 new = (QueueNodePtr)malloc(sizeof(QueueNode));
122 if( !new )
123 return ERROR;
124 new->operator = value;
125 new->flag = 0;
126 new->next = NULL;
127 q->rear->next = new;
128 q->rear = new;
129 return OK;
130 }
131 Status QueueDelete(Queue* q,QueueElemtype* value,QueueOperatorValue *operator,int* symbol){
132 QueueNodePtr first;
133 if( q->front == q->rear )
134 return ERROR;
135 first = q->front->next;
136 if( first->flag == 1 ){
137 *value = first->data;
138 *symbol = 1;
139 }
140 else{
141 *operator = first->operator;
142 *symbol = 0;
143 }
144 q->front->next = first->next;
145 if( first == q->rear ){
146 q->rear = q->front;
147 }
148 return OK;
149 }
150
151 /* 利用栈将中缀表达式转化为后缀表达式:
152 * ——————————————————————————————————————————————————————————————
153 * | 用户的输入 | 进行的处理 |
154 * | 0~9: | 直接输出到控制台 |
155 * | /,*,( | 直接Push |
156 * | +,- | 将栈中的元素Pop直到1.栈空或者是2.遇到( |
157 * | ) | 在遇到(之前将栈中的元素全部Pop |
158 * ——————————————————————————————————————————————————————————————
159 * */
160
161 Status Infix2Postfix(Queue* q){
162 //Queue q;
163 //QueueInit(&q);
164 Stack s;
165 StackInit(&s);
166 char c,e;
167 char bufferDigit[10];
168 int i = 0;
169 double longDigit;
170 printf(" Please Enter Infix Expression\n");
171 printf("------------NOTE: end of ‘#‘--------------\n");
172 scanf("%c", &c);
173 while( ‘#‘ != c){
174 while( c <= ‘9‘ && c >= ‘0‘ || ‘.‘ == c ){
175 bufferDigit[i++] = c;
176 bufferDigit[i] = ‘\0‘;
177 scanf("%c", &c);
178 if(!((c <= ‘9‘ && c >= ‘0‘ ) || ‘.‘ == c )){
179 longDigit = atof(bufferDigit);
180 QueueInsert(q,longDigit);
181 i = 0;
182 }
183 }
184 if( ‘(‘ == c || ‘*‘ == c || ‘/‘ == c ){
185 Push(&s, c);
186 }
187 else if( ‘+‘ == c || ‘-‘ == c ){
188 if( !StackLength(s) )
189 Push(&s, c);
190 else{
191 Pop(&s, &e);
192 while( ‘(‘ != e ){
193 QueueInsert_operatorValue(q, e);
194 if( StackLength(s) == 0 ){
195 break;
196 }else
197 Pop(&s, &e);
198 }
199 if( ‘(‘ == e )
200 Push(&s, e);
201 Push(&s, c);
202 }
203 }else if( ‘)‘ == c ){
204 Pop(&s, &e);
205 while( ‘(‘ != e ){
206 QueueInsert_operatorValue(q, e);
207 Pop(&s, &e);
208 }
209 }else if( ‘#‘ == c){
210 break;
211 }else{
212 printf("input ERROR!\n");
213 return ERROR;
214 }
215 scanf("%c", &c);
216 }
217 while(StackLength(s)){
218 Pop(&s, &e);
219 QueueInsert_operatorValue(q, e);
220 }
221 QueueInsert_operatorValue(q,‘#‘);
222 return OK;
223 }
224 Status ShowQueue(Queue q){
225 printf("The Reverse Polish Notation is:");
226 if(q.front == q.rear){
227 printf("Queue Empty");
228 return ERROR;
229 }
230 QueueNodePtr p = q.front->next;
231 while(p != q.rear){
232 if(p->flag)
233 printf("%g ", p->data);
234 else
235 printf("%c ", p->operator);
236 p = p->next;
237 }
238 printf("\n");
239 return OK;
240 }
241
242 /* 利用栈求解后缀表达式(逆波兰表达式)的值。
243 * ——————————————————————————————————————————————————————————————————————
244 * | +,-,*,/, | 将栈顶的两个元素弹出进行计算,将结果压入栈顶 |
245 * | 数字 | 将其压入栈顶 |
246 * ———————————————————————————————————————————————————————————————————————
247 * */
248 Status ValueExpression(Queue q){
249 Stack_2 s;
250 StackInit_2(&s);
251 double o1;
252 double o2;
253 QueueElemtype number;
254 QueueOperatorValue operator;
255 int symbol;
256 QueueDelete(&q,&number,&operator,&symbol);
257 while( symbol == 1 || ( symbol == 0 && ‘#‘ != operator)){
258 if(symbol == 1){
259 Push_2(&s, number);
260 }
261 else if(symbol == 0){
262 switch(operator){
263 case ‘+‘:
264 Pop_2(&s,&o1);
265 Pop_2(&s,&o2);
266 Push_2(&s,o2 + o1);
267 break;
268 case ‘-‘:
269 Pop_2(&s,&o1);
270 Pop_2(&s,&o2);
271 Push_2(&s,o2 - o1);
272 break;
273 case ‘*‘:
274 Pop_2(&s,&o1);
275 Pop_2(&s,&o2);
276 Push_2(&s,o2 * o1);
277 break;
278 case ‘/‘:
279 Pop_2(&s,&o1);
280 Pop_2(&s,&o2);
281 Push_2(&s,o2 / o1);
282 break;
283 }
284 }
285 QueueDelete(&q,&number,&operator,&symbol);
286 }
287 Pop_2(&s,&o1);
288 printf("The Value of the Expression is %g\n",o1);
289 return OK;
290 }
291
292 int main(){
293 Queue q;
294 QueueInit(&q);
295 Infix2Postfix(&q);
296 ShowQueue(q);
297 /*
298 QueueElemtype number;
299 QueueOperatorValue operator;
300 int symbol;
301 QueueDelete(&q,&number,&operator,&symbol);
302 printf("%f,%c,%d\n",number,operator,symbol);
303 */
304 ValueExpression(q);
305 //Stack
306 /*
307 Stack s;
308 StackInit(&s);
309 StackElemtype c;
310 Push(&s,‘1‘);
311 Push(&s,‘2‘);
312 Push(&s,‘3‘);
313 Push(&s,‘4‘);
314 Pop(&s,&c);
315 printf("%c ", c);
316 Pop(&s,&c);
317 printf("%c ", c);
318 Pop(&s,&c);
319 printf("%c ", c);
320 Pop(&s,&c);
321 printf("%c ", c);
322 */
323 //Queue
324 /*
325 Queue q;
326 QueueElemtype c;
327 QueueInit(&q);
328 QueueInsert(&q,1);
329 QueueInsert(&q,2);
330 QueueInsert(&q,3);
331 QueueInsert(&q,4);
332 QueueDelete(&q,&c);
333 printf("%d ", c);
334 QueueDelete(&q,&c);
335 printf("%d ", c);
336 QueueDelete(&q,&c);
337 printf("%d ", c);
338 QueueDelete(&q,&c);
339 printf("%d ", c);
340 if(QueueDelete(&q,&c)){
341 printf("%d ",c);
342 }
343 */
344 /*
345 Queue q;
346 QueueInit(&q);
347 QueueInsert(&q,2.1);
348 QueueInsert_operatorValue(&q,‘+‘);
349 QueueInsert(&q,43.1);
350 QueueInsert_operatorValue(&q,‘a‘);
351 QueueInsert_operatorValue(&q,‘(‘);
352 int iswho;
353 double d;
354 char c;
355 QueueDelete(&q,&d,&c,&iswho);
356 if(iswho == 1)
357 printf("%f ",d);
358 else
359 printf("%c ", c);
360 QueueDelete(&q,&d,&c,&iswho);
361 if(iswho == 1)
362 printf("%f ",d);
363 else
364 printf("%c ", c);
365 QueueDelete(&q,&d,&c,&iswho);
366 if(iswho == 1)
367 printf("%f ",d);
368 else
369 printf("%c ", c);
370 QueueDelete(&q,&d,&c,&iswho);
371 if(iswho == 1)
372 printf("%f ",d);
373 else
374 printf("%c ", c);
375 */
376 return 0;
377 }
本文主要用C代码实现了求表达式的值,例如当用户输入表达式 5*((3+2)-6+8)+12/(5+3)时,可以直接得出结果为36.5.也会输出在计算过程中使用的逆波兰表达式。代码使用的数据结构主要是栈和队列,在将用户输入的中缀表达式转换为后缀表达式时,使用了栈。使用队列存储了得到的后缀表达式结构,供计算后缀表达式的值读取,在计算后缀表达式时,使用的也是栈。
程序存在的问题:1 在使用栈和队列时,如果只有存放的元素的类型不同,如一个用于存放char另一个用于存放double,那么应该怎么处理。在本程序中,分别定义了char型的栈和double型的栈,而他们除了元素的类型不同之外,其他的完全相同,这就使得本程序存在大量的冗余代码。
2 本程序中的队列中需要存放两种类型的元素,double型的操作数和char类型的操作符,所以将队列的数据域定义了两个分别来存储,并且使用了flag来表明该节点存放的是double类型的操作数还是char类型的操作符。不知是否有更好的方法
3 使用文件来保存中间生成的后缀表达式的结果,可能会使得本代码更简单
以上是关于求表达式的值--栈和队列的应用的主要内容,如果未能解决你的问题,请参考以下文章
3-5-表达式求值-栈和队列-第3章-《数据结构》课本源码-严蔚敏吴伟民版