Python 栈 四则运算

首先了解一下栈:

栈是限定仅在表尾进行插入和删除操作的线性表。允许插入与删除的一段叫做栈顶,另一端
叫做栈底,不含任何数据元素的栈称为空栈。栈又称为后进先出(Last In First Out)的线性
表,简称LIFO结构。

在Python中,可以用列表来实现栈:

lt = [3]
#相当于压栈
lt.append(4)
print(lt)
>>>[3,4]
#相当于弹栈
lt.pop()
print(lt)
>>>[3]

利用栈这种数据结构我们可以实现四则运算。首先,我们来了解一些名词:

中缀表达式:我们再平常写的四则运算表达式就叫做中缀表达式,运算符位于数字中间,例如:
9+3*(2+1)
后缀表达式:将运算符写到数字后面的式子叫做后缀表达式,对于上面的例子来说:

中缀表达式转为后缀表达式思路9+3*(2+1):

  1. 设立一个运算符栈和后缀表达式栈;
  2. 第一个元素为数字9,加入后缀表达式栈:9;
  3. 第二个元素为运算符“ + ”,加入到运算符栈:+;
  4. 第三个元素为数字3,后缀表达式栈:9 3;
  5. 第四个元素为运算符“ * ”,由于 “ * ” 的优先级大于栈顶元素 +,所以将其加入到运算符栈中:+ *;
  6. 第五个元素为“ ( ”,加入到运算符栈中:+ * (;
  7. 第六个元素为数字2,后缀表达式栈:9 3 2;
  8. 第七个元素为运算符“ + ”,加入到运算符栈:+ * ( +;
  9. 第八个元素为数字1,后缀表达式栈:9 3 2 1;
  10. 第九个元素为“ ) ”,并且由于这是最后一个元素,运算符栈开始弹出,并
    加入到后缀表达式栈中:9 3 2 1 + * +

后缀表达式写出来后,又该怎样去计算呢?我们可以发现,当遍历后缀表达式时,可以将数字元素加入到一个新栈,然后遇到一个运算符就弹出两个数字进行运算,将值压栈,直到最后一个元素为止,这样新栈中的值就是运算结果.

代码:

# 转为后缀表达式.运算表达式元素之间用空格隔开:
def change_houzhui(s):
    result = []  # 结果列表
    stack = []  # 栈
    s_lt = s.split(' ')
    for item in s_lt:
        if item.isnumeric():  # 如果当前字符为数字那么直接放入结果列表
            result.append(item)
        else:  # 如果当前字符为一切其他操作符
            if len(stack) == 0:  # 如果栈空,直接入栈
                stack.append(item)
            elif item in '*/(':  # 如果当前字符为*/(,直接入栈
                stack.append(item)
            elif item == ')':  # 如果右括号则全部弹出(碰到左括号停止)
                t = stack.pop()
                while t != '(':
                    result.append(t)
                    t = stack.pop()
            # 如果当前字符为加减且栈顶为乘除,则开始弹出
            elif item in '+-' and stack[-1] in '*/':
                if stack.count('(') == 0:  # 如果没有左括号,弹出所有
                    while stack:
                        result.append(stack.pop())
                else:  # 如果有左括号,弹到左括号为止
                    t = stack.pop()
                    while t != '(':
                        result.append(t)
                        t = stack.pop()
                    stack.append('(')
                stack.append(item)  # 弹出操作完成后将‘+-’入栈
            else:
                stack.append(item)  # 其余情况直接入栈(如当前字符为+,栈顶为+-)

    # 表达式遍历完了,但是栈中还有操作符不满足弹出条件,把栈中的东西全部弹出
    while stack:
        result.append(stack.pop())
    # 返回字符串
    return result

#后缀表达式进行计算
def calac_houzhui(follow):
    num = []
    base_opt = ['+', '-', '*', '/']
    for j in follow:
        if j.isdigit():
            num.append(int(j))
        if j in base_opt:
            num2 = num.pop()
            num1 = num.pop()
            if j == "+":
                num.append(num1 + num2)
            elif j == "-":
                num.append(num1 - num2)
            elif j == "*":
                num.append(num1 * num2)
            else:  
                num.append(num1 / num2)
    return num
if __name__ == '__main__':
    s = "9 + 3 * ( 2 + 1 )"   #空格隔开,括号注意中英文不要乱
    print(calac_houzhui(change_houzhui(s)))
>>>[18]