逆波兰算法-python代码实现

1,逆波兰算法简介

假定给定一个只 包含 加、减、乘、除,和括号的算术表达式,你怎么编写程序计算出其结果?

问题是:在表达式中,括号,以及括号的多层嵌套 的使用,运算符的优先级不同等因素,使得一个算术表达式在计算时,运算顺序往往因表达式的内容而定,不具规律性。 这样很难编写出统一的计算指令。
使用逆波兰算法可以轻松解决这个问题。他的核心思想是将普通的中缀表达式转换为后缀表达式。

什么是中缀表达式?例如a+b,运算符在两个操作数的中间。这是我们从小学开始学习数学就一直使用的表达式形式。

什么是后缀表达式?例如a b + ,运算符在两个操作数的后面。后缀表达式虽然看起来奇怪,不利于人阅读,但利于计算机处理。

转换为后缀表达式的好处是:
1、去除原来表达式中的括号,因为括号只指示运算顺序,不是实际参与计算的元素。
2、使得运算顺序有规律可寻,计算机能编写出代码完成计算。

2,逆波兰算法原理

逆波兰算法的核心步骤就2个:
1、将中缀表达式转换为后缀表达式,例如输入的原始表达式是 3*(5+7) ,转换得到 3 5 7 + *
2、根据后缀表达式,按照特定的计算规则得到最终计算结果

下面详细介绍这个2步的操作。

中缀表达式转换为后缀表达式
你需要设定一个栈SOP,和一个线性表 L 。SOP用于临时存储运算符和左括号分界符( ,L用于存储后缀表达式。
遍历原始表达式中的每一个表达式元素
(1)如果是操作数,则直接追加到 L中。只有 运算符 或者 分界符( 才可以存放到 栈SOP中
(2)如果是分界符
         Ⅰ 如果是左括号 ( , 则 直接压入SOP,等待下一个最近的 右括号 与之配对。
          Ⅱ 如果是右括号),则说明有一对括号已经配对(在表达式输入无误的情况下)。不将它压栈,丢弃它,然后从SOP中出栈,得到元素e,将e依次追加到L里。一直循环,直到出栈元素e 是 左括号 ( ,同样丢弃他。
(3)如果是运算符(用op1表示)
        Ⅰ如果SOP栈顶元素(用op2表示) 不是运算符,则二者没有可比性,则直接将此运算符op1压栈。 例如栈顶是左括号 ( ,或者栈为空。
         Ⅱ 如果SOP栈顶元素(用op2表示) 是运算符 ,则比较op1和 op2的优先级。如果op1 > op2 ,则直接将此运算符op1压栈。
如果不满足op1 > op2,则将op2出栈,并追加到L,再试图将op1压栈,如果如果依然不满足 op1>新的栈顶op2,继续将新的op2弹出追加到L ,直到op1可以压入栈中为止。
也就是说,如果在SOP栈中,有2个相邻的元素都是运算符,则他们必须满足:下层运算符的优先级一定小于上层元素的优先级,才能相邻。

最后,如果SOP中还有元素,则依次弹出追加到L后,就得到了后缀表达式。

3,应用

请写一个整数计算器,支持加减乘除三种运算和括号。

输入

"1+2"

输出

3

输入

"(2*(3-4))*5"

输出

-10

python 代码实现:

class Solution:
    def __init__(self):
        self.Operator_priority = {
            "+": 0,
            "-": 0,
            "*": 1,
            "/": 1
        }
        self.Operator = ["+""-""*""/"]
        self.DemarcationSymbol = ["("")"]
        self.L = []
        self.stack = []

    def solve(self, s):
        self.infixToSuffix(s)
        return self.suffixToResult(self.L)


    def changeTypeofExpression(self, expression):
        temp_expression = []
        temp_num ""
        for exp in expression:
            if exp.isdigit():
                temp_num += exp
                continue
            else:
                temp_expression.append(temp_num)
                temp_num ""
                temp_expression.append(exp)
        temp_expression.append(temp_num)
        return temp_expression


    def infixToSuffix(self, expression):
        temp_expression = self.changeTypeofExpression(expression)
        for item in temp_expression:
            if item.isdigit():
                self.L.append(item)
            elif item in self.Operator:  # 判断是否是操作符
                while len(self.stack) != 0 and self.stack[-1] in self.Operator and self.Operator_priority[item] <= self.Operator_priority[self.stack[-1]]:
                    self.L.append(self.stack.pop())
                self.stack.append(item)


            elif item in self.DemarcationSymbol:  # 判断是否是分隔符
                if item == "(":
                    self.stack.append(item)
                elif item == ")":
                    while len(self.stack) != 0 and self.stack[-1] != "(":
                        self.L.append(self.stack.pop())
                    if len(self.stack) != 0:
                        self.stack.pop()


        while len(self.stack) != 0:
            self.L.append(self.stack.pop())


    def suffixToResult(self, suffix_expression):
        for item in suffix_expression:
            if item.isdigit():  # 如果是数字就添加到stack中去
                self.stack.append(item)
            elif item in self.Operator:
                num1 = self.stack.pop()
                num2 = self.stack.pop()
                temp_value = self.Calculation(float(num2), float(num1), item)
                self.stack.append(temp_value)
        return self.stack.pop()


    def Calculation(self, num1, num2, op):
        if op == "+":
            return num1+num2
        elif op == "-":
            return num1-num2
        elif op == "*":
            return num1*num2
        else:
            return num1/num2


if __name__ == "__main__":
    s = Solution()
    print(s.solve("(100+100)*100"))

 

posted @ 2020-10-27 16:39  不能说的秘密  阅读(975)  评论(0编辑  收藏  举报