中缀表达式:便于人看;
前缀表达式:又称波兰式,运算符在前边,运算数在后边;
后缀表达式:又称逆波兰式,运算数在前边,运算符在后边;
一、中缀表达式转换前缀表达式:
1、初始化两个栈,s1(存放数字),s2(存放运算符);
2、表达式右边开始,遍历表达式;
3、遇到数字放入s1中,遇到运算符放入s2中,放入法则如下:
(1)如果s2为空,或者“)”,直接放进去;
(2)当前运算符和栈顶运算符比较,当前运算符优先级大于等于栈顶运算符优先级,直接放进去;
(3)如果当前运算符小于栈顶运算符优先级,栈顶运算符取出来放入s1中,重复(2)、(3);
4、s1栈中的元素依次出栈,入s2栈;
5、s2栈中元素依次出栈重新组成表达式即为前缀表达式。
二、中缀表达式转换后缀表达式
1、初始化两个栈,s1(存放数字),s2(存放运算符);
2、从表达式左边开始遍历,数字放入s1中,运算符放入s2中;
3、运算符放入s2中的规则:
(1)如果s2空或者栈顶是”(”,直接放进去;
(2)如果当前运算符优先级大于栈顶元素优先级,直接放入;
(3)如果当前运算符优先级小于等于栈顶元素优先级,栈顶元素出栈,并且入s1栈;
(4)遇到”)”,运算符出栈,入s1栈,直到遇到”(”, ”( )”要丢掉;
4、s1中的元素依次出栈,入s2栈;
5、s2栈中元素出栈重新组成表达式即为后缀表达式。
以上算法比较试用笔试的时候计算选择或者填空题,用代码实现的时候我选择了用一个栈和一个字符串去实现。比如编程实现将中缀表达式转成前缀表达式,如a+b*(c-d)-e/f转成-+a*b-cd/ef。首先我们要考虑运算符的优先级问题,除去括号的优先级,就是先乘除后加减,我是用的定义宏来处理这个问题,当然还有更好的处理方法大家可以给我意见,定义宏比较通俗易懂所以我就暂且这样使用了。然后就开始入栈出栈了,规则是遇到字符就放到定义好的字符串中,遇到运算符就入栈。因为是中缀转前缀,所以要从右往左遍历表达式。运算符入栈的规则是,栈空时运算符直接入栈;栈不空时,当“+”或“-”入栈要与栈顶元素的优先级比较,若小于栈顶元素,需要将比即将要入栈元素大的元素都依次出栈,放入字符串中,然后将“+”或“-”入栈,反之直接入栈(注意:将优先级大的元素出栈后切勿忘了将“+”或“-”入栈);当遇到“*”或“/”入栈就直接入栈;还如注意的就是括号,如遇到“)”直接入栈,如遇到“(”须将元素依次出栈放入字符串中,直到遇到“)”即停止出栈(因为是从右至左遍历所以先遇到右括号)。遍历完字符串后接着判断栈是否为空,若不为空则将栈内元素依次出栈放入字符串中,最后逆置字符串即得到前缀表达式。
(代码实现较长,有较多重复代码,请大家见谅)
实现代码如下:
#define RIGHT 0
#define ADD 1
#define SUB 2
#define MULTI 3
#define DIVIDE 4
{
assert(str!=NULL);
char tmp;
{
tmp=str[i];
str[i]=str[j];
str[j]=tmp;
}
return str;
}
char* Infix_Turn_Suffix(char *str)
{
SNode p;
InitStack(&p);
char *arr=(char*)malloc(sizeof(char)*strlen(str));
int top=-1;
int tmp=-1;
int rval;
int j=0;
{
GetTop(&p,&top);
switch(str[i])
{
case '+':
while(!IsEmpty(&p))
{
GetTop(&p,&top);
if(top>SUB)
{
Pop(&p,&rval);
if(rval==MULTI)
{
arr[j]='*';
j++;
}
if(rval==DIVIDE)
{
arr[j]='/';
j++;
}
}
else break;
}
break;
case '-':
while(!IsEmpty(&p))
{
GetTop(&p,&top);
if(top>SUB)
{
Pop(&p,&rval);
if(rval==MULTI)
{
arr[j]='*';
j++;
}
if(rval==DIVIDE)
{
arr[j]='/';
j++;
}
}
else break;
}
Push(&p,SUB);
break;
case '*':
Push(&p,MULTI);
break;
case '/':
Push(&p,DIVIDE);
break;
case '(':
while(rval!=LEFT)
{
Pop(&p,&rval);
if(rval==ADD)
{
arr[j]='+';
j++;
}
if(rval==SUB)
{
arr[j]='-';
j++;
}
if(rval==MULTI)
{
arr[j]='*';
j++;
}
if(rval==DIVIDE)
{
arr[j]='/';
j++;
}
}
break;
case ')':
Push(&p,LEFT);
break;
default:
arr[j]=str[i];
j++;
break;
}
}
{
arr[j]='\0';
}
else
{
while(!IsEmpty(&p))
{
Pop(&p,&rval);
if(rval==ADD)
{
arr[j]='+';
j++;
}
if(rval==SUB)
{
arr[j]='-';
j++;
}
if(rval==MULTI)
{
arr[j]='*';
j++;
}
if(rval==DIVIDE)
{
arr[j]='/';
j++;
}
}
arr[j]='\0';
}
Reverse(arr);
return arr;
}