具体思路:
Step1: 将中缀表达式转为后缀表达式
Step2: 后缀表达式求值
算法部分
Step1:
先声明两个需要用到的容器:stack,string
#include <string>
#include <stack>
...
stack <char> s; //push the operators in it
string ans; //save the postfix expression
...
从左到右依次扫描输入
- 遇到数字则直接输出。
- 遇到运算符且栈不为空则将其与栈顶运算符对比优先级,该运算符优先级大于栈顶运算符则将其压入,否则将栈顶元素一直弹出并输出直到给运算符优先级大于栈顶运算符为止。(栈为空则直接压入)
- 遇到左括号直接压入栈中。
- 遇到右括号将栈顶元素依次弹出并输出,直到遇到对应的左括号为止,然后将左括号弹出。
- 读到输入结尾后将栈内元素依次弹出
根据以上规则,我们可以进行这样的优化:
如:(1+2)*2 => ((1+2)*2)
这样就可以将第5点省去了,并且可以不用对栈进行判空(第2点)。
关于优先级的判定,姑且假设一共只有’+’,’-’,‘×’,‘÷’,’^'这五种运算,则:
运算符 | 优先级(数字越大优先级越高) |
---|---|
^ | 3 |
* / | 2 |
+ - | 1 |
因为要排除’('对判断的干扰,则左括号的优先级为0(最低)。
代码如下:
inline int priority(const char _Operator) {
switch(_Operator) {
case '+':
case '-': return 1;
case '*':
case '/': return 2;
case '^': return 3;
default: return 0;
}
}
所以完整的代码如下:
inline void InfixExpToPostfixExp(string &ans, const string str) { //中綴表達式轉為後綴表達式,ans為答案,str為輸入
stack <char> s;
for (size_t i = 0; i < str.length(); ++i) {
if (isdigit(str[i])) {
while (isdigit(str[i])) {
ans.push_back(str[i]);
++i;
}
ans.push_back(' ');
}
if (str[i] == '(') {
s.push(str[i]);
continue;
}
if (str[i] == ')') {
while (s.top() != '(') {
ans.push_back(s.top());
ans.push_back(' ');
s.pop();
}
s.pop();
continue;
}
if (priority(str[i]) > priority(s.top())) {
s.push(str[i]);
continue;
} else {
//一直彈到該運算符比棧頂運算符優先級大為止
//例如:s = "^*+"(自下而上)str[i] = '-'
//則現將'+'彈出,再將*彈出,最後將^彈出
//如果不加while判斷則只會彈出'+',然後將'-'壓入,以致錯誤
while (priority(str[i]) <= priority(s.top())) {
ans.push_back(s.top());
ans.push_back(' ');
s.pop();
}
s.push(str[i]);
}
}
}
运行结果如下:
Step2:
后缀表达式的求值还是比较简单的
先定义一个数字栈
#include <stack>
...
stack <int> s;
...
从左到右依次扫描表达式
- 遇到数字将其压入栈中。
- 遇到运算符则将栈顶的两个数字取出后进行运算,(如:某个栈最上面一个元素x为’123’,第二个元素y为’6’,运算符为’-’,则答案为y-x(按找入栈的先后进行计算)。)将计算的结果压入栈中。
- 最后的答案则为s.top()。
因为比较简单,所以就不一一细讲了,代码如下:
inline int PostfixExp(const string str) { //後綴表達式求值(利用stack),str為後綴表達式
stack <int> s;
for (size_t i = 0; i < str.length(); ++i) {
if (isdigit(str[i])) {
string temp = "";
while (isdigit(str[i])) {
temp.push_back(str[i]);
++i;
}
int weight = 1, sum = 0;
for (int j = temp.length() - 1; j >= 0; --j) {
sum += (temp[j] - '0') * weight;
weight *= 10;
}
s.push(sum);
}
else if (isoperator(str[i])) {
int x = s.top(); s.pop();
int y = s.top(); s.pop();
if (str[i] == '+') s.push(y + x);
if (str[i] == '-') s.push(y - x);
if (str[i] == '*') s.push(y * x);
if (str[i] == '/') s.push(y / x);
if (str[i] == '^') {
int ans = 1;
for (int i = 1; i <= x; ++i)
ans *= y;
s.push(ans);
}
}
}
return s.top();
}