这里为可带括号的四则运算求值,先转为逆波兰表达式,再解逆波兰表达式的值,解法具有可拓展性
class ReversePolishNotation {
public:
ReversePolishNotation(string s) {
if (!s.empty()) {
transferToRePolish(s);
computeReversePolish();
}
}
private:
//计算逆波兰表达式的值,栈的经典应用
void computeReversePolish() {
stack<float> stk;
for (auto s : v) {
if (!isOperator(s)) {
stk.emplace(stof(s));
}else {
float y = stk.top();
stk.pop();
float x = stk.top();
stk.pop();
float num;
if (s == "+") num = x + y;
else if (s == "-") num = x - y;
else if (s == "*") num = x*y;
else num = x / y;
stk.emplace(num);
}
}
cout << stk.top() << endl;
}
//中缀表达式转换为逆波兰表达式,也是栈的经典应用
//遍历到完整数字,追加到逆波兰表达式式尾
//遍历到左括号入栈,遇到右括号,弹栈直到遇到左括号,把弹出的元素追加到逆波兰表达式式尾
//遍历操作符ch,如果它的优先级小于等于栈顶操作符的优先级,则弹栈,把弹出的元素追加到逆波兰表达式式尾,
//最后把该操作符ch压栈,维持栈顶优先级最高,维持一个递增栈。
//遍历结束时,弹出所有的元素,并依次追加到逆波兰表达式式尾
void transferToRePolish(const string& s) {
int size = s.size();
stack<char> stk;
int i = 0;
while (i < size) {
if ((s[i] >= '0'&&s[i] <= '9') || s[i] == '.') {
int j = i;
while (s[i] >= '0'&&s[i] <= '9')
i++;
if (j - 1 >= 0 && (s[j - 1] == '-' || s[j - 1] == '+') && j - 2 >= 0 && s[j - 2] == '(') {
stk.pop();
v.emplace_back(s.substr(j - 1, i - j + 1));
}
else
v.emplace_back(s.substr(j, i - j));
}
else if (s[i] == '(') {
stk.push(s[i++]);
}
else if (s[i] == ')') {
while (stk.top() != '(') {
v.emplace_back(to_string(stk.top()));
stk.pop();
}
stk.pop();
i++;
}else {
while (!stk.empty() && priority(s[i]) <= priority(stk.top())) {
v.emplace_back(to_string(stk.top()));
stk.pop();
}
stk.emplace(s[i]);
i++;
}
}
while (!stk.empty()) {
v.emplace_back(to_string(stk.top()));
stk.pop();
}
}
int priority(char ch) {
switch (ch) {
case '(': return 0;
case '-':
case '+': return 1;
case '*':
case '/': return 2;
default: return -1;
}
}
bool isOperator(const string& s) {
return s.size() == 1 && string("+-*/").find(s[0]) != string::npos;
}
private:
vector<string> v;
};