求表达式的值--栈和队列的应用

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-栈和队列

3-5-表达式求值-栈和队列-第3章-《数据结构》课本源码-严蔚敏吴伟民版

考研数据结构与算法栈和队列

博客作业03--栈和队列

栈和队列数据结构的特点,啥情况下用到栈,啥情况下用到队列(各举3个例子)

数据结构与算法学习笔记 栈和队列Ⅰ