//逆波兰表达式思路:构建两个栈,一个为数值栈,一个为运算符栈。
//遇到栈内的运算符比字符串中的运算符低,就压栈,否则,出栈,并且数值栈元素出栈,并做计算
//然后将计算结果压栈
//重复此过程,最后将字符栈中字符出空,数值栈中元素压栈,输出栈底元素。
#include<bits/stdc++.h>
#define N 81
using namespace std;
int Level(char op)
{
int k;
switch(op){//返回优先级
case '*':
case '/':k=2;
break;
case '+':
case '-':k=1;
break;
case '(':k=0;
break;
case '@':k=-1;
}
return k;
}
int Cal(int x1,int x2,char op)//计算函数
{
switch(op){
case '*':return x1*x2;//接收的字符op为‘*’
case '/':return x2/x1;
case '+':return x1+x2;
case '-':return x2-x1;
}
}
void Process(int *vals,char *ops,int *Pvaltop,int *Poptop)//出栈-出栈-计算-入栈函数
{
int x1,x2;
char op;
x1=vals[(*Pvaltop)--];//出栈
x2=vals[(*Pvaltop)--];//出栈
op=ops[(*Poptop)--];//出栈
vals[++(*Pvaltop)]=Cal(x1,x2,op);//计算并压栈
}
int Compute(char s[])
{
int *vals;
char *ops;
int val,Valtop=-1,Optop=0,i;//val用于存储最后的计算结果,Valtop为数字栈栈顶指针,Optop为字符栈栈顶指针,其栈底存放‘@’用作标记
//建栈
vals=(int *)malloc(N*sizeof(int));
ops=(char *)malloc(N*sizeof(char));
ops[Optop]='@';//存储在栈底的标记字符
//遍历中缀表达式
i=0;
int y;
while(s[i]){
if(s[i]>='0'&&s[i]<='9'){//每一次第一个字符是数字字符
y=0;
while(s[i]>='0'&&s[i]<='9'){//从第一个数字字符到出现运算符的这段,计算并压入栈中
y=y*10+s[i]-'0';
i++;//i控制向后遍历
}
vals[++Valtop]=y;//将计算出的结果压栈
i--;//为了和后面统一,i退回到运算符前面的一个数字字符处
}
else if(s[i]=='('){//遇到左括号就压栈
ops[++Optop]=s[i];
}
else if(s[i]==')'){//遇到右括号就出栈到第一个左括号处
while(ops[Optop]!='('){
Process(vals,ops,&Valtop,&Optop);//出栈-出栈-计算-入栈 函数 (将出栈元素计算)
}
Optop--;//将左括号也出栈
}
else if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/'){//运算符就要比较优先级,a[i]和栈顶元素比较高者直接入栈,否则出栈
while(Level(s[i])<=Level(ops[Optop])){//s[i]优先级比栈顶元素优先级低,出栈计算
Process(vals,ops,&Valtop,&Optop);
}
ops[++Optop]=s[i];//s[i]优先级比栈顶元素优先级高,直接压栈
}
i++;//i+1,继续遍历数组
}
while(Optop){//将字符栈清空,并结合数字栈进行计算
Process(vals,ops,&Valtop,&Optop);
}
val=vals[Valtop];//数字栈栈底存放的即为所求
free(vals);//释放malloc分配的动态单元
free(ops);
return val;
}
int main()
{
char s[N];
int val;
cout<<"请输入一个中缀表达式:";
gets(s);
val=Compute(s);
cout<<"请输出中缀表达式及计算结果:";
cout<<s<<"="<<val;
return 0;
}