后缀表达式求值
中缀表达式转换为后缀表达式
首先说明一点,中缀表达式中间是可以有括号的,而括号的作用在于扰乱计算的顺序,使得括号内的计算优先级高于括号外的,但是在括号内,四则运算的法则依然是成立的。
而后缀表达式则严格按照计算符出现的顺序来执行操作。
在下面的代码中,用到了栈,解释一下使用栈的理由。
无论是加减乘除,都需要两个操作数,但是我们阅读中缀表达式的时候都是从左向右看,当你发现一个运算符的时候,你只能确定你的左边一定有一个已经计算完毕的操作数,但是你不能保证你的下一个字符也是操作数,因为可能存在优先级比你高的操作数在后面等待计算,你使用的只是返回值,所以我们使用栈来进行缓冲。
由于栈是后进先出的,所以当优先级低的操作符出现时,高级的操作符必须已经完成计算(后缀表达式严格按照计算符出现的顺序),所以我们要从栈顶开始把优先级高的操作数全部出栈,然后将低优先级的运算符入栈。(如果不这么做,当扫描输入完成时,栈由上往下出栈进入后缀表达式时,低优先级运算符会在高优先级运算符的左边)
对于括号的处理,括号的优先级是最高的,把他当成优先级最高的运算符处理即可,但是要注意把左括号也出栈。
代码中对后缀表达式中加入了空格,是为了方便对于后缀表达式的计算,想一想如果后缀表达式有一堆数字,1234,你如何区分他是12 和34还是1 和234,我们加入分隔符来进行分辨,这里的分隔符是空格
#include<iostream>
#include<map>
#include<cstring>
#include<cctype>
using namespace std;
map<char, int>ID;
int top = 0;
int head = -1;
const int maxn = 200;
char postfix[maxn];
char infix[maxn];
char S[maxn];
int main(void)
{
int len = 0;
char ch;
while ((ch = getchar()) != '\n')
{
infix[len++] = ch;
}
ID['+'] = ID['-'] = 1;
ID['*'] = ID['/'] = 2;
for (int i = 0; i < len; i++)
{
if (infix[i] == ' ')
{
continue;
}
else if (infix[i] == '(')
{
S[++top] = infix[i];
}
else if (isdigit(infix[i]))
{
while (1)
{
postfix[++head] = infix[i];
if (isdigit(infix[i + 1]))
{
i++;
}
else
{
break;
}
}
postfix[++head] = ' ';
}
else if (infix[i] == ')')
{
while (S[top] != '(')
{
postfix[++head] = S[top--];
postfix[++head] = ' ';
}
top--;
}
else
{
while (top>0&&ID[S[top]] >= ID[infix[i]])
{
postfix[++head] = S[top--];
postfix[++head] = ' ';
}
S[++top] = infix[i];
}
for (int i = 1; i <= top; i++)
{
printf("S[%d] = %c\n", i, S[i]);
}
}
while (top>0)
{
postfix[++head] = S[top--];
postfix[++head] = ' ';
}
printf("%s", postfix);
return 0;
}
后缀表达式求值
得到了后缀表达式,进行计算求值就是一件很简单的事情,因为不用考虑优先级的问题,只要从左往右扫描,如果是数字就放进栈里,如果是运算符,就从栈中提取两个数,把计算结果放回即可。
int calculate()
{
int h = 0,x=0;
int s[maxn];
int len = strlen(postfix);
for (int i = 0; i < len; i++)
{
switch (postfix[i])
{
case '+':s[--h] += s[h + 1]; break;
case '-':s[--h] -= s[h + 1]; break;
case '*':s[--h] *= s[h + 1]; break;
case '/':s[--h] /= s[h + 1]; break;
case ' ':break;
default:
{
x = 0;
while(1)
{
if (isdigit(postfix[i]))
{
x = x * 10 + (postfix[i] - '0');
i++;
}
else
{
break;
}
}
}
s[++h] = x;
for (int i = 0; i <= h; i++)
{
printf("%d ", s[i]);
}
printf("\n");
break;
}
}
return s[1];
}
完整代码
#include<iostream>
#include<map>
#include<cstring>
#include<cctype>
using namespace std;
map<char, int>ID;
int top = 0;
int head = -1;
const int maxn = 200;
char postfix[maxn];
char infix[maxn];
char S[maxn];
int calculate()
{
int h = 0,x=0;
int s[maxn];
int len = strlen(postfix);
for (int i = 0; i < len; i++)
{
switch (postfix[i])
{
case '+':s[--h] += s[h + 1]; break;
case '-':s[--h] -= s[h + 1]; break;
case '*':s[--h] *= s[h + 1]; break;
case '/':s[--h] /= s[h + 1]; break;
case ' ':break;
default:
{
x = 0;
while(1)
{
if (isdigit(postfix[i]))
{
x = x * 10 + (postfix[i] - '0');
i++;
}
else
{
break;
}
}
}
s[++h] = x;
for (int i = 0; i <= h; i++)
{
printf("%d ", s[i]);
}
printf("\n");
break;
}
}
return s[1];
}
int main(void)
{
int len = 0;
char ch;
while ((ch = getchar()) != '\n')
{
infix[len++] = ch;
}
ID['+'] = ID['-'] = 1;
ID['*'] = ID['/'] = 2;
for (int i = 0; i < len; i++)
{
if (infix[i] == ' ')
{
continue;
}
else if (infix[i] == '(')
{
S[++top] = infix[i];
}
else if (isdigit(infix[i]))
{
while (1)
{
postfix[++head] = infix[i];
if (isdigit(infix[i + 1]))
{
i++;
}
else
{
break;
}
}
postfix[++head] = ' ';
}
else if (infix[i] == ')')
{
while (S[top] != '(')
{
postfix[++head] = S[top--];
postfix[++head] = ' ';
}
top--;
}
else
{
while (top>0&&ID[S[top]] >= ID[infix[i]])
{
postfix[++head] = S[top--];
postfix[++head] = ' ';
}
S[++top] = infix[i];
}
}
while (top>0)
{
postfix[++head] = S[top--];
postfix[++head] = ' ';
}
printf("%s\n", postfix);
int ans = calculate();
printf("%d", ans);
return 0;
}