栈的应用之后缀表达式求值

后缀表达式,指的是不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则)。我们数学上采用的表达式叫中缀表达式,即将运算放在两个运算对象中间。此外还有后缀表达式,即将运算符放在两个运算对象的前面。

下面是同一个算术表达式的三种等价表示形式:

中缀形式:(3-5)*(6+17*4)/3

前缀形式:/ * - 3 5 + 6 * 17 4 3

后缀形式:3 5 - 6 17 4 * + * 3 /

根据后缀表达式的计算规则,计算过程应该是顺序检查表达式里的一个个项,分两种情况:

  • 遇到运算对象时,应该记录它以备后面使用。
  • 遇到运算符(函数名也一样,下面不考虑)时,应该根据其元数(下面假定都是二元运算符),取得前面最近遇到的几个运算对象或已完成运算的结果(二元运算符都取2个),应用这个运算符(或函数)计算,并保存其结果。

由于表达式可以任意复杂,不能事先确定需要记录的信息的项数,必须用一个缓存结构。采用什么结构则要根据计算的性质决定。首先分析情况:

  • ·需要记录的是已经掌握的数据,无论这些数据是直接由外部得到,还是前面计算出来,都需要缓存。因为当时这些中间结果还不能立刻使用。
  • 每次处理运算符,应使用的是此前最后记录的几个结果(具体项数根据运算符的元数确定,现在都是2)。

显然,这里的情况是典型的后保存先使用,应该用栈作为缓存结构。

def suf_exp_evaluator(exp):
    operators="+-*/"
    st=ESStack()                     #栈

    for x in exp:
        if x not in operators:      #x不是运算符,转化为小数,压入栈
            st.push(float(x))        #转化不成功会抛出异常
            continue                #continue的作用:一直将数字压入栈

        if st.depth()<2:            #一个后缀表达式,前两个元素肯定都是数字,如果栈的深度小于2,则表达式的长度不够
            print("表达式长度不够")
            return

        a = st.pop()                #从栈顶取出两个元素
        b = st.pop()

        c=0                         #根据当前运算符计算结果,压入栈
        if x=="+":
            c=b+a
        if x=="-":
            c=b-a
        if x=="*":
            c=b*a
        if x=="/":
            c=b/a

        st.push(c)

    if st.depth()==1:               #全部处理完栈里应该只用一个元素,否则表达式有误
        return st.pop()
    else:
        print("表达式有误")

if __name__ == '__main__':
    exp=input("请输入后缀表达式(每项空格分隔):\n").split()
    print(suf_exp_evaluator(exp))

测试结果为:

请输入后缀表达式(每项空格分隔):
3 5 - 6 17 4 * + * 3 /
-49.333333333333336

可见后缀表达式的计算对于计算机来说十分简单,是一种便于计算机计算的算术表达形式。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值