逆波兰表达式

    1 + 2 - (4 - 2 * 3 /2)  * 5

正常的中缀表达式(运算符左右是参与计算的两个值),符合两条运算规则

    1.运算符优先级高的先计算。

    2.运算符优先级相同则左到右依次计算。

 

第一条运算规则是高于第二条的。

如果严格按照这个定律的话,中缀表达式在正常处理上,是比较跳脱的,步骤如下:

    1.需要先找到最高优先级的运算符,参与计算。

    2.重复1,直到剩下的运算符优先级相同。

    3.从左到右依次计算。

    如果表达式中只有 '+' , '-', '*' , '/' ,那还比较方便,因为只有两个优先级,所以只需要两轮计算,第一轮计算 '*' ,'/' ,第二轮计算'+','-'。

    但是如果有括号的话,因为括号的优先级不是固定的,括号内的括号的优先级比括号外的括号的优先级高。

    这样的情况下,程序实现的话,需要一轮一轮的计算去消除括号,十分繁琐。

    仔细想想,繁琐的原因是因为优先级的不确定性,需要自己去找当前优先级最高的运算符。如果能把表达式中的运算符转换成按实际计算顺序的形式,相当于消除掉了第一条运算定理(运算符优先级高的先计算)那么计算起来就十分便捷,只需要按序读取计算即可。

本文第一行的运算表达式如下:

    1 + 2 - (4 - 2 * 3 /2)  * 5;

按实际计算顺序转换成新的表达式:

    到这里发现,行不通,因为中缀表达式的特性,运算符左右是参数计算的值,运算符放中间的话,如果右值是一个表达式需要优先计算,并不知道右值需要计算到第几个计算符,换言之,还得加括号。。

 

 

逆波兰表达式能解决这个问题,了解一下。它是一种后缀表达式。

逆波兰表达式如何构建?

本文第一行的运算表达式转化为逆波兰表达式:

    1 2 4 2 3 * 2 / - - + 5 *

转化的过程及其简单:

    1.把所有的数值抄下来

        1 2 4 2 3 2 5

    2.根据运算符的优先顺序,将运算符添加到相应的两个数值后

        2.1 先计算1 + 2 - (4 - 2 * 3 /2)  * 5中的'*'

            添加至待计算值的后方,变为:1 2 4 2 3 * 2 5

        2.2 再计算1 + 2 - (4 - 2 * 3 /2)  * 5中的 '/'

            添加至待计算值的后方,变为:1 2 4 2 3 * 2 / 5

        2.3 再计算1 + 2 - (4 - 2 * 3 /2)  * 5中的 '-'

            添加至待计算值的后方,变为:1 2 4 2 3 * 2 / - 5

    3. 根据2依次类推,得到逆波兰表达式:

        1 2 4 2 3 * 2 / - - + 5 *

 

逆波兰表达式如何计算?

以下面的逆波兰表达式为例:

    1 2 4 2 3 * 2 / - - + 5 *

1. 读取第一个运算符,向前取运算符所需的数值个数参与计算。

    1 2 4 2 3 * 2 / - - + 5 *

2.将计算结果填入当前位置,得到新的逆波兰表达式

    1 2 4 6 2 / - - + 5 *

3.重复步骤1,步骤2,直到没有运算符为止,得到了最终结果。

 

逆波兰表达式有啥用?

    根据计算过程,它是顺序计算的。在程序中,只需要一个stack,一次遍历表达式,就可以得到计算结果。

程序计算流程如下:

    1.从左到右,数值依次入栈,若碰见运算符,执行步骤2

    2.从栈中取运算符所需的数值个数参与计算,将计算结果入栈.

    3.重复步骤1,步骤2 直到逆波兰表达式读取完。

    4.此时栈中还有一个数值,这个数值就是最终结果。

 

为什么逆波兰表达式(后缀表达式)好使?中缀表达式为什么不行?前缀表达式行么?

    从左到右顺序读取时,只有后缀表达式是先拿到参与计算的数值,再拿到计算符,此时,值一定是个确定的值。前缀,中缀表达式都是先拿到了计算符,后拿到参与计算的值,而此时,这个值可能还只是一个子表达式,需要计算才能得到确定的值。后缀表达式能保证参与计算的一定是值,而不是表达式。

 

 

 以1 + 2 - (4 - 2 * 3 /2)  * 5为例子。第一步计算2*3和第一步计算1+2都是没问题的。所以同一个中序表达式有多个逆波兰表达式形态

 

中序表达式转逆波兰表达式,就是确定运算符相对优先的,然后填入对应的位置即可。为什么是相对有限的?

     当然我们关心的是怎么转换。

算法实现思路 中序表达式转逆波兰表达式

    举几个例子:

    有表达式 1 a 2 b 3 c 4 d 5

    其中a,b,c,d分别是运算符。

    若优先级是a>=b>=c>=d,计算顺序显而易见,(((1 a 2) b 3) c 4) d 5 

    即:从左向右计算,如果当前运算符优先级大于等于下一个运算符,则直接计算。

    若优先级是a<b<c<d    ,计算顺序显而易见 ,最优先计算的是d,其次是c,再次b,最后a

    即:从左向右计算,如果当前运算符优先级小于下一个运算符,则先将此运算符入栈,如果运算符读取完,则依次出栈计算。

   若优先级是a<b<c=d,

    即:从左向右计算,如果当前运算符优先级小于下一个运算符,则先将此运算符入栈,如果运算符读取完

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值