1.将中缀表达式转化为后缀表达式
后缀表达式也叫作逆波兰表达式,主要是运用栈的后进先出思想,下面就讲讲我自己的思考,
假设中缀表达式为:2*(2+1)-6(4-2)#,则后缀表达式为:2 2 1 + * 6 4 2 - / -;
首先依次遍历中缀表达式,遇到操作数字符则直接输出(数字字符大小区间在 ‘0’~‘9’),遇到操作符字符则依次入栈,其中操作符入栈条件:
- 若栈中没有元素,即栈空,无条件入栈。
- 若为左括号“( ”,无条件入栈。
- 若为右括号" ) ",则依次输出栈中的运算符,直到遇到左括号“(”为止。
- 若为非括号操作符,则比较此时遍历到的操作符和栈顶元素,并判断元素优先级(优先级和平常运算的先后一样),如果栈顶的元素优先级较高或者相等,则弹出栈顶元素并输出,将遍历到的操作符入栈。若遍历的操作符优先级较高,则直接入栈。
- 遍历到“#”时,结束遍历,判断栈是否为空,若栈不为空,依次输出栈顶元素,直至栈为空。
注意:右括号“)”不进栈,只是为了更好地表达,实际不进栈
也可以参考这篇,比较详细:中缀表达式转换为后缀表达式
附上自己写的代码吧!!
// nibolanbiaodashi.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdlib.h"
typedef char Elemtype;
#define STACKINITSIZE 100
#define STACKINCREMENT 10
typedef struct SQSTACK{
Elemtype *top;
Elemtype *base;
int stacksize;
}Sqstack;
typedef struct{
Elemtype data[STACKINITSIZE];
int length;
}SqList;
void InitList(SqList *L)
{
(*L).length=0;
}
void InitStack(Sqstack *S)
{
(*S).base=(Elemtype *)malloc(STACKINITSIZE * sizeof(Elemtype));
(*S).top=(*S).base;
(*S).stacksize=STACKINITSIZE;
}
void Push(Sqstack *S,Elemtype e)
{
if((*S).top-(*S).base>=(*S).stacksize)
{
(*S).base=(Elemtype *)realloc((*S).base,((*S).stacksize+STACKINITSIZE)*sizeof(Elemtype));
(*S).top=(*S).base+(*S).stacksize;
(*S).stacksize=(*S).stacksize+STACKINCREMENT;
}
*((*S).top)=e;
(*S).top++;
}
void Pop(Sqstack *S,Elemtype *e)
{
if((*S).top == (*S).base)
return;
e=(*S).top;
(*S).top--;
}
void GetPop(Sqstack S,Elemtype *e)
{
if(S.base==S.top)
return;
*e=*(S.top-1);
}
int EmptyStack(Sqstack S)
{
if(S.base == S.top)
return 1;
return 0;
}
int Precede(Elemtype e,Elemtype a)
{
Elemtype book;
if((e == '+'||e == '-') && (a == '+'||a == '-'))
book='=';
if((e == '+'||e == '-') && (a == '*'||a == '/'))
book='<';
if((e == '*'||e == '/') && (a == '+'||a == '-'))
book='>';
if((e == '*'||e == '/') && (a == '*'||a == '/'))
book='=';
if(e=='(')
book='<';
return book;
}
void InversePolandExpression(Sqstack S,Elemtype str[],SqList *L)//逆波兰
{
int i=0,j=0;
Elemtype book;
Elemtype e;
printf("逆波兰表达式:\n");
while(str[i]!='#')
{
if(str[i]>='0' && str[i]<='9')
{
(*L).data[j]=str[i];
(*L).length++;
j++;
printf(" %c ",str[i]);
}
else
{
if(str[i]=='(')
Push(&S,str[i]);
if(str[i]==')')
{
GetPop(S,&e);
while(e!='(')
{
Pop(&S,&e);
(*L).data[j]=e;
j++;
(*L).length++;
printf(" %c ",e);
GetPop(S,&e);
if(e=='(')
Pop(&S,&e);
}
}
if(str[i]=='+' || str[i]=='-' || str[i]=='*' || str[i]=='/')
{
if(EmptyStack(S))
Push(&S,str[i]);
else
{
GetPop(S,&e);
book=Precede(e,str[i]);
switch(book)
{
case '<' :
Push(&S,str[i]);
break;
case '=' :
Pop(&S,&e);
(*L).data[j]=e;
j++;
(*L).length++;
printf("%c",e);
Push(&S,str[i]);
break;
case '>' :
Pop(&S,&e);
(*L).data[j]=e;
j++;
(*L).length++;
printf("%c",e);
Push(&S,str[i]);
break;
}
}
}
}
i++;
}
while(!EmptyStack(S))
{
GetPop(S,&e);
(*L).data[j]=e;
j++;
(*L).length++;
printf(" %c ",e);
Pop(&S,&e);
}
printf("\n");
}
/*void print(SqList *L)
{
int i=0;
while(i<(*L).length)
{
printf("%c",(*L).data[i]);
i++;
}
printf("\n");
}*/
int Calculate(Elemtype a,Elemtype b,Elemtype OPTR)
{
int n;
if(OPTR=='+')
{
n=(a-48)+(b-48);
}
if(OPTR=='-')
{
n=(b-48)-(a-48);
}
if(OPTR=='*')
{
n=(a-48)*(b-48);
}
if(OPTR=='/')
{
n=(b-48)/(a-48);
}
return n;
}
void calvalInverPoland(SqList L)//后缀表达式求值
{
int i=0;
int n;
Elemtype ch;
Elemtype a,b,e;
Sqstack OPND;
InitStack(&OPND);
printf("逆波兰表达式求值 : ");
while(i<L.length)
{
if(L.data[i]>='0' && L.data[i]<='9')
{
Push(&OPND,L.data[i]);
}
else
{
GetPop(OPND,&a);
Pop(&OPND,&a);
GetPop(OPND,&b);
Pop(&OPND,&b);
n=Calculate(a,b,L.data[i]);
ch=n+48;
Push(&OPND,ch);
}
i++;
}
GetPop(OPND,&e);
printf("%c",e);
printf("\n");
}
int main(int argc, char* argv[])
{
Sqstack S;
SqList L;
char str[20]="2*(2+1)-6/(4-2)#";
printf("Please end with '#'\n");
//scanf("%s",str);
InitList(&L);
InitStack(&S);
InversePolandExpression(S,str,&L);
calvalInverPoland(L);
return 0;
}
后面因为临时加入了后缀表达式求值,就用了一个线性表来储存后缀表达式。