逆波蘭算法-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"))

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM