逆波兰表达式

逆波兰表达式也叫后缀表达式,先操作数,后操作符

例如,5×(6+3)÷3-1 

就是中缀表达式。下面这个就是后缀表达式:

563+×3÷1-   

中缀表达式变后缀表达式方法

见到数字直接输出,见到符号按一定规则入栈出栈
规则就是,用当前的符号与栈顶的符号比较优先级,如果当前符号优先级小于栈顶符号的优先级,则把栈里面的符号都弹出来。括号的操作除外,括号是左括号优先级最高,不管跟啥比,都是入栈;右括号是优先级最低,跟啥比都是弹出栈内符号,但只弹到跟它匹配的最近的那个左括号。

这里就涉及到一个符号优先级的问题。看下图吧,从上往下的符号是优先级从高到低。

5×(6+3)÷3-1

先看到的是5,直接输出,现在的后缀表达式为:“5”。下一个,“×”,压入栈中。下一个,“(”,优先级超级高,处在金字塔顶端的符号,也压入栈中。下一个,“6”,数字,直接输出,现在的后缀表达式为:“56”

下一个, “+” ,当栈顶是 “(” 的时候,当前的符号优先级是一定小于 “(” 的,但不能还按照原来的规则,把栈内符号弹出。 “(” 的弹出条件是等到与之匹配的最近的 “)” 。只有等到了 “)” , “(” 才弹出。当然了, “(” 和 “)” 中间一定还会有别的运算符,弹的时候一起都弹出来。而且当遇到 “)” 的时候,不是全栈都弹出来,而是弹到 “(” 停止。那么,再说回来,当前符号是 “+” ,由于 “(” 只等到 “)” 才弹出,所以把 “+” 压入栈中。下一个, “3” ,直接输出。

下一个, “)” ,这个优先级极低,所以弹出栈中元素,但这个也不能按常规的规则操作。遇到 “)” 了,不应把全栈都弹出来,而是只弹到 “(” ,因此,现在栈里面从栈顶一直往下弹,弹到 “(” 为止。

下一个, “÷” ,跟栈顶符号 “×” 比优先级为同级,则将栈中元素都弹出来,即 “×” 弹出,将 “÷” 压入栈中。因为转换规则是,当前符号与栈顶符号比较,优先级大于栈顶符号,才不弹出直接压入;否则就要先弹出,即清空栈再压入。

简单说就是,当前符号优先级大于栈顶符号优先级时,不弹出直接压入;小于等于时,弹出再压入。

下一个, “3” ,直接输出,此时输出为:563+×3。下一个, “-” ,这个符号跟栈顶符号比较,优先级低于栈顶符号,so,弹出栈中元素,把 “-” 压入栈中。

下一个, “1” ,直接输出,此时输出为:563+×3÷1。原中值表达式没有元素了,最后一步操作将栈内还没弹出的符号都弹出。【在计算机中,其实是自动向中缀表达式末尾填充一个 “#” ,由于 “#” 优先级最低,这样在搜索到 “#” 时,就会清空栈。但 “#” 不参与表达式的计算,就是输出时,没有 “#” 。这和数组最后一位是结束符是同样的道理。】弹出时符号写在输出中的顺序是,按从栈底到栈顶这个顺序在输出表达式中从左到右列出。最后的输出就是:563+×3÷1-

算法总结:

逆波兰表达式求值

当我们以后缀表达式输入时,按规则可以求出计算结果并打印

#include <stack>
class Solution {
public:
    int evalRPN(vector<string> &tokens) {
        int i=0;
        stack<int> s;
        int ret=0;
        while(i<tokens.size()){
            while(i<tokens.size() && tokens[i]!="+" && tokens[i]!="-" && tokens[i]!="*" && tokens[i]!="/")
                s.push(atoi(tokens[i++].c_str()));
            int right_num=s.top();
            s.pop();
            if(s.empty())
                return right_num;
            int left_num=s.top();
            s.pop();
            if(tokens[i]=="+")
                ret=left_num+right_num;
            else if(tokens[i]=="-")
                ret=left_num-right_num;
            else if(tokens[i]=="*")
                ret=left_num*right_num;       
            else if(tokens[i]=="/")
                ret=left_num/right_num;
            s.push(ret);
            i++;
        }
        return s.top();
    }
};

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值