根据逆波兰表示法,求表达式的值。
有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:
整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
示例 1:
输入: [“2”, “1”, “+”, “3”, “*”]
输出: 9
解释: ((2 + 1) * 3) = 9
示例 2:
输入: [“4”, “13”, “5”, “/”, “+”]
输出: 6
解释: (4 + (13 / 5)) = 6
后缀表达式,可以看作是一棵树的后序遍历,树的叶子节点均为操作数,非叶子节点均为操作符号
中序遍历特征就是先看子节点 再看父节点
所以对于后缀表达式的解析,只需要一个栈来存取操作数
从左→→→右遍历:
— 遇到操作数则入栈
— 遇到操作符号则说明 该子树的孩子节点都遍历完了,回到了父节点了(后序遍历的逻辑),则将栈顶弹出两个操作数 和 该操作符号 进行运算
#include <vector>
#include <string>
#include <stack>
#include <algorithm>
using namespace std;
class Solution {
private:
stack<int> operandStack;
public:
int evalRPN(vector<string>& tokens) {
for (int i = 0; i < tokens.size(); i++)
if (isSymbol(tokens[i])) {
int a = operandStack.top();
operandStack.pop();
int b = operandStack.top();
operandStack.pop();
operandStack.push(operateNums(b, a, tokens[i]));
}
else
operandStack.push(stoi(tokens[i]));
return operandStack.top();
}
private:
bool isSymbol(const string &str) {
if (str == "+" || str == "-" || str == "*" || str == "/")
return true;
else
return false;
}
int operateNums(const int& a, const int &b, string operatorStr) {
int sum = 0;
if (operatorStr == "+")
sum = a + b;
else if (operatorStr == "-")
sum = a - b;
else if (operatorStr == "*")
sum = a * b;
else if (operatorStr == "/")
sum = a / b;
return sum;
}
};
拓展:
https://www.cnblogs.com/chensongxian/p/7059802.html
此博客详细讲解了前缀、中缀、后缀,以及中缀转前缀、中缀转后缀。
中缀转前缀 与 中缀转后缀:
使用两个栈,分别维护操作符和数字,来进行 中缀 转 前缀or后缀
1、中缀转前缀:
(1)初始化两个栈:运算符 栈s1,储存中间结果(操作数)的 栈s2
(2)从左←←←右扫描中缀表达式
(3)遇到操作数时,将其压入s2
(4)遇到运算符时,比较其与s1栈顶运算符的优先级
--------如果s1为空,或栈顶运算符为右括号 “)”,则直接将此运算符入s1
--------否则,若优先级比栈顶运算符的较高或相等,也将运算符压入s1
--------否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4) 与s1中新的栈顶运算符相比较
(5)遇到括号时
--------如果是右括号 “)”,则直接压入s1
--------如果是左括号 “(”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到右括号“)” 为止,此时将这一对括号丢弃
(6)重复步骤2→→5,直到表达式的最左边
(7)将s1中剩余的运算符依次弹出并压入s2
(8)依次弹出s2中的元素并输出,结果即为中缀表达式对应的前缀表达式
2、中缀转后缀:
(1)初始化两个栈:运算符 栈s1,储存中间结果(操作数)的 栈s2
(2)从左→→→右扫描中缀表达式
(3)遇到操作数时,将其压s2
(4)遇到运算符时,比较其与s1栈顶运算符的优先级:
--------如果s1为空,或栈顶运算符为左括号 “(”,则直接将此运算符入s1
--------否则,若优先级比栈顶运算符的高,也将运算符压入s1(注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况)
--------否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4) 与s1中新的栈顶运算符相比较
(5)遇到括号时:
--------如果是左括号 “(”,则直接压入s1
--------如果是右括号 “)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到 左括号"(" 为止,此时将这一对括号丢弃
(6)重复步骤 2→→5,直到表达式的最右边
(7)将s1中剩余的运算符依次弹出并压入s2
(8)依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)