这几天在预习数据结构的知识。。刚好看到栈的应用 后缀表达式(逆波兰表达式)。
后缀表达式:操作符都在数字的后面,首先要运用后缀表达式,要明白如何从中缀表达式转换到后缀表达式,然后如何从后缀表达式进行计算。
首先中缀转后缀:
将表达式读入,数字直接输出到后缀表达式中,符号则 判断其与栈顶元素之间优先级的关系,如果优先级不高于栈顶元素的优先级,则将栈顶元素输出,再对新的栈顶元素进行重复操作。直到最后将该符号压入栈中。 如果符号是右括号,将与栈中遇到的第一个左括号之间的符号都输出, 括号都不用输出。
通过后缀表达式进行计算:
将数字都压入另一个存放数字的栈之中,碰到字符就将栈顶元素取出当做第二操作数,弹出,再取一个当做第一操作数,弹出,将计算结果再压入栈中。
第一次写还是写了好久,思路也不能说非常清晰。这道题目我用了‘#’来分隔每个数字与操作符,因为不分隔的话无法判断这是多位的数字还是两个数字。
记录后缀表达式的数组记得要初始化,或者边界不用strlen。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <cstring>
#include <cctype>
using namespace std;
#define M 1009
char a[M] = "+-*/";
int b[M] = {1,1,2,2};
char out[M];
char in[M];
stack<char> s; //存放操作符
int main()
{
while(1)
{
//memset(out,'\0',sizeof(out));
gets(in);
if(strcmp(in,"0")==0)
break;
int k = 0;
for(int i = 0;i < strlen(in);i++)
{
if(in[i]==' ') continue;
if(isdigit(in[i]))
{
if(i < strlen(in)-1 && isdigit(in[i+1]))
out[k++] = in[i];
else
{
out[k++] = in[i];
out[k++] = '#';
}
}
else
{
while(!s.empty())
{
int p=-1,q=-1;
for(int j = 0;j < 4;j++)
{
if(a[j]==in[i])
{
p = j;
}
if(a[j]==s.top())
{
q = j;
}
}
if(p!=-1 && q!=-1)
{
if(b[p] <= b[q])
{
out[k++] = s.top();
out[k++] = '#';
s.pop();
}
else break;
}
}
s.push(in[i]);
}
}
while(!s.empty())
{
out[k++] = s.top();
out[k++] = '#';
s.pop();
}
//printf("%s\n",out);
//int p = 0;
double sum = 0;
stack<double> ss; //存放数字
int ok = 0;
for(int i = 0;i < k;i++) //循环到后缀表达式的最后一个
{
if(isdigit(out[i]))
{
sum = 10*sum + out[i]-'0';
ok = 1;
}
else
{
if(ok)
{
ss.push(sum);
ok = 0;
sum = 0;
}
if(out[i]!='#')
{
double one ,two;
one = ss.top();
ss.pop();
two = ss.top();
ss.pop();
double temp;
switch (out[i])
{
case '+':
temp = one+two;
ss.push(temp);
break;
case '-':
temp = two-one;
ss.push(temp);
break;
case '*':
temp = one*two;
ss.push(temp);
break;
case '/':
temp = (double)two/one;
ss.push(temp);
break;
}
}
}
}
if(!ss.empty())
printf("%.2f\n",ss.top());
while(!ss.empty()) ss.pop();
while(!s.empty())s.pop();
}
return 0;
}