表达式求值(中缀转后缀)

表达式求值

https://www.acwing.com/problem/content/3305/

首先进行中缀转后缀,然后根据后缀表达式求值。

转换过程:

准备一个符号栈,从左到右依次扫描中缀表达式

  • 如果遇到数字,直接输出
  • 若为 (,直接入栈
  • 若为 ),依次出栈并输出,直到遇见 (,左括号出栈但不输出
  • 若为 +-,依次出栈并输出,直到遇见 ( 或栈空;
  • 若为 */,若栈顶为 */,依次出栈并输出

求解过程:

准备一个数字栈,从左到右依次扫描后缀表达式

  • 若为数字,直接压入栈中
  • 若为操作符,取栈顶两个元素分别做相应运算,并将结果压入栈中(注意运算次序,先出栈的是第二个操作数,后出栈的是第一个操作数)

C++代码

#include 
#include 
#include 
#include 
using namespace std;

stack<char> stk;
stack<int> s;

// (2+2)*(1+1)
int main() {
    string str; cin >> str;
    string res;
    for (int i = 0; i < str.length(); i ++) {
        if (str[i] >= '0' && str[i] <= '9') {
            do {
                res += str[i ++];
            } while(i < str.length() && str[i] >= '0' && str[i] <= '9');
            if (i < str.length()) i --;
            res += " ";
        } else if (str[i] == '(') { // 入栈
            stk.push('(');
        } else if (str[i] == ')') { // 出栈
            while(stk.top() != '(') {
                res += stk.top();
                res += " ";
                stk.pop();
            }
            stk.pop();
        } else if (str[i] == '+' || str[i] == '-') {
            while(stk.size() && (stk.top() == '*' || stk.top() == '/' || stk.top() == '+' || stk.top() == '-')) { // + - * / 全部弹出
                res += stk.top();
                res += " ";
                stk.pop();
            }
            stk.push(str[i]);
        } else {
            while(stk.size() && (stk.top() == '*' || stk.top() == '/')) { // * / 全部弹出
                res += stk.top();
                res += " ";
                stk.pop();
            }
            stk.push(str[i]);
        }
    }
    while(stk.size()) {
        res += stk.top();
        res += " ";
        stk.pop();
    }
    // cout << res << endl;
    for (int i = 0; i < res.length(); i ++) {
        if (res[i] >= '0' && res[i] <= '9') {
            int t = 0;
            while(i < res.length() && res[i] != ' ') {
                t = t * 10 + res[i ++] - '0';
            }
            s.push(t);
        } else if (res[i] != ' ') {
            int a1 = s.top(); s.pop();
            int a2 = s.top(); s.pop();
            if (res[i] == '+') {
                s.push(a1 + a2);
            } else if (res[i] == '-') {
                s.push(a2 - a1);
            } else if (res[i] == '*') {
                s.push(a2 * a1);
            } else {
                s.push(a2 / a1);
            }
        }
    }
    cout << s.top() << endl;
    return 0;
}

简洁做法

边转后缀边求值

根据遇到符号决定操作:

  • 数字:读取数字并压入数字栈
  • 左括号:压入符号栈
  • 右括号:执行运算操作,直到符号栈遇到左括号,将左括号弹出
  • 加减乘除:当前符号的优先级小于等于栈顶时,执行运算操作,将栈中能算的算完
#include 
#include 
#include 
#include 
#include 

using namespace std;

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

void eval() {
    int b = num.top(); num.pop();
    int a = num.top(); num.pop();
    char 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);
}

string str;
int main() {
    cin >> str;
    unordered_map<char, int> pr{{'-', 1}, {'+', 1}, {'*', 2}, {'/', 2}};    
    for (int i = 0; i < str.length(); i ++) {
        auto c = str[i];
        if (isdigit(c)) {
            int d = 0, j = i;
            while(j < str.length() && isdigit(str[j])) {
                d = d * 10 + str[j ++] - '0';
            }
            num.push(d);
            i = j - 1;
        } else if (c == '(') op.push(c);
        else if (c == ')') {
            while(op.top() != '(') {
                eval();
            }
            op.pop();
        } else {
            while(op.size() && op.top() != '(' && pr[op.top()] >= pr[c]) eval();
            op.push(c);
        }
    }
    while(op.size()) eval();
    cout << num.top() << endl;
    return 0;
}

你可能感兴趣的:(数据结构,c++,算法,蓝桥杯,数据结构)