zoukankan      html  css  js  c++  java
  • HDU 1237 简单计算器

    题目给出的是中缀表达式,所以要计算它的值主要是两个步骤:

    1. 中缀表达式转后缀表达式。
    2. 计算后缀表达式。

    下面分别讲一下这两步。

    1. 中缀表达式转后缀表达式
      ①设立一个操作符栈,用以临时存放操作符;设立一个数组或者队列,用以存放后缀表达式。
      ②从左至右扫描中缀表达式,如果碰到操作数(注意:操作数可能不止一位,因此需要一位一位读入然后合并在一起),就把操作数加入后缀表达式中。
      ③如果碰到操作符op,就将其优先级与操作符栈的栈顶操作符的优先级比较。

      • 若op的优先级高于栈顶操作符的优先级,则压入操作符栈。
      • 若op的优先级低于或等于栈顶操作符的优先级,则将操作符栈的操作符不断弹出到后缀表达式中,直到op的优先级高于栈顶操作符的优先级。

      ④重复上述操作,直到中缀表达式扫描完毕,之后若操作符栈中仍有元素,则将它们依次弹出至后缀表达式中。

      • 所谓操作符的优先级即它们计算的优先级,其中乘除>加减>左括号。
      • 关于为什么当op高于栈顶时就压入操作符栈,这里举一个例子:
        对中缀表达式3+2x5,显然如果先计算加法3+2会引起错误,必须先计算乘法2x5。当从左到右扫描时,加号先进入操作符栈,而由于乘号优先级大于加号,其必须先计算,因此在后缀表达式中乘号必须在加号前面,于是在栈中乘号要比加号更靠近栈顶,以让其先于加号进入后缀表达式。
      • 关于为什么当op等于栈顶时不能直接压入操作符栈,这里举一个例子:
        对中缀表达式2/3×4,如果设定优先级相等时直接压入操作符栈,那么算法步骤如下:
        (1) 2进入后缀表达式,当前后缀表达式为2。
        (2) 1进入操作符栈,当前操作符栈为/。
        (3) 3进入后缀表达式,当前后缀表达式为23。
        (4) *与操作符栈的栈顶元素/比较,相等,压入操作符栈,当前操作符栈为/*。
        (5) 4进入后缀表达式,当前后缀表达式为234。
        (6) 中缀表达式扫描完毕,操作符栈非空,将其全部弹入后缀表达式,最终后缀表达式变为234*/。
        (7) 计算该后缀表达式,发现其实变成了2/(3×4),显然这跟原来中缀表达式的计算结果完全不同。

    本题没有出现括号,但是如果出现括号,处理方法也很简单,只需要在步骤3的a与b之前判断,如果是左括号'(',就压入操作符栈;如果是右括号')',就把操作符栈里的元素不断弹出到后缀表达式直到碰到左括号'(',然后把左括号'('出栈。

    1. 计算后缀表达式
      从左到右扫描后缀表达式,如果是操作数,就压入栈;如果是操作符,就连续弹出两个操作数,(注意:后弹出的是第一操作数, 先弹出的是第二操作数),然后进行操作符的操作,生成的新操作数压入栈中。反复直到后缀表达式扫描完毕,这时栈中只会存在一个数,就是最终的答案。

    注意点

    注意除法可能导致浮点数,因此操作数类型要设成浮点型。

    代码

    用两个栈,一边入栈一边计算。

    stack<double> num;
    stack<char> opt;
    map<char,int> level;
    string s;
    
    void calc(char op)
    {
        double x=num.top();
        num.pop();
        double y=num.top();
        num.pop();
    
        if(op == '+') num.push(x+y);
        if(op == '-') num.push(y-x);
        if(op == '*') num.push(x*y);
        if(op == '/') num.push(y/x);
    }
    
    int main()
    {
        level['+']=level['-']=1;
        level['*']=level['/']=2;
    
        while(getline(cin,s))
        {
            if(s == "0") break;
    
            while(num.size()) num.pop();
            while(opt.size()) opt.pop();
    
            for(int i=0;i<s.size();i++)
                if(isdigit(s[i]))
                {
                    int j=i;
                    int res=0;
                    while(j<s.size() && isdigit(s[j]))
                    {
                        res=res*10+s[j]-'0';
                        j++;
                    }
                    num.push(res);
                    i=j-1;
                }
                else if(s[i] != ' ')
                {
                    while(opt.size() && level[opt.top()] >= level[s[i]])
                    {
                        calc(opt.top());
                        opt.pop();
                    }
                    opt.push(s[i]);
                }
    
            while(opt.size())
            {
                calc(opt.top());
                opt.pop();
            }
    
            printf("%.2f
    ",num.top());
        }
        //system("pause");
        return 0;
    }
    
  • 相关阅读:
    【技术贴】解决Eclipse编译java源文件之后没有生成class文件|找不到class文件
    小米1s 正式为我服役,纪念一下。
    解决servlet的out输出流html中文乱码
    小米1s充电时屏幕一直亮着不关闭的解决办法
    今天遇到的问题分析
    java操作Excel(org.apache.poi.hssf.usermodel)
    HTML滚动文字代码 marquee标签
    MIUI小米 卸载金山安全服务
    Oracle DBA 逻辑备份试题
    Oracle DBA结构试题1
  • 原文地址:https://www.cnblogs.com/fxh0707/p/14416729.html
Copyright © 2011-2022 走看看