算法步骤:
初始化一个栈,用于保存暂时还不能确定运算顺序的运算符
从左到右处理各个元素,直到末尾,可能遇到三种情况:
- 遇到操作数,直接加入后缀表达式
- 遇到界限符,遇到左括号则直接入栈,遇到右括号则依次弹出栈内运算符并加入后缀表达式,直到弹出左括号为止。注意左括号不加入后缀表达式
- 遇到运算符,依次弹出栈中优先级高于或等于当前运算符的所有运算符,并加入后缀表达式,若碰到了左括号或栈空则停止,之后再把当前运算符入栈
编写程序过程中,扫描到运算符的时候,判断栈中优先级高于当前运算符的情况,注意用GetTop来代替直接Pop, 先判断优先级是否高于当前运算符,为真,则Pop. 并注意continue和break的正确使用
//中缀表达式转后缀表达式
/* 算法步骤:
初始化一个栈,用于保存暂时还不能确定运算顺序的运算符
从左到右处理各个元素,直到末尾,可能遇到三种情况:
4. 遇到操作数,直接加入后缀表达式
5. 遇到界限符,遇到左括号则直接入栈,遇到右括号则依次弹出栈内运算符并加入
后缀表达式,直到弹出左括号为止。注意左括号不加入后缀表达式
3.遇到运算符,依次弹出栈中优先级高于或等于当前运算符的所有运算符,并加入
后缀表达式,若碰到了左括号或栈空则停止,之后再把当前运算符入栈
*/
//栈的顺序存储结构,用静态数组实现
#include<stdio.h>
#include<string.h>
#define MaxSize 40//定义栈中元素的最大个数
#define ElemType char
typedef struct{
ElemType data[MaxSize];//存放栈中的元素
int top;//栈顶指针
}SqStack;//顺序栈
void InitStack(SqStack &s){
s.top=-1;//初始化栈顶指针
}
bool StackEmpty(SqStack s){
return s.top==-1;
}
bool Push(SqStack &s,ElemType x){
if(s.top == MaxSize-1){
printf("overflow\n");
return false;
}
s.data[++s.top]=x;
return true;
}
bool Pop(SqStack &s,ElemType &x){
//先判断栈是否为空
if(!StackEmpty(s)){
x = s.data[s.top--];
return true;
}
}
bool GetTop(SqStack s,ElemType &x){
//先判断栈是否为空
if(!StackEmpty(s)){
x = s.data[s.top];
return true;
}
}
bool DestroyStack(SqStack &s){
s.top=-1;
}
bool PrintStack(SqStack s){
int p=s.top;
if(p==-1){
printf("\n栈空\n");
return false;
}
printf("Stack is :");
while(p!=-1){
printf("%d ",s.data[p--]);
}
printf("\n");
}
bool isDigit(char c){
return (c>='0'&&c<='9');
}
bool isAlpha(char c){
return ((c>='a'&& c<='z')||(c>='A'&&c<='Z'));
}
//输入字符串,和其长度
bool midToSuffix(char str[],int len){
SqStack s;
InitStack(s);
char ch;
ElemType topElem='\0';
for(int i=0;i<len;i++){
ch=str[i];
if(isDigit(ch)){
printf("%c",ch);
if(!isDigit(str[i+1])){//不是数字的话则输出空格
printf(" ");
}
continue;
}
if(isAlpha(ch)){//如果是字母的话
printf("%c ",ch);
continue;
}
switch(ch){
//遇到左括号则直接入栈
case '(':
Push(s,ch);break;
case '[':
Push(s,ch);break;
case '{':
Push(s,ch);break;
//遇到右括号,则依次弹出栈内运算符并加入后缀表达式;
case ')':
Pop(s,topElem);
while(topElem!='('){
printf("%c ",topElem);
Pop(s,topElem);
};
break;
case ']':
Pop(s,topElem);
while(topElem!='['){
Pop(s,topElem);
printf("%c ",topElem);
};
break;
case '}':
Pop(s,topElem);
while(topElem!='{'){
printf("%c ",topElem);
Pop(s,topElem);
};
break;
case '+':
GetTop(s,topElem);//获取栈顶元素,这里用GetTop比直接Pop省事甚多
while(!StackEmpty(s) && topElem != '('&& topElem != '['&& topElem != '{'){//栈空
printf("%c ",topElem);
Pop(s,topElem);//先打印后弹出
GetTop(s,topElem);//@@@
}
Push(s,'+');
break;
case '-':
GetTop(s,topElem);//弹出栈顶元素
//栈中只能是左括号or运算符
//若栈非空,且栈顶元素不是左括号, 对于+-,则无条件pop
while(!StackEmpty(s) && topElem != '('&& topElem != '['&& topElem != '{'){
printf("%c ",topElem);
Pop(s,topElem);
GetTop(s,topElem);//@@@
//flag++;
}
//当前运算符号入栈
Push(s,'-');
break;
case '*':
GetTop(s,topElem);//弹出栈顶元素
//若栈非空,且栈顶元素不是左括号, 对于*,则只有* / 优先级>= *
while(!StackEmpty(s) && topElem != '('&& topElem != '['&& topElem != '{'){//
if(topElem=='*'||topElem=='/'){//优先级>='*'的出栈
printf("%c ",topElem);
Pop(s,topElem);
GetTop(s,topElem);//@@@查看下一个栈顶元素是否需要弹出
continue;//@@@
}
break;//若优先级< '*',则直接跳出while
}
Push(s,'*');
break;
case '/':
GetTop(s,topElem);//弹出栈顶元素
//若栈非空,且栈顶元素不是左括号, 对于*,则只有* / 优先级>= /
while(!StackEmpty(s) && topElem != '('&& topElem != '['&& topElem != '{'){
if(topElem=='*'||topElem=='/'){
printf("%c ",topElem);
Pop(s,topElem);
GetTop(s,topElem);//@@@
continue;
}
break;//若优先级< '/',则直接跳出while
}
//将此运算符入栈
Push(s,'/');
break;
}
}
while(!StackEmpty(s)){
Pop(s,topElem);
printf("%c ",topElem);
}
return true;
}
int main(){
char str0[35]="((15/(7-(1+1)))*3)-(4+(4+8))";
char str1[35]="A+B-c*D/e+f";
char str2[35]="A+B*(c-D)-E/F";
printf("中缀表达式: ");
for(int i=0;i<strlen(str0);i++){
printf("%c",str0[i]);
}
printf("\n后缀表达式:");
midToSuffix(str0, strlen(str0));
printf("\n");
printf("\n*****************************\n\n");
printf("中缀表达式: ");
for(int i=0;i<strlen(str1);i++){
printf("%c",str1[i]);
}
printf("\n后缀表达式:");
midToSuffix(str1, strlen(str1));
printf("\n");
printf("\n*****************************\n\n");
printf("中缀表达式: ");
for(int i=0;i<strlen(str2);i++){
printf("%c",str2[i]);
}
printf("\n后缀表达式:");
midToSuffix(str2, strlen(str2));
printf("\n");
return 0;
}