• 中缀表达式求值


    描述

    人们熟悉的四则运算表达式称为中缀表达式,例如(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]!=''; 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] = '';
    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] != ''; 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);
     6     while(n--) {
     7         gets(infix);
     8         infix_to_suffix(infix, suffix);    
     9         printf("%d
    ", suffix_value(suffix));
    10     }
    11 
    12     return 0;
    13 }
  • 相关阅读:
    SpringBoot2.x前后端分离跨域问题及Swagger不能访问
    SpirngBoot2.x整合Swagger2接口文档
    SpringBoot2.x整合Druid数据源
    SpringBoot2.x整合logback 实现自动打印日志
    docker 进入 mysql中的操作
    Intellij Springboot (子模块)访问jsp页面404
    运行rabbitmq 的docker
    mybatis拦截器修改sql重新set后不生效?
    oracle+mybatis如何在新增时返回主键(自增序列)的值?
    oracle+mybatis报“未找到要求的from关键字”错误?
  • 原文地址:https://www.cnblogs.com/zghaobac/p/3394705.html
Copyright © 2020-2023  润新知