用Python实现表达式求值,递归解法和栈解法(附详细代码和测试)

问题描述:

输入四则运算表达式,仅由数字、+、-、*、/、()组成,没有空格,要求求其值,假设运算符结果都是整数,/结果也是整数

输入:
(2+3)*(5+7)+9/3
输出:
63

第一种解法:eval()函数

>>> eval('(3+5)*2')
16

第二种解法:递归

搞清楚表达式的递归定义很关键

  • 表达式=项或项的加减
  • 项=因子或因子的乘除
  • 因子=(表达式)或整数

代码:

def expression_value():
    global i
    a=term_value()
    if i==len(s):
        return a
    c=s[i]
    while c in '+-':
        i+=1
        b=term_value()
        if c=='+':
            a+=b
        else:
            a-=b
        if i==len(s):
            return a
        else:
            c=s[i]
            if c==')':
                i+=1
                return a
    return a
def term_value():
    global i
    a=factor_value()
    if i==len(s):
        return a 
    c=s[i]
    while c in '*/':
        i+=1
        b=term_value()
        if c=='*':
            a*=b
        else:
            a=a//b
        if i==len(s):
            return a 
        else:
            c=s[i]
    return a
def factor_value():
    global i
    if s[i]=='(':
        i+=1
        return expression_value()
    else:
        temp_i=i 
        while s[i].isdigit():
            i+=1
            if i==len(s):
                break
        return int(s[temp_i:i])
s='(((3+2)*2-8)-8)*3+20'
i=0
print(expression_value())

输出为2,正确

但是这种做法有个bug,就是把没必要加括号的加了括号就会只计算括号里的
比如(8/4)-6得到2,但是8/4-6得到-4,此bug留待有缘再来破。。。

第三种解法:栈

  1. 中缀表达式转后缀表达式(栈存放操作符)
  2. 计算后缀表达式的值(栈存放数)

中缀转后缀的规则:(这里借鉴自csdn的某位作者)

中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f  + g * +。

转换过程需要用到栈,具体过程如下:

1)如果遇到操作数,我们就直接将其输出。

2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。

3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。

4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。

5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。

上代码,其中中缀转后缀的函数是参考这个规则写的,感觉还挺麻烦,写了快一个小时。不过最后的结果还是感到舒适。

def infix2suffix(s):
    l=[]
    out=[]
    i=0
    while i [2, 3, '+', 5, 7, '+', '*', 9, 3, '/', '+', 8, 4, '/', 6, '-', '-']
> 67

这种做法就很好了,无论怎么加括号都会得到正确的逆波兰表达式和结果。

中缀转后缀用到的栈存放符号,根据一系列规则生成正确的后缀表达式。后缀表达式求值用到的栈存放数,这个过程就很简单了。

 

最后要问的是有没有人知道递归解法我的代码哪里出了bug?请在下面留言,感激不尽~

你可能感兴趣的:(算法)