问题描述:
实现思路:
使用栈实现一个求逆波兰表达式的函数,求出表达式后,再通过逆波兰表达式的求值算法,再通过栈求出表达式的值。求值方法见力扣的150题:
实现代码:
#include <iostream>
#include <string>
#include <vector>
#include <stack>
class Solution {
private:
std::stack<float> ans;//求结果的栈
std::stack<char> pre_notation;//求后缀表达式的栈
std::vector<std::string> reversePolishNotation;//后缀表达式
private:
bool isNumber(char& str) {//判断数字
return !(str == '+' || str == '-' || str == '*' || str == '/' || str == '(' || str == ')');
}
bool isNumber(std::string& str) {//判断数字
return !(str == "+" || str == "-" || str == "*" || str == "/" || str == "(" || str == ")");
}
public:
float evacuateReversePolishNotation(std::string& str) {//计算后缀表达式的值
while (!ans.empty()) {ans.pop();}//清除原有的元素
std::string temp = str;
gainReversePolishNotation(temp);
for (int i = 0; i < reversePolishNotation.size(); ++i) {
std::string& s = reversePolishNotation[i];
if (isNumber(s)) {
ans.push(std::stol(s));
} else {
float num1 = ans.top();
ans.pop();
float num2 = ans.top();
ans.pop();
switch(s[0]) {
case '*' : ans.push(num1 * num2);break;
case '/' : ans.push(num2 / num1);break;
case '+' : ans.push(num1 + num2);break;
case '-' : ans.push(num2 - num1);break;
}
}
}
return ans.top();
}
void gainReversePolishNotation(std::string& str) {//求后缀表达式
while (!pre_notation.empty()) {pre_notation.pop();}//清除原有的元素
reversePolishNotation.clear();
for (int i = 0; i < str.size(); ++i) {
if (str[i] != ' ') {//如果不是空格
char& temp = str[i];
if (isNumber(temp)) {//如果该字符是数字
std::string post_str;
post_str.push_back(temp);
while (str[i+1] != ' ' && isNumber(str[i + 1]) && i + 1 < str.size()) {//可能数字不止一位
post_str.push_back(str[++i]);
}
reversePolishNotation.push_back(post_str);
} else {//如果该字符不是数字
std::string temp_str;
switch (temp) {
case '*' ://乘法,直到弹出栈顶遇到的所有*和/,然后推入*
while (!pre_notation.empty() && (pre_notation.top() == '/' || pre_notation.top() == '*')) {
std::string post_str;
post_str.push_back(pre_notation.top());
reversePolishNotation.push_back(post_str);//推入后缀表达式
pre_notation.pop();
}
pre_notation.push(temp);
break;
case '/' ://除法,直到弹出栈顶遇到的所有*和/,然后推入/
while (!pre_notation.empty() && (pre_notation.top() == '/' || pre_notation.top() == '*')) {
std::string post_str;
post_str.push_back(pre_notation.top());
reversePolishNotation.push_back(post_str);//推入后缀表达式
pre_notation.pop();
}
pre_notation.push(temp);
break;
case '-' ://减法,直到弹出栈顶遇到的所有*和/和+和-,然后推入-
while (!pre_notation.empty() && (pre_notation.top() == '/' || pre_notation.top() == '*' || pre_notation.top() == '+'|| pre_notation.top() == '-')) {
std::string post_str;
post_str.push_back(pre_notation.top());
reversePolishNotation.push_back(post_str);//推入后缀表达式
pre_notation.pop();
}
pre_notation.push(temp);
break;
case '+' ://加法,直到弹出栈顶遇到的弹出所有*和/和+和-,然后推入+
while (!pre_notation.empty() && (pre_notation.top() == '/' || pre_notation.top() == '*' || pre_notation.top() == '-' || pre_notation.top() == '+')) {
std::string post_str;
post_str.push_back(pre_notation.top());
reversePolishNotation.push_back(post_str);//推入后缀表达式
pre_notation.pop();
}
pre_notation.push(temp);
break;
case ')' : //遇到右括号,执行出栈操作,输出到后缀表达式,直到弹出的是左括号
while (!pre_notation.empty() && pre_notation.top() != '('){
std::string post_str;
post_str.push_back(pre_notation.top());
reversePolishNotation.push_back(post_str);//推入后缀表达式
pre_notation.pop();
}
pre_notation.pop();//弹出左括号
break;
case '(' ://遇到左括号,入栈
pre_notation.push(temp);
break;
}
}
} else {//如果是空格
continue;
}
}
while (!pre_notation.empty()) {//剩余内容推入后缀表达式
std::string post_str;
post_str.push_back(pre_notation.top());
reversePolishNotation.push_back(post_str);
pre_notation.pop();
}
}
};
int main() {
std::vector<std::string> inputs;
std::string temp;
std::getline(std::cin, temp);
while (temp != "0") {
inputs.push_back(temp);
std::getline(std::cin, temp);
}
Solution* ans = new Solution();
for (int i = 0; i < inputs.size(); ++i) {
printf("%.2f\n", ans->evacuateReversePolishNotation(inputs[i]));
}
delete ans;
return 0;
}
备注:
代码纯自己手撸,由于hdu目前不开了,所以也没法提交代码验证正确性。具体求后缀表达式的思路和方法大家参见别人的博客。如有错误欢迎指出(应该没有吧,改了一下午了233)。