使用顺序栈将中缀表达式转换成逆波兰表达式
基本思路:
按序判断表达式,如果是数字输出并加空格区分;如果是操作符先判断栈是不是空的,如果栈是空的先判断待入栈的操作符是不是左括号,是左括号令计算左括号个数的标志变量自加,但不管是不是都将这个操作符入栈;如果栈非空则先比较待入栈操作符与栈顶操作符优先级,如果待入栈的操作符优先级不比栈顶操作符的优先级低则先判断待入栈操作符是不是右括号,若不是右括号则判断这个操作符是不是左括号,是左括号则令计算左括号的标志变量自加,但不管是不是都将这个操作符入栈;若待入栈的操作符是右括号则先判断栈内有没有左括号,如果没有左括号则提醒输入错误,反之将与之匹配的左括号之间的操作符全部弹出到后缀表达式中(不包括括号)然后令计算左括号数量的标志变量自减;;如果待入栈的操作符优先级比栈顶优先级低,先判断栈中有没有左括号,如果没有左括号则弹出栈内所有操作符然后将这个操作符入栈,如果栈内有左括号则将左括号之后的所有操作符弹出,然后将这个操作符入栈。结束后弹出栈内所有操作符。
栈内非空的操作图示:
整体代码:
#include<iostream>
#include<string>
using namespace std;
const int stacksize=100;
typedef struct Stack{
string fix[stacksize];
int top=-1;
}Stack;
void Input(string&); //输入中缀表达式
int Isempty(Stack*); //判栈空
int Isfull(Stack*); //判栈满
int Push(Stack*,string); //入栈
string Pop(Stack*); //出栈
int Compare(string); //判断操作符优先级
void Change(string&); //将中缀表达式转换成后缀表达式
int main(void){
string fix;
Input(fix);
Change(fix);
cout<<fix<<endl;
return 0;
}
void Input(string& fix){
cout<<"Please input a nifix expression."<<endl;
getline(cin,fix);
}
int Isempty(Stack* p){
return p->top==-1;
}
int Isfull(Stack* p){
return p->top==stacksize-1;
}
int Push(Stack* p,string temp){
if(Isfull(p)){
cout<<"The stack is full."<<endl;
return 0;
}
p->fix[++p->top]=temp;
return 1;
}
string Pop(Stack* p){
if(Isempty(p)){
cout<<"The stack is empty."<<endl;
return 0;
}
return p->fix[p->top--];
}
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;
Stack 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.fix[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.fix[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.fix[p.top][0]!='(') postfix+=Pop(&p); //弹出左括号之后的所有操作符
Push(&p,temp);
}
}
}
}
}
while(!Isempty(&p)) postfix+=Pop(&p);
fix=postfix;
}
一些小心得:
1、例如,string fix=“abcdefg”,fix[3]这是字符类型不是string类型,string类是个容器
2、可以用_str()函数将string变量转换成char*类型