逆波兰表达式
正常表达式转化逆波兰表达式
- 创建两个栈命名为s1, s2。
- 遍历待转化的表达式,如果是数字,直接丢进s2。
- 如果是左括号’(’,丢进s1。
- 如果是符号’+’, ‘-’, ‘*’, ‘/’,本质上是维护一个运算优先级严格单调递增栈,即如果s1栈顶符号运算优先级高于或者等于当前符号,出栈直到栈空或者栈顶运算符号优先级低于当前符号。如果s1栈顶符号运算优先级低于(不包括等于)当前符号,当前符号入s1。
- 左括号是优先级最低的。
- 如果是右括号,把栈内的符号全部弹出放入s2,直到遇到左括号,并丢弃该左括号。
- 遍历完毕时,s1如果还有东西,全部丢给s2。
- 此时s2从栈低到栈顶就是一个逆波兰表达式。
逆波兰表达式求值
- 创建一个栈
- 遍历逆波兰表达式
- 遇见数字,丢入栈
- 遇见符号,出栈num1,删除栈顶,出栈num2,删除栈顶,注意顺序,求值num = num2 ±*/ num1,再一次提示,注意顺序。
- 然后将num放入栈
- 最后栈顶元素即为答案。
772. 基本计算器 III
实现一个基本的计算器来计算简单的表达式字符串。
表达式字符串只包含非负整数,算符 +、-、*、/ ,左括号 ( 和右括号 ) 。整数除法需要 向下截断 。
你可以假定给定的表达式总是有效的。所有的中间结果的范围为 [-231, 231 - 1] 。
代码
class Solution {
public:
int calculate(string s) {
//表达式转换逆波兰表达式
//创建双栈
stack<char> s1;
stack<string> s2;
int n = s.size();
int l = 0;
while(l < n) {
//碰见数字,全部转换丢入s2
if(s[l] >= '0' && s[l] <= '9') {
int r = l + 1;
while(r < n && s[r] >= '0' && s[r] <= '9') {
r++;
}
s2.push(s.substr(l, r - l));
l = r;
}
//碰见符号
else {
//左括号直接丢入s1
if(s[l] == '(') {
s1.push(s[l]);
}
//+-号是运算级最低的,严格单调递增
else if(s[l] == '+' || s[l] == '-') {
//所以即使碰见同一运算级的+-也还是要出栈
while(!s1.empty() && (s1.top() == '*' || s1.top() == '/' || s1.top() == '+' || s1.top() == '-')) {
//出栈的符号直接丢入s2
string tmp = "";
tmp += s1.top();
s2.push(tmp);
s1.pop();
}
//最后将当前符号丢入s1
s1.push(s[l]);
}
//*/是运算级最高的
else if(s[l] == '*' || s[l] == '/') {
//所以仅在碰见同一优先级*/才出栈
while(!s1.empty() && (s1.top() == '*' || s1.top() == '/')) {
string tmp = "";
tmp += s1.top();
s2.push(tmp);
s1.pop();
}
s1.push(s[l]);
}
//碰见右括号
else if(s[l] == ')'){
//s1的符号全部出栈,直到碰见左括号
while(!s1.empty() && s1.top() != '(') {
string tmp = "";
tmp += s1.top();
s2.push(tmp);
s1.pop();
}
//丢弃该左括号
if(!s1.empty() && s1.top() == '(') {
s1.pop();
}
}
l++;
}
}
//遍历完了如果s1还有符号,全部丢入s2
while(!s1.empty()) {
string tmp = "";
tmp += s1.top();
s2.push(tmp);
s1.pop();
}
//此时s2从栈低到栈顶就是逆波兰表达式
//转换为vec准备求值
vector<string> vec;
while(!s2.empty()) {
vec.emplace_back(s2.top());
s2.pop();
}
//逆波兰表达式求值
//创建一个栈
stack<int> stk;
//遍历逆波兰表达式
//由于从栈逐一弹出,所以逆序遍历vec才是逆波兰表达式
for(int i = vec.size() - 1; i >= 0; i--) {
//碰见数字,丢入栈
if(vec[i].size() != 1 || (vec[i][0] >= '0' && vec[i][0] <= '9')) {
stk.push(stoi(vec[i]));
}
//碰见符号,出两个栈的数,注意顺序,后出栈的数是第一操作数,计算完毕再入栈
else {
if(vec[i] == "+") {
int num1 = stk.top();
stk.pop();
int num2 = stk.top();
stk.pop();
stk.push(num1 + num2);
}
else if(vec[i] == "-") {
int num1 = stk.top();
stk.pop();
int num2 = stk.top();
stk.pop();
stk.push(num2 - num1);
}
else if(vec[i] == "*") {
int num1 = stk.top();
stk.pop();
int num2 = stk.top();
stk.pop();
stk.push(num2 * num1);
}
else {
int num1 = stk.top();
stk.pop();
int num2 = stk.top();
stk.pop();
stk.push(num2 / num1);
}
}
}
return stk.top();
}
};