表达式求值与后缀表达式

 一个算术表达式,含有数字(为简化处理,数字只有一位),运算符:+、-、*,以及括号,求表达式的值。


 给出的表达式是一般我们见到的中缀表达式,即运算符位于操作数之间。如果把中缀表达式转化为后缀表达式,那么对后缀表达式求值将会很方便。


 后缀表达式特点:


  1.操作符位于操作数之后;


  2.没有括号;


  3.运算符没有优先级。


 中缀表达式转化为后缀表达式的步骤:


  1.初始化一个空操作符栈和空结果字符串;


  2.从前到后读取中缀表达式的字符,如果是操作数,加到结果字符串后面;


  3.如果是操作符,分两种情况入栈:


    a.如果待入栈操作符优先级大于栈顶操作符,直接入栈;


    b.如果待入栈操作符优先级小于或等于栈顶操作符,栈顶操作符加到结果字符串后面;重复b过程直到遇到前括号‘(’或栈顶操作符优先级比待入栈操作符小,待入栈操作符入栈。


  4.如果是前括号‘(’,直接入栈;


  5.如果是后括号,将栈中操作符依次弹出,直至遇到一个前括号‘(’结束。前括号出栈。


  最后结果字符串就是后缀表达式。


  后缀表达式求值的步骤:


  1.初始化一个空操作数栈;


  2.从前到后读取后缀表达式字符。如果是操作数直接入栈。如果读到一个操作符@,弹出栈顶元素a和新的栈顶元素b,执行b @ a,将结果压入栈中;


  3.最后栈中只剩下一个元素,即表达式的值。


 


  关于中缀表达式转换成后缀表达式与后缀表达式正确性的说明:


  先观察一些例子:


  1.假设中缀表达式没有括号,且所有运算符优先级相同。比如a+b-c+d-e+f ,将被转化为ab+c-d+e-f+。此时用括号来说明后缀表达式执行顺序:((((( ab+ ) c- ) d+ ) d- ) f+ ),运算顺序没有改变。


  2.假设中缀表达式没有括号,但是运算符优先级不同。比如a+b*c+d-e*f,将被转化为 abc*+d+ef*-,用括号来说明后缀表达式执行顺序:((( a ( bc* ) + ) d+ ) ( ef* ) - ),运算顺序依然没有变。


  3.假设中缀表达式有括号。比如(a+b)*(c+d)*e+f,将被转化为ab+cd+*e*f+,用括号表示执行顺序(((( ab+ ) ( cd+ ) * ) e* ) f+ )。运算顺序还是没有改变。


 


  不难观察出以下5点:


  1.后缀表达式中操作数出现的顺序和中缀表达式一样。这是因为操作数是直接加入结果字符串;


  2.每个操作符都会入栈一次,出栈一次;


  3.在没有括号时,如果相邻两个操作符优先级相同或前一个操作符的优先级高,则后缀表达式中操作符出现的顺序和中缀表达式一样。因为后一个操作符入栈时,栈顶元素一定是前一个相邻的操作符,如果其优先级小于等于待入栈的,则前一个操作符被弹出并加入结果字符串,后缀表达式中操作符顺序得到保持。


  4.在没有括号时,如果相邻两个操作符,后者优先级大与前者,后者将直接被压入栈中,且位于前者之上。在出栈时,后者将先出栈,因而后缀表达式中,操作符顺序发生交换,即中缀表达式中要先运算的操作在后缀表达式中出现在前面。


  5.出现括号。括号中的处理因为遵循前4点,不再赘述,而括号的内容作为一个整体的性质得到维护。


  参考文章:


  http://blog.csdn.net/daheiantian/article/details/6553713


  http://blog.csdn.net/niushuai666/article/details/6702964


  http://www.cnblogs.com/luna-lovegood/archive/2012/07/17/2596464.html




//数据结构与算法
 //利用后缀表达式对算数表达式求值
 //不含符号变量处理,且数字都是一位,运算符仅含+、-、*和括号
 #include
 #include
 #include
 #define NUM 200
 
 using namespace std;
 
 char s[NUM],a[NUM],stack[NUM];
 int stacknum[NUM];
 
 int trans(char s[NUM],char a[NUM],char stack[NUM],int lens){
     int lena = 0,top = 0;
     for(int i=0; i){
         if(s[i]>='0' && s[i]<='9'){
             a[lena++] = s[i];
         }
         else if(s[i]=='+' || s[i]=='-'){
             while(top>0 && stack[top-1]!='(')
                 a[lena++] = stack[--top];
             stack[top++] = s[i];
         }
         else if(s[i] == '*'){
             while(top>0 && stack[top-1]!='(' && stack[top-1]!='+' && stack[top-1]!='-')
                 a[lena++] = stack[--top];
             stack[top++] = s[i];
         }
         else if(s[i]=='(')
             stack[top++] = s[i];
         else if(s[i]==')'){
             while(top>0 && stack[top-1]!='(')
                   a[lena++] = stack[--top];
             top--;
         }
     }
     while(top>0){
         a[lena++] = stack[--top];
     }
     return lena;
 }
 
 int calcu(char a[NUM],int stack[NUM],int lena){
     int top=0;
     for(int i=0; i)
         if(a[i]>='0' && a[i]<='9')
             stack[top++] = a[i]-'0';
         else{
             if(a[i]=='+')
                 stack[top-2] = stack[top-2] + stack[top-1];
             else if(a[i] == '-')
                 stack[top-2] = stack[top-2] - stack[top-1];
             else if(a[i]=='*')
                 stack[top-2] = stack[top-2] * stack[top-1];
             top--;
         }
     return stack[0];
}
 
 int main()
 {
     int ans,lens,lena;
     gets(s);
     lens = strlen(s);
     lena = trans(s,a,stack,lens);//将中缀表达式转换横后缀表达式,返回值是后缀表达式a的长度
     ans = calcu(a,stacknum,lena);//计算后缀表达式值
     printf("%d\n",ans);
     return 0;
 }


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值