经典问题:给出一个表达式,求其运算后的结果。
如:
思路:
- 首先需要将中缀表达式转化为后缀表达式
- 然后通过后缀表达式求值
第一步(中缀表达式->后缀表达式)的思路:
定义一个操作符栈stack<char> s,一个队列queue<string>q用来存放后缀表达式,一个map用来存放运算符的优先级
循环读取字符串的每一个字符c:
- 若c为'(':入栈
- 若c为')':出栈,一直出到栈顶为'(',将出栈的运算符push到q中,将'('出栈
- 若c为'+','-','*','/'其中一个,根据优先级,将优先级大于等于c的运算符出栈push到q中,然后将c入栈
- 若c为数字,则定义一个string temp = "";然后循环读取下一个字符,执行temp+=c,直到不是数字和小数点。然后将temp入队
- 执行1-4直到读取了每一个字符,然后将s中剩下的操作符push到q中,q即为所求后缀表达式
第二步(后缀表达式求值):
定义一个queue<string>q2 = q,一个stack<double> sd用来存放操作数
- 这一步很简单,从q中读取string.若第一个字符为数字,则将该string转化为double入栈
- 若第一个字符不是数字,说明是操作符,则分别定义double d1, d2,为sd的头两个操作数。然后执行这个操作符(注意d1, d2的运算顺序),将结果入栈
- 执行1-2直到q为空,此时sd只剩一个最终结果。
代码:
#include<bits/stdc++.h>
#include<queue>
using namespace std;
map<char, int>p; //操作符优先级
stack<char> s; //操作符栈
stack<double> sd; //操作数栈,通过后缀表达式求值时需要
queue<string> q, q2; //后缀表达式队列
//中缀转后缀表达式
void f(string str){
for(int i = 0;i < str.length();i++){
char c = str[i];
string d = "";
if(c == '('){ //左括号入栈
s.push(c);
} else if(c == ')'){ //右括号,出栈到左括号为止,并将操作符输出到后缀表达式
while(!s.empty() && s.top() != '('){
d += s.top();
q.push(d);
s.pop();
}
s.pop(); //弹出左括号
} else if(c == '+' || c == '-' || c == '*' || c == '/'){ //如果是操作符,弹出所有优先级大于等于该运算符的栈顶元素
while(!s.empty() && p[s.top()] >= p[c]){ //然后将该操作符入栈
d += s.top();
q.push(d);
s.pop();
d = "";
}
s.push(c);
} else {
string temp = "";
int j;
for(j = i;j < str.length();j++){
char t = str[j];
if(isdigit(t) || t == '.'){
temp += t;
} else {
break;
}
}
i = j - 1;
q.push(temp);
}
}
while(!s.empty()){
string temp = "";
temp += s.top();
q.push(temp);
s.pop();
}
}
double to(string str){
const char *ss = str.data();
return atof(ss);
}
//后缀表达式求值
void cal(){
while(!q2.empty()){
string str = q2.front();
q2.pop();
char tt = str[0];
if(isdigit(tt)){
double temp = to(str);
sd.push(temp);
}else{
char c = str[0];
double t1 = sd.top(); //第二操作数
sd.pop();
double t2 = sd.top(); //第一操作数
sd.pop();
double num; //结果
switch(c){
case '+':
num = t2 + t1;
break;
case '-':
num = t2 - t1;
break;
case '*':
num = t2 * t1;
break;
case '/':
num = t2 / t1;
break;
}
sd.push(num);
}
}
cout<<sd.top();
}
int main(){
p['+'] = p['-'] = 1;
p['*'] = p['/'] = 2;
string str;
cin>>str;
f(str); //处理字符串
q2 = q;
while(!q.empty()){
cout<<q.front()<<" ";
q.pop();
}
cout<<endl;
cal();
}