C++实现计算中缀式(转后缀式来计算)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jal517486222/article/details/86572383

题目:输入一个中缀表达式,计算其结果。
输入的前提假设:
(1)只考虑+、-、*、/这四种运算符,中缀表达式中只有一种括号:();
(2)输入的中缀表达式中只有整数,没有小数;
(3)假定输入是合法的。

一、如何将中缀表达式转化为后缀表达式

在日常应用中,算术表达式中运算符总是出现在两个操作数之间,例如5*(7-23)+8/2,这种形式称为中缀表达式。计算一个中缀表达式需要知道运算符的优先级和结合性。乘除是高优先级,加减是低优先级,优先级相同时他们都是左结合的,也就是从左计算到右。有括号就要计算括号内的表达式。
中缀表达式利于人的理解,但不便于计算机的处理。因此需要将中缀表达式转换成后缀表达式,以方便计算机处理。所谓后缀表达式就是将运算符放在运算数之后。后缀表达式也称为逆波兰表达式。
比如:
中缀表达式为: 1   +   (   2     3   )     4   +   4   /   2 1 + ( 2 - 3 ) * 4 + 4 / 2
对应后缀表达式为: 1   2   3     4     +   4   2   /   + 1  2  3  -  4 *  +  4  2  /  +
如何将一个中缀表达式转化为后缀表达式?我们需要借助栈的力量,用它来存放运算符。算法流程如下:
首先将各种运算符(包括括号)的优先级排列如下(数字越大,优先级越高):
1:(
2:+ -
3:
/
4:)
对输入的中缀表达式从左到右遍历:
1)如果遇到数字,直接添加到后缀表达式末尾;
2)如果遇到运算符+、-、*、/:
先判断栈是否为空。若是,则直接将此运算符压入栈。若不是,则查看当前栈顶元素。若栈顶元素优先级大于或等于此操作符级别,则弹出栈顶元素,将栈顶元素添加到后缀表达式中,并继续进行上述判断。如果不满足上述判断或者栈为空,将这个运算符入栈。要注意的是,经过上述步骤,这个运算符最终一定会入栈。
3)如果遇到括号:
如果是左括号,直接入栈。如果是右括号,弹出栈中第一个左括号前所有的操作符,并将左括号弹出。(右括号别入栈)。
4)字符串遍历结束后,如果栈不为空,则弹出栈中所有元素,将它们添加到后缀表达式的末尾,直到栈为空。

二、计算后缀表达式

后缀表达式的计算就相当简单了。准备一个数字栈。从左到右扫描后缀表达式,如果是数字,放入数字栈。如果是符号,从数字栈中弹出两个数字,第一个取出的数字为右运算数,第二个为左运算数,进行运算。然后将结果放进数字栈中。如此反复,直到读完整个表达式后,留在数字栈中的那个数字就是最终结果。

三、代码如下:

#include <bits/stdc++.h>
using namespace std;
int main(){
    map<char,int>p;
    p['('] = 1;
    p['+'] = 2; p['-'] = 2;
    p['*'] = 3; p['/'] = 3;
    p[')'] = 4;
    string s;
    ifstream cin("input.txt");
    while(cin >> s){

        //中缀转后缀
        vector<int>result;
        stack<char>op;
        int t = 0;
        for(int i = 0; i < s.size(); i++){
            if(isdigit(s[i])){
                t = t * 10 + s[i] - '0';
                if(i+1<s.size() && !isdigit(s[i+1])){
                    result.push_back(t);
                    t = 0;
                }
            }
            else{
                if(s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/'){
                    if(op.size() <= 0){
                        op.push(s[i]);
                    }else{
                        while(op.size() > 0 && p[op.top()] >= p[s[i]]){
                            result.push_back((int)op.top());
                            op.pop();
                        }
                        op.push(s[i]);
                    }
                }
                else if(s[i] == '('){
                    op.push(s[i]);
                }else{
                    while(op.top() != '('){
                        result.push_back((int)op.top());
                        op.pop();
                    }
                    op.pop();
                }
            }
        }
        while(op.size() > 0){
            result.push_back((int)op.top());
            op.pop();
        }
//        for(auto i : result){
//            if(i>=40)cerr<<(char)i<<" ";
//            else
//            cerr << i << " ";
//        }
        //计算后缀式
        stack<int>sk;
        for(int i = 0; i < result.size(); i++){
            if(result[i] == '+' || result[i] == '-' || result[i] == '*' || result[i] == '/'){
                int b = sk.top(); sk.pop();
                int a = sk.top(); sk.pop();
                int c;
                if(result[i] == '+'){
                    c = a + b;
                }else if(result[i] == '-'){
                    c = a - b;
                }else if(result[i] == '*'){
                    c = a * b;
                }else {
                    c = a / b;
                }
                sk.push(c);
            }else{
                sk.push(result[i]);
            }
        }
        cout << sk.top() << endl;
    }
}

样例输入

4+23-10/5#
3
(7-2)#
2*3/2#

样例输出

8
15
3

猜你喜欢

转载自blog.csdn.net/jal517486222/article/details/86572383