所谓中缀表达式与后缀表达式的定义,即是看运算符在操作数的位置如何
中缀表达式即作符是以中缀形式处于操作数的中间(例:3 + 4)
后缀表达式(也叫逆波兰表达式)则为3 4 +
以下摘抄百度百科:
一个表达式E的后缀形式可以如下定义:
(1)如果E是一个变量或常量,则E的后缀式是E本身。
(2)如果E是E1 op E2形式的表达式,这里op是任何二元操作符,则E的后缀式为E1'E2' op,这里E1'和E2'分别为E1和E2的后缀式。
(3)如果E是(E1)形式的表达式,则E1的后缀式就是E的后缀式。
如:我们平时写a+b,这是中缀表达式,写成后缀表达式就是:ab+
(a+b)*c-(a+b)/e的后缀表达式为:
(a+b)*c-(a+b)/e
→((a+b)*c)((a+b)/e)-
→((a+b)c*)((a+b)e/)-
→(ab+c*)(ab+e/)-
→ab+c*ab+e/-
由这个例子可以看出,中缀表达式转化为后缀表达式的实质就是,将每个 “部分式” 的算术符号移到式子后面
还是以百度的例子为例:
第一步,把整个式子看作一个部分,左边的数是(a+b)*c,右边的是(a+b)/e,将➖号移到式子最后
第二步,再把第一步式子的两个“数”做相似处理,例如(a+b)*c,看成(a+b) 和c,将✖号移到式子最后
第三步。。。。。。
那么我们如何使用栈来实现转换呢?
读入中缀表达式infix[i];
1.遇到数字 0-9 ,则将其直接送进后缀表达式postfix[]数组
2.如果遇到左括号 '(' ,入栈(起到了限制范围的作用)
3.如果遇到右括号')' ,弹出上一个左括号'('之前的所有运算符并送入postfix ;注意左括号'('只弹出不赋值
4.如果遇到运算符(+ - * /),就将栈中所有优先级大于等于它的运算符出栈,直到栈空,再把该运算符入栈
后缀表达式求值:
1.遇到数字0-9,直接进栈
2.遇到运算符(+ - * /),将栈中头两个数弹出来进行运算,并将结果入栈
附代码:
#include
#include
#include
typedef struct _nodechar
{
char data;
struct _nodechar *next;
} nodechar;
typedef struct _stackchar
{
int size;
nodechar *top;
} stackchar;
typedef struct _nodeint
{
int data;
struct _nodeint *next;
} nodeint;
typedef struct _stackint
{
int size;
nodeint *top;
} stackint;
int getPriority(char opt)
{
if(opt == '+' || opt =='-')
return 1;
if(opt == '*' || opt == '/')
return 2;
return 0;
}
int calucalte(int opt1, char opt, int opt2)
{
switch(opt)
{
case '+':
return opt1 + opt2;
break;
case '-':
return opt1 - opt2;
break;
case '*':
return opt1 * opt2;
break;
case '/':
return opt1 / opt2;
break;
}
return 0;
}
stackchar *createStackchar(void)
{
stackchar* p = (stackchar*)malloc(sizeof(stackchar));
p->size = 0;
p->top = NULL;
return p;
}
void pushchar(stackchar* pStack, char x)
{
nodechar *t = (nodechar*)malloc(sizeof(nodechar));
t->data = x;
t->next = pStack->top;
pStack->top = t;
pStack->size++;
}
void popchar(stackchar* pStack)
{
nodechar *t = pStack->top;
pStack->top = t->next;
free(t);
pStack->size--;
}
char topchar(stackchar* pStack)
{
return pStack->top->data;
}
bool emptychar(stackchar* pStack)
{
return pStack->top == NULL;
}
void destroyStackchar(stackchar* pStack)
{
while (!emptychar(pStack))
{
popchar(pStack);
}
free(pStack);
}
stackint *createStackint(void)
{
stackint* p = (stackint*)malloc(sizeof(stackint));
p->size = 0;
p->top = NULL;
return p;
}
void pushint(stackint* pStack, int x)
{
nodeint *t = (nodeint*)malloc(sizeof(nodeint));
t->data = x;
t->next = pStack->top;
pStack->top = t;
pStack->size++;
}
void popint(stackint* pStack)
{
nodeint *t = pStack->top;
pStack->top = t->next;
free(t);
pStack->size--;
}
int topint(stackint* pStack)
{
return pStack->top->data;
}
bool emptyint(stackint* pStack)
{
return pStack->top == NULL;
}
void destroyStackint(stackint* pStack)
{
while (!emptyint(pStack))
{
popint(pStack);
}
free(pStack);
}
int main(void)
{
//转换部分
int n;
scanf("%d", &n);
while(n--)
{
char infix[21], postfix[21] = "\0";
int index = 0;
scanf("%s", infix);
stackchar *pStackchar = createStackchar();
for(int i = 0; infix[i] != '\0'; i++)
{
if(infix[i] >= '0' && infix[i] <= '9')
{
postfix[index++] = infix[i];
}
else if(infix[i] == '(')
{
pushchar(pStackchar, infix[i]);
}
else if(infix[i] == ')')
{
char c = topchar(pStackchar);
popchar(pStackchar);
while(c != '(')
{
postfix[index++] = c;
c = topchar(pStackchar);
popchar(pStackchar);
}
}
else//算术符号
{
if(emptychar(pStackchar) || getPriority(infix[i]) > getPriority(topchar(pStackchar)))
{
pushchar(pStackchar, infix[i]);
}
else
{
while(!emptychar(pStackchar) && getPriority(infix[i]) <= getPriority(topchar(pStackchar)))
{
char c = topchar(pStackchar);
popchar(pStackchar);
postfix[index++] = c;
}
pushchar(pStackchar, infix[i]);
}
}
}
while(!emptychar(pStackchar))
{
char c = topchar(pStackchar);
popchar(pStackchar);
postfix[index++] = c;
}
printf("%s", postfix);
destroyStackchar(pStackchar);
//算值部分,优先级高的数在栈顶,优先级高的计算符号在符号序列最左边
stackint *pStackint = createStackint();
for(int i = 0; postfix[i] != '\0'; i++)
{
if(postfix[i] >= '0' && postfix[i] <= '9')
{
int m = postfix[i] - '0';
pushint(pStackint, m);
}
else
{
char opt = postfix[i];
int opt2, opt1;
opt2 = topint(pStackint);
popint(pStackint);
opt1 = topint(pStackint);
popint(pStackint);
pushint(pStackint, calucalte(opt1, opt, opt2));//先弹出的数要放在操作符的右边
}
}
int ans = topint(pStackint);
printf(" %d\n", ans);
popint(pStackint);
destroyStackint(pStackint);
}
return 0;
}