使用顺序栈将输入的中缀表达式变成逆波兰表达式并计算结果
主要分成两部分,一是将中缀表达式变成逆波兰表达式,二是计算逆波兰表达式,在编写过程中我使用了模板函数和函数重载。基本思路和我之前的用顺序栈计算逆波兰表达式和用顺序栈将中缀表达式转换成逆波兰表达式相同。
函数代码:
#include<iostream>
#include<string>
const int stacksize=100;
using namespace std;
typedef struct Stack{
double a[stacksize]; //数据域
int top=-1; //指示栈顶位置
}Stack;
typedef struct Stack2{
string a[stacksize];
int top=-1;
}Stack2;
template<typename T>int Isempty(T*); //判栈空
template<typename T>int Isfull(T*); //判栈满
template<typename T,typename N>
int Push(T*,N); //进栈
string Pop(Stack2*); //出栈
double Pop(Stack*); //退栈
void Input(string&); //输入中缀表达式
int Compare(string); //判断操作符优先级
void Change(string&); //将中缀表达式转换成后缀表达式
double Calculate(string); //计算后缀表达式
int main(void){
string fix;
double sum;
Input(fix);
Change(fix);
cout<<"该中缀表达式变成的后缀表达式为:"<<fix<<endl;
sum=Calculate(fix);
cout<<sum;
return 0;
}
template<typename T>
int Isempty(T*p){
return p->top==-1;
}
template<typename T>
int Isfull(T*p){
return p->top==stacksize-1;
}
template<typename T,typename N>
int Push(T*p,N x){
if(Isfull(p)){
cout<<"The stack is full"<<endl;
return 0;
}else{
p->a[++p->top]=x; //data中p->top自加后对应的单元存入x
}
return 1; //函数正常调用
}
string Pop(Stack2* p){
if(Isempty(p)){
cout<<"The stack is empty."<<endl;
return 0;
}
return p->a[p->top--];
}
double Pop(Stack*p){
if(Isempty(p)){
cout<<"The stack is empty"<<endl;
return 0;
}else{
return p->a[p->top--]; //返回a[p->top]然后p->top--
}
}
void Input(string& fix){
cout<<"请输入一个中缀表达式"<<endl;
getline(cin,fix);
}
int Compare(char op){ //判断操作符的优先级
int grade=0;
if(op=='+'||op=='-') grade=1;
else if(op=='*'||op=='/') grade=2;
else if(op=='('||op==')') grade=3;
return grade;
}
void Change(string& fix){
string postfix;
Stack2 p;
int i,flag=0,rank1,rank2; //flag用来标志栈中左括号的数量,
//rank1,rank2用来比较操作符优先级,优先级高的数字大
for(i=0;i<fix.size();i++){
if(isdigit(fix[i])||fix[i]=='.'){
postfix+=fix[i];
if(!isdigit(fix[i+1])&&fix[i+1]!='.')
postfix+=' '; //如果后面是操作符则加空格区分数字
}else{ //如果是操作符的话
string temp;
temp=fix[i];
if(Isempty(&p)){ //栈空的话
if(fix[i]=='(') flag++;
Push(&p,temp);
}else{ //栈内非空的话
rank1=Compare(p.a[p.top][0]);
rank2=Compare(fix[i]);
if(rank1<=rank2){ //待入栈的操作符优先级不比栈顶操作符优先级低
if(fix[i]!=')'){ //如果不是右括号
if(fix[i]=='(')flag++; //如果是左括号flag自加
Push(&p,temp);
}else{ //待入栈的操作符是右括号
if(flag==0){ //栈中没有左括号
cout<<"输入错误"<<endl;
return ; //跳出多重循环
}else{ //栈中有左括号
while(p.a[p.top][0]!='(') postfix+=Pop(&p);
//将与这个右括号匹配的左括号之间的操作符全部弹出
Pop(&p); //将与之匹配的左括号也弹出但不计入表达式
flag--; //左括号的数量减一
}
}
}else{ //待入栈的操作符优先级低
if(flag==0){ //栈中没有左括号
while(!Isempty(&p)) postfix+=Pop(&p); //弹出栈中所有的操作符
Push(&p,temp);
}else{ //栈中有左括号
while(p.a[p.top][0]!='(') postfix+=Pop(&p); //弹出左括号之后的所有操作符
Push(&p,temp);
}
}
}
}
}
while(!Isempty(&p)) postfix+=Pop(&p);
fix=postfix;
}
double Calculate(string postfix){
string temp;
Stack p;
int i;
double temp1=0,temp2=0,temp3=0,sum;
for(i=0;i<postfix.size();i++){
if(isdigit(postfix[i])||postfix[i]=='.'){
temp+=postfix[i];
}else if(postfix[i]==' '){
if(Isfull(&p)){
cout<<"The stack is full"<<endl;
break;
}else{
temp3=stod(temp);
Push(&p,temp3);
temp.erase(0);
}
}else if(postfix[i]=='+'){
temp1=Pop(&p);
temp2=Pop(&p);
sum=temp1+temp2;
Push(&p,sum);
}else if(postfix[i]=='-'){
temp1=Pop(&p);
temp2=Pop(&p);
sum=temp2-temp1;
Push(&p,sum);
}else if(postfix[i]=='*'){
temp1=Pop(&p);
temp2=Pop(&p);
sum=temp1*temp2;
Push(&p,sum);
}else if(postfix[i]=='/'){
temp1=Pop(&p);
temp2=Pop(&p);
sum=temp2/temp1;
Push(&p,sum);
}
}
sum=Pop(&p);
return sum;
}