表达式求值

时间复杂度O(n)

#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#include <stack>

using namespace std;

stack<char> op;
stack<int> num;

void eval()
{
    auto b = num.top(); num.pop();
    auto a = num.top(); num.pop();
    auto c = op.top(); op.pop();

    int x;
    if (c == '+') x = a + b;
    else if (c == '-') x = a - b;
    else if (c == '*') x = a * b;
    else x = a / b;
    num.push(x);
}
/**
 * 定义简单表达式:无括号且操作符递增的表达式为简单表达式,如1 - 2 + 3 * 5 / 6
 * 定义复杂表达式: 1)带括号的复杂复杂表达式,如:(1 - 3) * 4
 *                 2)局部操作符无序,如:1 - 2 + 3 * 4 - 5
 * 对于这种算法其实就是一趟运算树的中序遍历,再遍历的过程中括号内的东西在遇到右括号的时候就算完了,
 * 然后最终留下的是没有括号的简单的表达式,从而在经过一次后缀表达式的运算就可以了
 * 
 * 该算法保证了,每次操作后的结果都是一个简单表达式,为下次遇到复杂表达式做铺垫,本质上是递归的一个过程,但是转换成了遍历。
 **/
int main()
{
    string s;
    cin >> s;

    unordered_map<char, int> pr{{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}};
    for (int i = 0; i < s.size(); i ++ )
    {
        if (isdigit(s[i]))//如果是数的话就直接加入数字栈中
        {
            int j = i, x = 0;
            while (j < s.size() && isdigit(s[j]))
                x = x * 10 + s[j ++ ] - '0';
            num.push(x);
            i = j - 1;
        }
        else if (s[i] == '(') op.push(s[i]);//如果是左括号就加入符号栈中
        else if (s[i] == ')')//当遇到右括号就一直操作到左括号,同时此时括号内的表达是已经经过运算的简单表达式,而这步操作也同样是把带括号的复杂表达式简单化
        {
            while (op.top() != '(') eval();
            op.pop();
        }
        else//这一步处理复杂表达式变为简单表达式比如1 * 2 + 3 -> 2 + 3
        {
            while (op.size() && op.top() != '(' && pr[op.top()] >= pr[s[i]])
                eval();
            op.push(s[i]);
        }
    }

    while (op.size()) eval();//最终运算一下处理过后的简单表达式
    cout << num.top() << endl;

    return 0;
}
posted @ 2021-08-15 14:40  NgAgo  阅读(98)  评论(0)    收藏  举报