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

表达式求值

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

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

转换过程:

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

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

求解过程:

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

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

C++代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <stack>
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 <iostream>
#include <cstring>
#include <algorithm>
#include <stack>
#include <unordered_map>

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
表达式求值是指将一个数学表达式中的数字和运算符进行计算的过程。在计算机中,表达式求值通常采用中缀表达式后缀表达式的方式进行。中缀表达式是指运算符位于两个操作数之间的表达式,例如:3 + 4 * 5。而后缀表达式是指运算符位于操作数之后的表达式,例如:3 4 5 * +。将中缀表达式换为后缀表达式的过程中,需要使用栈来存储运算符,并按照一定的规则进行出栈和入栈操作,最终得到后缀表达式。后缀表达式的计算比较简单,只需要按照操作符从左到右的顺序依次执行即可。 在C语言中,可以使用栈来实现中缀表达式后缀表达式的过程。具体步骤如下: 1. 初始化一个字符栈和一个后缀表达式字符串。 2. 从左到右遍历中缀表达式的每个字符。 3. 如果当前字符是数字,则直接将其添加到后缀表达式字符串中。 4. 如果当前字符是左括号,则将其入栈。 5. 如果当前字符是右括号,则将栈中的字符依次出栈并添加到后缀表达式字符串中,直到遇到左括号为止。 6. 如果当前字符是运算符,则将栈中优先级大于等于该运算符的字符依次出栈并添加到后缀表达式字符串中,然后将该运算符入栈。 7. 重复以上步骤直至遍历完成中缀表达式。 8. 判断字符栈是否为空,非空则直接出栈,并将出栈字符依次送入后缀表达式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值