中缀变后缀和求后缀表达式的方法参考博客:http://blog.csdn.net/xiaoniba1024/article/details/6573452
http://blog.csdn.net/wu_lai_314/article/details/8274978
表达式的表示形式有中缀、前缀和后缀3中形式。中缀表达式按操作符的优先级进行计算(后面代码实现只包括+、-、*、/,小括号),即数学运算(例:3*(1+2)+6/3 )。 后缀表达式中只有操作数和操作符。操作符在两个操作数之后(例:1 2 + 3 * 即(1+2)*3 )。它的计算规则非常简单,严格按照从左到右的次序依次执行每一个操作。每遇到一个操作符,就将前 面的两个数执行相应的操作。
后缀表达式求值的步骤:
1.初始化一个空操作数栈;
2.从前到后读取后缀表达式字符。如果是操作数直接入栈。如果读到一个操作符@,弹出栈顶元素a和新的栈顶元素b,执行b @ a,将结果压入栈中;
3.最后栈中只剩下一个元素,即表达式的值。
给出的表达式是一般我们见到的中缀表达式,即运算符位于操作数之间。如果把中缀表达式转化为后缀表达式,那么对后缀表达式求值将会很方便。
后缀表达式特点:
1.操作符位于操作数之后;
2.没有括号;
3.运算符没有优先级。
中缀表达式转化为后缀表达式的步骤:
1.初始化一个空操作符栈和空结果字符串;(将中缀转化成后缀时,因为用栈存是倒序的,可以用字符数组存放结果字符串,也可以用栈存,后面再拿出来放数组中)
2.从前到后读取中缀表达式的字符,如果是操作数,加到结果字符串后面;(可以在遇到运算符时在结果字符中加入一个无关字符用来分隔操作数)
3.如果是操作符,分两种情况入栈:
a.如果待入栈操作符优先级大于栈顶操作符,直接入栈;
b.如果待入栈操作符优先级小于或等于栈顶操作符,栈顶操作符加到结果字符串后面;重复b过程直到遇到前括号‘(’或栈顶操作符优先级比待入栈操作符小,待入栈操作符入栈。
4.如果是前括号‘(’,直接入栈;
5.如果是后括号‘)’,将栈中操作符依次弹出,直至遇到一个前括号‘(’结束。前括号出栈。
最后结果字符串就是后缀表达式。
两个中缀变后缀例题:
NYOJ 35 表达式求值
此题操作数可能是小数,处理时要注意;
CODE:
#include<stdio.h>
#include<stack>
#include<algorithm>
#include<string.h>
using namespace std;
char a[2005],b[2005];//a[]输入的中缀表达式串,b[]存中缀变后缀的结果串
int get(char c)//定义操作优先级
{
if(c=='(') return 0;
if(c=='+'||c=='-') return 1;
if(c=='*'||c=='/') return 2;
}
double ys(double x,double y,char c)//操作运算
{
if(c=='+') return x+y;
if(c=='-') return x-y;
if(c=='*') return x*y;
if(c=='/') return x/y;
}
int main()
{
stack<char>s;
stack<char>q;//存中缀变后缀的结果串
stack<double>p;//求后缀表达式时存放操作数的栈
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",a);
while(!s.empty()) s.pop();
while(!q.empty()) q.pop();
while(!p.empty()) p.pop();
int len=strlen(a),pos;
for(int i=0; i<len; i++)
{
if(a[i]>='0'&&a[i]<='9'||a[i]=='.')
{
q.push(a[i]);
}
else if(a[i]=='(')
{
s.push(a[i]);
}
else if(a[i]=='+'||a[i]=='-'||a[i]=='/'||a[i]=='*')
{
q.push('#');//用来分割操作数
if(s.size()==0)
{
s.push(a[i]);
}
else
{ //遇到栈顶有同级或优先级高的放入结果栈
while(!s.empty()&&get(s.top())>=get(a[i]))
{
q.push(s.top());
s.pop();
}
s.push(a[i]);//放入操作符栈
}
}
else if(a[i]==')')//将栈中操作符依次弹出,直至遇到一个前括号‘(’结束。前括号出栈
{
while(s.top()!='(')
{
q.push(s.top());
s.pop();
}
s.pop();
}
else if(a[i]=='=')//遇到结束字符处理操作符栈中的剩余元素,依次出栈
{
while(!s.empty())
{
q.push(s.top());
s.pop();
}
}
}
int kk=0;
while(!q.empty())
{
b[kk++]=q.top();
q.pop();
}
for(int i=kk-1; i>=0; i--)
{
if(b[i]>='0'&&b[i]<='9')//将字符转化为double型放入操作数栈
{
pos=0;
for(int j=i; j>=0; j--)
{
if(b[j]>='0'&&b[j]<='9'||b[j]=='.')
{
pos++;
}
else break;
}
double k=1,sum1=0,sum2=0;
for(int j=i-pos+1; j<=i; j++)
{
if(b[j]>='0'&&b[j]<='9')
{
sum1+=(b[j]-'0')*k;
k*=10;
}
else if(b[j]=='.')
{
sum1/=k;
k=1;
sum2+=sum1;
sum1=0;
}
}
sum2+=sum1;
p.push(sum2);
i-=pos-1;
}
else if(b[i]=='+'||b[i]=='-'||b[i]=='*'||b[i]=='/')//依次计算
{
double x=p.top();p.pop();
double y=p.top();p.pop();
p.push(ys(y,x,b[i]));
}
}
printf("%.2lf\n",p.top());
}
}
NYOJ1727
表达式求值 | (河南省第九届省赛) |
此题操作数都是整数,运算符只有+,*,和Smax(),和上题不同之处在这个Smax,处理时可以把“," 看作运算符
CODE:
#include<stdio.h>
#include<stack>
#include<algorithm>
#include<string.h>
using namespace std;
char a[2005],b[2005];
int get(char c)
{
if(c=='('||c==',') return 0;
if(c=='+') return 1;
if(c=='*') return 2;
}
int ys(int x,int y,char c)
{
if(c=='+') return x+y;
if(c=='*') return x*y;
if(c==',')
{
int xx=0,yy=0;
while(x)
{
xx+=x%10;
x/=10;
}
while(y)
{
yy+=y%10;
y/=10;
}
return max(xx,yy);
}
}
int main()
{
stack<char>s;
stack<char>q;
stack<int>p;
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",a);
while(!s.empty()) s.pop();
while(!q.empty()) q.pop();
while(!p.empty()) p.pop();
int len=strlen(a),pos;
a[len]='=';//加个终止字符
for(int i=0; i<=len; i++)
{
if(a[i]>='0'&&a[i]<='9')
{
q.push(a[i]);
}
else if(a[i]=='(')
{
s.push(a[i]);
}
else if(a[i]=='+'||a[i]=='*'||a[i]==',')
{
q.push('#');
if(s.size()==0)
{
s.push(a[i]);
}
else
{
while(!s.empty()&&get(s.top())>get(a[i]))
{
q.push(s.top());
s.pop();
}
s.push(a[i]);
}
}
else if(a[i]==')')
{
while(s.top()!='(')
{
q.push(s.top());
s.pop();
}
s.pop();
}
else if(a[i]=='=')
{
while(!s.empty())
{
if(s.top()!='S')
{
q.push(s.top());
}
s.pop();
}
}
}
int kk=0;
while(!q.empty())
{
b[kk++]=q.top();
q.pop();
}
for(int i=kk-1; i>=0; i--)
{
if(b[i]>='0'&&b[i]<='9')
{
pos=0;
for(int j=i; j>=0; j--)
{
if(b[j]>='0'&&b[j]<='9'||b[j]=='.')
{
pos++;
}
else break;
}
int k=1,sum1=0,sum2=0;
for(int j=i-pos+1; j<=i; j++)
{
if(b[j]>='0'&&b[j]<='9')
{
sum1+=(b[j]-'0')*k;
k*=10;
}
}
p.push(sum1);
i-=pos-1;
}
else if(b[i]=='+'||b[i]=='*'||b[i]==',')
{
int x=p.top();p.pop();
int y=p.top();p.pop();
p.push(ys(y,x,b[i]));
}
}
printf("%d\n",p.top());
}
}
只要明白了中缀变后缀的过程就简单了,但是写表达式求值太费时间容易出bug需要细心