AcWing 3302. 表达式求值

发布时间 2023-12-04 11:32:09作者: 爬行的蒟蒻

题面:给定一个表达式,其中运算符仅包含加减乘除,可能包含括号,请你求出表达式的最终值。

原题链接:3302. 表达式求值 - AcWing

基本思路

  • 创建两个栈,分别存储数字和运算符
  • 运算符的判定:仅在以下条件满足时将运算符直接压入栈中:
    ①栈中不存在元素 ②当前运算符优先级比栈顶高 ③栈顶为左括号
    其他情况下,取出栈顶优先级较高的运算符,与数字栈顶两元素,先行计算
  • 括号的判定:当遇到右括号时,将括号内表达式优先计算
    为什么此时不需要考虑运算符优先级的问题?因为此时括号内均为同一优先级

两个核心关键点[1]

  1. 双栈:一个操作数栈,一个运算符栈;
  2. 运算符优先级:栈顶运算符,和,即将入栈的运算符的优先级比较。
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;

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

//也可以写为优先级表
unordered_map<char, int> h{ {'+', 1}, {'-', 1}, {'*',2}, {'/', 2} };
//判断运算符优先级
//int prior(char op) {
//    if (op == '+' || op == '-')
//        return 1;
//    if (op == '*' || op == '/')
//        return 2;
//    return 0;
//}

//弹出栈顶运算符,进行计算
void calculate(stack<int>& num, stack<char>& op, char opr) {
    int top = num.top();
    num.pop();
    int sec = num.top();
    num.pop();
    if (opr == '+') sec += top;
    if (opr == '-') sec -= top;
    if (opr == '*') sec *= top;
    if (opr == '/') sec /= top;
    num.push(sec);
    op.pop();
}

//初始化数字栈,运算符栈中只保留同一优先级的运算符
void init(stack<int>& num, stack<char>& op) {
    //for (size_t i = 0; str[i] != '='; i++) 
    //不需要size_t也能正确计算数字的做法
    for (int i = 0; i < str.size() ; i++) {
        if (isdigit(str[i])) {  //将字符串转换为数字并入数字栈
            double x = 0;
            int j = i;  //保存指针
            while (i < str.size() && isdigit(str[j]))
                x = x * 10 + str[j++] - '0';
            num.push(x);
            i = --j;
        }
        else if (str[i] == '(')
            op.push(str[i]);
        else if (str[i] == ')') {   //优先计算括号中表达式
            while (!op.empty() && op.top() != '(')
                calculate(num, op, op.top());
            op.pop();
        }
        else {
            //待入栈运算符优先级低,则先计算
            while (!op.empty() && h[str[i]] <= h[op.top()])
                calculate(num, op, op.top());
            op.push(str[i]);
        }
    }
}

//此时运算符只有相同优先级,即加减,一次性计算完毕
int finalCal(stack<int>& num, stack<char>& op) {
    while (!op.empty())
        calculate(num, op, op.top());
    return num.top();
}

int main()
{
    cin >> str;
    init(num, op);
    cout << finalCal(num, op);
    return 0;
}

  1. https://www.acwing.com/solution/content/40978/ ↩︎