逆波兰表达式

一般我们在表达运算式时都用中序表达式,但是这样的表达方式并不适合机器来进行运算。以表达式1+2*3为例,计算机会将会解析这个表达式,然后递归求值。比如从左起顺序解析,符号树为:

  +

 /  \

1   *

    /   \

  2     3

计算机会递归的计算子树,直到根节点。这样空间和时间的消耗都很多。因此波兰数学家扬·武卡谢维奇提出了逆波兰表达式。逆波兰表达式的数字都在符号前面,计算的时候从左到右扫描,遇到符号就计算,大大的节省了空间和时间的消耗。

leetcode上https://leetcode.com/problems/evaluate-reverse-polish-notation/#/description,这道题 是求解逆波兰表达式的值。我写的代码是这样的:

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        if (tokens.empty()) {
            return 0;
        }
        if (tokens[0] == "+" || tokens[0] == "-" || tokens[0] == "*" || tokens[0] == "/") {
            return 0;
        }
        stack<int> st;
        int i = 0;
        for (int i = 0; i < tokens.size(); i++) {
            if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/") {
                int top1 = st.top();
                st.pop();
                int top2 = st.top();
                st.pop();
                if (tokens[i] == "+") {
                    st.push(top2 + top1);
                }
                else if (tokens[i] == "-") {
                    st.push(top2 - top1);
                }
                else if (tokens[i] == "*") {
                    st.push(top2 * top1);
                }
                else if (tokens[i] == "/") {
                    st.push(top2 / top1);
                }
                else {
                    return 0;
                }
            }
            else {
                st.push(stoi(tokens[i]));
            }
        }
        return st.top();
    }
};
而关于如何将中序表达式转为后序表达式。可以参考上面的做法,建立两个栈s1和s2,s1存储后序表达式的结果,s2存储运算符号。从左到右遍历,如果当前符号是数字则推入s1,如果当前符号是"("推入s2,如果当前符号是")",将(之前的符号都弹出,推入s1;如果当前符号的优先级大于s2的顶部,则推入栈,否则一直弹出直到当前符号的优先级大于等于s2的顶部。最后把s2的所有符号都推入s1。

#include <iostream>
#include <string>
#include <stack>
#include <algorithm>
using namespace std;

bool compare(char op1, char op2) {
    if (op1 == '*' || op1 == '/') {
        if (op2 == '+' || op2 == '-') {
            return 1;
        }
        else {
            return 0;
        }
    }
    else if (op1 == '+' || op1 == '-') {
        if (op2 == '*' || op2 == '/') {
            return -1;
        }
        else {
            return 0;
        }
    }
    return 0;
}

int main() {
    string a = "(2+3*1)*5+1/2";
    stack<char> ope;
    stack<char> res;
    for (int i = 0; i < a.size(); i++) {
        if (a[i] >= '0' && a[i] <= '9') {
            res.push(a[i]);
        }
        else if (a[i] == '(') {
            ope.push(a[i]);
        }
        else if (a[i] == ')') {
            //char tmp = ope.top();
            while (ope.top() != '(') {
                res.push(ope.top());
                ope.pop();
                //tmp = ope.top();
            }
            ope.pop();
        }
        else{
            if (ope.empty()) {
                ope.push(a[i]);
                continue;
            }
            int cmp = compare(a[i],ope.top());
            if (cmp >= 0) {
                ope.push(a[i]);
            }
            else {
                while (!ope.empty() && compare(a[i], ope.top()) < 0) {
                    res.push(ope.top());
                    ope.pop();
                }
                ope.push(a[i]);
            }
        }
    }
    while (!ope.empty()) {
        res.push(ope.top());
        ope.pop();
    }
    string b = "";
    while (!res.empty()) {
        b += res.top();
        res.pop();
    }
    reverse(b.begin(), b.end());
    cout << b;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值