zoukankan      html  css  js  c++  java
  • nyoj 35-表达式求值(stack, 栈的应用)

    35-表达式求值


    内存限制:64MB 时间限制:3000ms Special Judge: No
    accepted:37 submit:53

    题目描述:

    ACM队的mdd想做一个计算器,但是,他要做的不仅仅是一计算一个A+B的计算器,他想实现随便输入一个表达式都能求出它的值的计算器,现在请你帮助他来实现这个计算器吧。
    比如输入:“1+2/4=”,程序就输出1.50(结果保留两位小数)

    输入描述:

    第一行输入一个整数n,共有n组测试数据(n<10)。
    每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式,每个运算式都是以“=”结束。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数。
    数据保证除数不会为0

    输出描述:

    每组都输出该组运算式的运算结果,输出结果保留两位小数。

    样例输入:

    2
    1.000+2/4=
    ((1+2)*5+1)/4=

    样例输出:

    1.50
    4.00

    分析与步骤:
      ①、类似于表达式求解问题需要用到栈(stack)的思想(即就是先进后出)
      ②、遇到数字就将数字放入数字栈中
      ③、遇到字符串就要分开考虑
        1、是‘(’就直接入栈,方便遇到')'时,就将'('以后所有的运算栈带入数字栈运算,结果保存于数字串
        2、如果操作栈为空栈直接入栈
        3、如果操作栈的栈顶元素优先级小于带输入字符的优先级直接入栈
        4、其他情况就是要将数字栈与操作栈结合,算出结果保存在数字栈中
        5、数字栈中的最后一个元素即为题解

    核心代码(表达式求值模板);
     1 int priority(char c) // 表达优先级的大小关系
     2 {
     3     if (c == '*' || c == '/') return 2;
     4     if (c == '+' || c == '-') return 1;
     5     return 0;
     6 }
     7 
     8 void cal(stack<char> &my_op, stack<double> &my_num) // 将数字栈与操作栈通过引用的形式实现调用与更改
     9 {
    10     double b = my_num.top();
    11     my_num.pop();
    12     double a = my_num.top();
    13     my_num.pop();
    14     switch(my_op.top())
    15     {
    16         case '+': my_num.push(a + b); break;
    17         case '-': my_num.push(a - b); break;
    18         case '*': my_num.push(a * b); break;
    19         case '/': my_num.push(a / b); break;
    20     }
    21     my_op.pop();
    22 }
    23 for(int i = 0; i < len; ++ i) // 判断是因该执行什么操作
    24 {
    25     if(isdigit(s[i]))
    26     {
    27         double temp = atof(&s[i]);
    28         while(isdigit(s[i]) || s[i] == '.') ++ i;
    29         my_num.push(temp);
    30         -- i;
    31     }
    32     else if(s[i] == '(')
    33     {
    34         my_op.push(s[i]);
    35     }
    36     else if(s[i] == ')')
    37     {
    38         while(my_op.top() != '(')
    39             cal(my_op, my_num);
    40         my_op.pop();
    41     }
    42     else if(my_op.empty())
    43     {
    44         my_op.push(s[i]);
    45     }
    46     else if(priority(my_op.top()) < priority(s[i]))
    47     {
    48         my_op.push(s[i]);
    49     }
    50     else if(priority(my_op.top()) >= priority(s[i]))
    51     {
    52         while(!my_op.empty() && priority(my_op.top()) >= priority(s[i])) // 比较的是优先级关系不是ASCⅡ
    53             cal(my_op, my_num);
    54         my_op.push(s[i]);
    55     }
    56 }

    C/C++代码实现(AC):

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstring>
     4 #include <cstdio>
     5 #include <cmath>
     6 #include <stack>
     7 #include <map>
     8 #include <queue>
     9 #include <set>
    10 
    11 using namespace std;
    12 const int MAXN = 1010;
    13 
    14 int priority(char c) // 表达优先级的大小关系
    15 {
    16     if (c == '*' || c == '/') return 2;
    17     if (c == '+' || c == '-') return 1;
    18     return 0;
    19 }
    20 
    21 void cal(stack<char> &my_op, stack<double> &my_num) // 将数字栈与操作栈通过引用的形式实现调用与更改
    22 {
    23     double b = my_num.top();
    24     my_num.pop();
    25     double a = my_num.top();
    26     my_num.pop();
    27     switch(my_op.top())
    28     {
    29     case '+':
    30         my_num.push(a + b);
    31         break;
    32     case '-':
    33         my_num.push(a - b);
    34         break;
    35     case '*':
    36         my_num.push(a * b);
    37         break;
    38     case '/':
    39         my_num.push(a / b);
    40         break;
    41     }
    42     my_op.pop();
    43 }
    44 
    45 int main()
    46 {
    47 
    48     int t;
    49     scanf("%d", &t);
    50     while(t --)
    51     {
    52         char s[MAXN];
    53         scanf("%s", s);
    54         int len = strlen(s);
    55         stack <double> my_num;
    56         stack <char> my_op;
    57 
    58         for(int i = 0; i < len; ++ i)
    59         {
    60             if(isdigit(s[i]))
    61             {
    62                 double temp = atof(&s[i]);
    63                 while(isdigit(s[i]) || s[i] == '.') ++ i;
    64                 my_num.push(temp);
    65                 -- i;
    66             }
    67             else if(s[i] == '(')
    68             {
    69                 my_op.push(s[i]);
    70             }
    71             else if(s[i] == ')')
    72             {
    73                 while(my_op.top() != '(')
    74                     cal(my_op, my_num);
    75                 my_op.pop();
    76             }
    77             else if(my_op.empty())
    78             {
    79                 my_op.push(s[i]);
    80             }
    81             else if(priority(my_op.top()) < priority(s[i]))
    82             {
    83                 my_op.push(s[i]);
    84             }
    85             else if(priority(my_op.top()) >= priority(s[i]))
    86             {
    87                 while(!my_op.empty() && priority(my_op.top()) >= priority(s[i])) // 比较的是优先级关系不是ASCⅡ,my_op.top()忘记放在priority中,弄的找了半天的bug,::>_<::
    88                     cal(my_op, my_num);
    89                 my_op.push(s[i]);
    90             }
    91         }
    92         my_op.pop();
    93         printf("%.2lf
    ", my_num.top());
    94         my_num.pop();
    95     }
    96     return 0;
    97 }
  • 相关阅读:
    Asymptote 学习记录(1):基本的安装以及用批处理模式和交互模式绘图
    导函数的介质定理
    在新浪云上建立了一个wordpress独立博客
    数学分析原理 定理 6.10
    数学分析原理 定理 6.12
    opencvSparseMat稀疏矩阵
    基于MRSHudi构建数据湖的典型应用场景介绍
    解析云原生2.0架构设计的8大关键趋势
    全链路数据血缘在满帮的实践
    10年经验总结,华为fellow教你如何成为一名优秀的架构师?
  • 原文地址:https://www.cnblogs.com/GetcharZp/p/9070083.html
Copyright © 2011-2022 走看看