1、简介
离散数学中学过将中缀表达式转化为后缀表达式,再进行求解。因此,在求解中缀表达式结果时需要分两步。转化、求解。
1.1 转化
如何将一个中缀表达式转化为后缀表达式。
使用栈st1与栈st2,从左向右扫描中缀表达式
- 如果是操作数,直接压入st1
- 如果是操作符,考虑当前操作符与st2栈顶的优先级关系。
– 如果高于栈顶的优先级,则直接压入st2
–如果低于或等于栈顶的优先级,则将st2中所有操作符依次出栈并压入st1。 结束以后将当前操作符压入st2。 - 扫描完中缀表达式以后,如果st2还有剩余操作符,那么将st2中操作符依次出栈压入st1。
1.2 求解
使用一个栈st,从左向右扫描后缀表达式
- 如果是操作数,直接压入st,
- 如果是操作符,将st次栈顶与st栈顶元素(
注意顺序不能变
)之间进行操作,运算结果压入st.。
2、 代码实现
#include<iostream>
#include<stack>
#include<string>
#include<cctype>
#include<map>
using namespace std;
typedef double ElemType;
bool flag = true;
map<char,int>op;
string Transfer(string s);
ElemType cal(string s);
int main(){
string s;
cin >> s;
string sm = Transfer(s);
cout << sm << endl;
ElemType result = cal(sm);
if(flag){
cout << result;
}else{
cout << "ERROR" << endl;
}
return 0;
}
string Transfer(string s){
stack<char> st1;
stack<char> st2;
op['*'] = op['/'] = 2;
op['+'] = op['-'] = 1;
for (int i = 0; i < s.length(); i++){
char ch = s[i];
if(isdigit(ch)){
st1.push(ch);
continue;
}else{
//如果该操作符的优先级低于或等于st2栈顶优先级
//把st2中每一个操作福压到st1中
while(!st2.empty() && op[ch] <= op[st2.top()]){
st1.push(st2.top());
st2.pop();
}
//结束以后,再将改操作符压入st2中
st2.push(ch);
}
}
//如果st2还有,全部压入st1即可
while(!st2.empty()){
st1.push(st2.top());
st2.pop();
}
string st = s;
for(int i = s.length()-1; i >= 0; i--){
st[i] = st1.top();
st1.pop();
}
return st;
}
ElemType cal(string s){
stack<ElemType> st;
for(int i = 0; i < s.length(); i++){
char ch = s[i];
if(isdigit(ch)){
st.push(ch-'0');
}else{
ElemType b = st.top();
st.pop();
ElemType a = st.top();
st.pop();
ElemType c;
switch (ch) {
case '+':
c = a + b;
break;
case '-':
c = a -b;
break;
case '*':
c = a * b;
break;
case '/':
if(b == 0){
flag = false;
break;
}else{
c = a / b;
}
break;
}
st.push(c);
}
}
return st.top();
}
3、缺点
上面的代码只能解决操作数都为整数的情况,但是实际使用中,浮点数才是最常见的使用。