表达式求值 (栈应用)

简单计算器

Description

计算一个算术表达式的值。(式子中每个数都是一位数,且除法运算时整除,即3/2=1。输入数据保证每个表达式合法。)

Input

有多组测试样例。一个算术表达式占一行。

Output

输出表达式的值。

Sample Input

1+1
2*3

Sample Output

2
6



分析:就是一个含有加减乘除的表达式,并且不含有括号,计算其值。明明是很简单的表达式求值,愣是让我水了几个小时,也是醉了。。。看来真是老了大哭

表达式求值:1、先按照计算法则,给出各运算符的优先级,这个是为了比较两个相邻运算符应该先算哪一个。

2、接下来就是真正的比较计算了,总体的比较思想是开两个栈,一个用来存数字(题目比较水,只是一位的数字),一个用来存运算符。

3、从头到尾扫描一遍表达式,逐个读入数字或运算符,如果是数字,则直接压入数字栈即可;要是运算符,则要考虑以下几种情况:

             1.运算符栈为空时,直接进栈即可。

              2.若不为空,则比较当前运算符和运算符栈顶运算符的优先级,若栈顶的大,就代表它的优先级比较大,我们就要先把栈顶运算符弹出栈,同时从数字栈中弹出栈顶的两个数字,因为这两个数字就是运算符栈顶元素的两个操作数(这个如果不懂得话,可以手动模拟一下操作步骤,即可明白其间的关系),这点要注意,由于栈的特点,我们取出的数字顺序,是跟原来在运算符两边的位置是相反的,所以计算的时候要调过来。再把计算出的结果压入数字栈。

               3.重复步骤3.2,直到当前运算符的优先级大于运算符栈顶运算符的优先级,这时,我们再把当前等待入栈的运算符入栈。

4、重复步骤2,直到表达式扫描完为止。

5、最后,运算符栈里剩的就是优先级相等的运算符了,我们只需要把它们一个一个取出来,按照顺序算出来即可。这个顺序,比上面的简单很多,每次从运算符栈顶弹出一个运算符op,再从数字栈里依次弹出两个数a,b,那么最后计算b  op  a的值,再将其放入数字栈中,直到运算符栈为空的时候,刚好我们的数字栈中只剩下了一个元素(因为每个运算符都是两个操作数,但是所有的都相邻排列的,所以所有的操作数恰好比运算符多1个),这个就是我们表达式的最终结果。




AC代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <stack>
using namespace std;
#define INF 0x7fffffff
#define LL long long
#define LLL(a, b)  a<<b
#define RRR(a, b)  a>>b
#define MID(a, b)  a+(b-a)/2
const int maxn = 10000000 + 10;

int cal(int x, int y, char p){              //计算x op y的值
    if(p == '*') return x * y;
    else if(p == '/') return x / y;
    else if(p == '+') return x + y;
    else return x - y;
}

int main(){
    #ifdef sxk
        freopen("in.txt", "r", stdin);      //不用看,从文件读入用的,跟题目无关
    #endif // sxk

    int n;
    int pri[300];
    string s;
    memset(pri, 0, sizeof(pri));            //初始化优先级数组
    pri['*'] = pri['/'] = 3;                //设定运算符的优先级
    pri['+'] = pri['-'] = 1;
    while(cin >> s){                        //读入表达式
        stack<int> num;                     //数字栈
        stack<char> op;                     //运算符栈
        int len = s.size();
        for(int i=0; i<len; i++){
            if(s[i] >= '0' && s[i] <= '9') num.push(s[i] - '0');    //是数字,直接压入数字栈
            else{                                                   //是运算符
                if(!op.size()) op.push(s[i]);                       //运算符栈空,直接入栈
                else{
                    while(pri[ s[i] ] <= pri[ op.top() ]){          //循环判断,把栈顶优先级不小于当前运算符优先级的运算符全部弹出栈
                        int x = num.top(); num.pop();               //弹出两个数字
                        int y = num.top(); num.pop();
                        char c = op.top(); op.pop();                //弹出运算符
                        num.push(cal(y, x, c));                     //把计算结果压入数字栈
                        if(op.size() == 0) break;                   //一定要注意,不判空的话,会报Runtime Erro
                    }
                    op.push(s[i]);                                  //再把当前待入栈运算符入栈
                }
            }
        }
        while(op.size()){                    //最后的计算
            int x = num.top(); num.pop();
            int y = num.top(); num.pop();
            char c = op.top(); op.pop();
            num.push(cal(y, x, c));
        }
        printf("%d\n", num.top());          //栈顶元素,即为表达式的最终结果
    }
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值