中缀表达式:操作符在操作数中间;例如:1+2*3-4/5
后缀表达式:操作符在操作数后面;例如:1 2 3 * 4 5 / - +
后缀表达式的优点:按顺序读取,碰到操作数进栈;碰到操作符就把前面两个操作数弹出来计算,计算结果进栈;
从中缀表达式到后缀表达式的变换:
栈st1 和栈st2 ,st1 放操作符,st2 放操作数;遍历表达式字符串:
遇到数字:压入st2;
遇到操作符:压入st1中,但是压入之前检查,如果当前栈顶不为空且该操作符优先级高于待入栈的操作符(操作符的优先级可以用map定义),那么就把当前栈顶的操作符出栈压入st2中,直到操作符优先级不高于当前待入栈的操作符。
最后将st1剩余元素依次弹出压入st2中,st2逆序输出即为后缀表达式;
不足:还未实现带小数的操作数识别以及带括号的表达式;
暂时只支持+ - * / 四种表达式。
【更新20190802】传送门
Code:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<string>
#include<vector>
#include<map>
#include<stack>
using namespace std;
struct node{
double num;
char op;
bool flag;//true-操作数 false-操作符
};
string str;
stack<node> st1;
stack<node> st2;
stack<node> st3;//后缀表达式
map<char,int> op;
double calop(double t1,double t2,char op){
if(op=='+') return t1+t2;
if(op=='-') return t1-t2;
if(op=='*') return t1*t2;
if(op=='/') return t1/t2;
}
void cal(){
while(!st2.empty()){
st3.push(st2.top());
st2.pop();
}
node temp;
double sum;
double temp1,temp2;
char op;
while(!st3.empty()){
if(st3.top().flag){
st2.push(st3.top());
st3.pop();
}else{
temp2=st2.top().num;
st2.pop();
temp1=st2.top().num;
st2.pop();
op=st3.top().op;
st3.pop();
sum=calop(temp1,temp2,op);
temp.flag=true;
temp.num=sum;
st2.push(temp);
}
}
printf("%.2f",st2.top().num);
}
void change(string str){
int len=str.length();
for(int i=0;i<len;i++){
node temp;
double num=0;
if(str[i]<='9'&&str[i]>='0'){
//是数字
while(i<len&&str[i]<='9'&&str[i]>='0'){
num=10*num+str[i]-'0';
i++;
}
temp.num=num;
temp.flag=true;
st2.push(temp);
i--;
}
else{
//是字符
temp.op=str[i];
temp.flag=false;
while(!st1.empty()&&op[str[i]]<op[st1.top().op]){
st2.push(st1.top());
st1.pop();
}
st1.push(temp);
}
}
while(!st1.empty()){
st2.push(st1.top());
st1.pop();
}
}
int main(){
// freopen("1.txt","r",stdin);
op['+']=op['-']=1;
op['*']=op['/']=2;
cin>>str;
change(str);
cal();
// while(!st2.empty()){
// if(st2.top().flag){
// printf("%.0f ",st2.top().num);
// st2.pop();
// }else{
// printf("%c ",st2.top().op);
// st2.pop();
// }
// }
}