中缀双目表达式叫做波兰式,后缀双目表达式叫做逆波兰式。
波兰式 逆波兰式
2+3 2 3 +
2+3*5 2 3 5 * +
2*3+5 2 3 * 5 +
2+3*5-6 2 3 5 * + 6 -
2*(3+5) 2 3 5 + *
逆波兰式的作用:计算机在计算一个表达式的时候就没有了优先级的概念,计算的过程简化为从左往右依次从逆波兰式中读取,读取到一个运算符则从其前面取出两个数字做这个运算符的运算,运算结果放置到当前位置,然后在从左至右开始第二次运算,直到算出结果。
比如2+3*5-6-->读取到第一个*则取出3和5做3*5=15,并将15放置到2后面,现在逆波兰式变为2 15 + 6 -,下一次读取到+取出2和15做2+15=17,并将17存放到6前面,逆波兰式又变为17 6 -,读取到-,则取出17和6做减法17-6=11,并将其放置到以前的序列中,计算结束。
给定一个波兰式,将逆波兰式(各个符号之间用空格隔开)输出,假设波兰式在数组a中,逆波兰式最后在数组b中。
思路:从逆波兰式和波兰式对比来看,数字的相对位置总是一致的,然而运算符的位置却不是一致的。运算符的位置满足碰到高优先级的入栈(栈是另外新建的一个数据结构,不是a也不是b),碰到低优先级的出栈(出栈后就放到b中)。比如读取2+3*5这个波兰式,读取到2直接存放如b中,然后读取+,这个先放入栈中,然后读取3又放入b中,接着读取到*,*的优先级比+高,所以*又在+之后入栈,最后读取5,直接存放如b中,表达式读取完毕,需要将栈中的所有运算符出栈到b中,就得到了:2 3 5 * +的顺序。
要完成这个功能,需要一个栈,而且栈的第一个单元必须放置一个默认的优先级最低的运算符,以保证第一个运算符能够入栈。
关于括号的处理:左括号if语句直接入栈,括号后的表达式按上面的顺序依次入栈或者出栈;碰到右括号则从栈中出栈直到碰到第一个左括号,将左括号从栈中取出这一级括号则处理完毕。
#include
#include
typedef struct st
{
int maxsize;
int top;
int *pstack;
}stack;
void create_stack(stack *s, int ms);
void push(stack *s, int x);
int pop(stack *s);
void clear_stack(stack *s);
char read_stack(stack *s);
int priority(char ch);
void transform(char a[], char b[]);
int main()
{
char a[80], b[200];
printf("Please input expression:");
gets(a);
transform(a, b);
puts(b);
return 0;
}
void create_stack(stack *s, int ms)
{
s->maxsize = ms;
s->top = -1;
s->pstack = (int *)malloc(ms*sizeof(int));
s->pstack[++s->top] = '@'; //这里@被假定为优先级最低的运算符
}
void push(stack *s, int x)
{
if(s->top < s->maxsize-1)
s->pstack[++s->top] = x;
}
int pop(stack *s)
{
if(s->top != -1)
return s->pstack[s->top--];
}
char read_stack(stack *s)
{
return (s->pstack[s->top]);
}
int priority(char ch)
{
int flag = 0;
switch(ch)
{
case '+':
case '-':
flag = 1;
break;
case '*':
case '/':
flag = 2;
break;
default:
flag = 0; //@的优先级设置为最低:0
break;
}
return flag;
}
void transform(char a[], char b[])
{
stack s;
int i = 0, j = 0;
create_stack(&s, 20);
while(a[i])
{
if(a[i] >= '0' && a[i] <= '9')
{
b[j++] = a[i];
}
else if(a[i] == '(')
push(&s, a[i]);
else if(a[i] == ')')
{
b[j++] = ' ';
while(read_stack(&s) != '(')
{
b[j++] = pop(&s);
b[j++] = ' ';
}
pop(&s); //出栈'('
}
else
{
b[j++] = ' ';
while(priority(a[i]) <= priority(read_stack(&s)))
{
b[j++] = pop(&s);
b[j++] = ' ';
}
push(&s, a[i]);
}
i ++;
}
while(s.top != 0) //如果判断a[]结束栈中还有运算符则出栈到b[]中
{
b[j++] = ' ';
b[j++] = pop(&s);
}
b[j++] = '\0'; //将b转换为字符换
}
void clear_stack(stack *s)
{
s->maxsize = 0;
s->top = -1;
free(s->pstack);
s->pstack = 0;
}
程序运行截图: