前几天刷LeetCode时,刷到了LeetCode---224. Basic Calculator和LeetCode---227. Basic Calculator II这两题,都是解析字符串中的四则表达式。题目分别如下:
题目意思很明确,输入的是字符串形式的四则运算,要求输出其四则运算的结果。记得曾经在《大话数据结构》那一本书上见到过使用后缀表达式来求解这类问题。所幸就动手实现一遍。这里可能有两个概念需要解释一下,中缀表达式:就是我们平时正常书写的表达式,运算符位于操作数的中间,例如:9 + 3 * 2,可以看出,运算符 + 与 * 都位于其操作数的中间。后缀表达式就是将运算符提取出来,放到操作数的后面,如中缀表达式 9 + 3 对应的后缀表达式为 9 3 +。当中缀表达式中含有(),+,-,*,/等运算符时怎么由中缀表达式转化为后缀表达式,这里不想过多的讨论了。大家可以参考《大话数据结构》4.9节---栈的应用---四则运算表达式求值( P104页)。下面直接看AC的代码,可以同时解决这两道题:
class Solution {
public:
int calculate(string s) {
//求后缀表达式
string postOrder;
stack symbol;
map priority = {
{'(',0},
{'+',1},
{'-',1},
{'*',2},
{'/',2},
};
for(int i = 0;i < (int)s.length(); ++i) {
if(s[i] == ' ') {
continue ;
} else if(isdigit(s[i])) {
postOrder += s[i];
while(i < s.length() - 1 && isdigit(s[i + 1])) {
postOrder += s[++i];
}
} else if(symbol.empty() || s[i] == '(' || (priority[s[i]] > priority[symbol.top()] && s[i] != ')')) {
symbol.push(s[i]);
} else if(s[i] == ')') {
while(!symbol.empty() && symbol.top() != '(') {
postOrder += symbol.top();
symbol.pop();
postOrder += " ";
}
symbol.pop();
} else {
while(!symbol.empty() && priority[s[i]] <= priority[symbol.top()]) {
postOrder += symbol.top();
symbol.pop();
postOrder += " ";
}
symbol.push(s[i]);
}
if(!postOrder.empty() && postOrder.back() != ' ') {
postOrder += " ";
}
}
while(!symbol.empty()) {
postOrder += symbol.top();
symbol.pop();
postOrder += " ";
}
//利用后缀表达式来求值
istringstream iss(postOrder);
stack st;
int num = 0;
char c = '\0';
while(iss.peek() != EOF) {
if(isdigit(iss.peek())) {
iss >> num;
st.push(num);
iss.ignore();
} else {
int num1 = st.top(); st.pop();
int num2 = st.top(); st.pop();
iss >> c;
switch(c) {
case '+' : st.push(num2 + num1); break;
case '-' : st.push(num2 - num1); break;
case '*' : st.push(num2 * num1); break;
case '/' : st.push(double(num2) / double(num1)); break;
}
iss.ignore();
}
}
return st.top();
}
};