中缀表达式求值

描述

人们熟悉的四则运算表达式称为中缀表达式,例如(23+34*45/(5+6+7))。在程序设计语言中,可以利用堆栈的方法把中缀表达式转换成保值的后缀表达式(又称逆波兰表示法),并最终变为计算机可以直接执行的指令,得到表达式的值。
给定一个中缀表达式,编写程序,利用堆栈的方法,计算表达式的值。

输入

第一行为测试数据的组数N
接下来的N行,每行是一个中缀表达式。表达式中只含数字、四则运算符和圆括号,操作数都是正整数,数和运算符、括号之间没有空格。中缀表达式的字符串长度不超过600。

输出

对每一组测试数据输出一行,为表达式的值

解法

该问题可以转换为两个子问题:

1、将中缀表达式转换为后缀表达式

2、利用栈对后缀表达式求值

中缀表达式转后缀表达式

算法: 可以使用栈来完成中缀表达式到后缀表达式的转换

1、栈stack[]用来存储操作符,top指向栈顶,但不存储元素,top=0表示栈为空

2、从左向右遍历中缀表达式

  a.如果遇到的是操作数num,则直接输出到后缀表达式

  b.如果遇到的是操作符op,则有几种情况:

    b.1.如果op==')',则依次弹出栈顶直到弹出'(',但'('不输出到后缀表达式

    b.2:如果op=='(',则直接入栈

    b.3:如果栈为空,则直接入栈

    b.4:如果op的优先级高于栈顶操作符的优先级,则入栈

    b.5:如果op的优先级低于或等于栈顶操作符的优先级,则依次弹出栈顶直到op的优先级高于栈顶操作符的优先级(或栈为空),再将op入栈

3、遍历完时,如果栈仍不为空,则依次弹出栈顶直到栈为空

具体的代码如下:

 1 int mycmp(char a, char b) {
 2     if(b == '(')
 3         return 1;//左括号直接入栈
 4     else if((b == '*' || b == '/') &&(a == '+' || a == '-' || a == '('))
 5         return 1;//*、/优先级高于+、-、(,入栈
 6     else if((b == '+' || b == '-') && (a == '('))
 7         return 1;//+、-优先级高于(,入栈
 8     else
 9         return 0;
10 }
11 
12 /*中缀表达式转后缀表达式
13  中缀表达式之间无分割
14  后缀表达式操作数、操作符之间用空格分割,便于区分不同操作数*/
15 void infix_to_suffix(char* infix, char* suffix) {
16     int i, k, j=0, top=0;
17     char stack[1000];//存储运算符的栈
18 
19     for(i=0; infix[i]!='\0'; i++) {
20         if(infix[i] >= '0' && infix[i] <= '9') {
21             suffix[j++] = infix[i];//操作数则直接输出
22         } else {
23             if(i != 0 && infix[i-1] >= '0' && infix[i-1] <= '9') {
24                 suffix[j++] = ' ';//操作数后补充空格分割
25             }
26             if(infix[i] == ')') {
27                 //遇到右括号则一直弹出直到左括号,但左括号不输出
28                 while(stack[top-1] != '(') {
29                     suffix[j++] = stack[--top];
30                     suffix[j++] = ' ';
31                 }
32                 top--;
33             } else if(top == 0 || mycmp(stack[top-1], infix[i])) {
34                 //栈为空或当前操作符的优先级高于栈顶操作符,当前操作符入栈
35                 stack[top++] = infix[i];
36             } else {
37                 //当前操作符优先级等于或低于栈顶操作符则弹出栈顶
38                 while(!mycmp(stack[top-1], infix[i])) {
39                     suffix[j++] = stack[--top];
40                     suffix[j++] = ' ';
41                     if(top == 0)
42                         break;
43                 }
44                 stack[top++] = infix[i];//当前操作符入栈
45             }
46         }
47     }
48     //补充空格分割
49     if(suffix[j-1] != ' ') {
50         suffix[j++] = ' ';
51     }
52     //如果操作符栈不为空,弹出所有操作符
53     while(top != 0) {
54         suffix[j++] = stack[--top];
55         suffix[j++] = ' ';
56     }
57     suffix[j] = '\0';
58 }

 

利用栈对后缀表达式求值

算法:

1、栈stack[]用来存储操作数,top指向栈顶,但不存储元素,top=0表示栈为空,

2、从左向右依次遍历后缀表达式

   a.如果遇到的是操作数num,则直接将num入栈,即stack[top++]=num

   b.如果遇到的是操作符op,则取出依次取出栈顶的两个元素stack[top-2]和stack[top-1],计算stack[top-2] op stack[top-1]的结果,并将结果入栈

3、遍历结束时,stack[top-1]即为后缀表达式求值结果

具体的C语言代码如下:

 1 /*后缀表达式求值*/
 2 int suffix_value(char* suffix) {
 3     int i, j;
 4     char op;
 5     int stack[1000];
 6     int top = 0, value = 0;
 7     for(i=0; suffix[i] != '\0'; i++) {
 8         if(suffix[i] >= '0' && suffix[i] <= '9') {
 9             value = value*10 + suffix[i] - '0';
10         } else if(suffix[i] == ' ') {
11             //操作数入栈
12             stack[top++] = value;
13             value = 0;
14         } else {
15             //根据操作符,对栈顶两个操作数进行计算并得到结果
16             switch(suffix[i]) {
17                 case '+': value = stack[top-2] + stack[top-1];break;
18                 case '-': value = stack[top-2] - stack[top-1];break;
19                 case '*': value = stack[top-2] * stack[top-1];break;
20                 case '/': value = stack[top-2] / stack[top-1];break;
21                 default: break;
22             }
23             top -= 2;
24         }
25     }
26 
27     return stack[0];
28 }

 

至此,中缀表达式求值的主程序如下:

 1 int main() {
 2     int n;
 3     char infix[1000], suffix[1000];//infix中缀表达式,suffix后缀表达式
 4     
 5     scanf("%d\n", &n);
 6     while(n--) {
 7         gets(infix);
 8         infix_to_suffix(infix, suffix);    
 9         printf("%d\n", suffix_value(suffix));
10     }
11 
12     return 0;
13 }

 

 

转载于:https://www.cnblogs.com/zghaobac/p/3394705.html

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值