一、簡介 波蘭表示法(Polish notation,或波蘭記法),是一種邏輯、算術和代數表示方法,其特點是操作符置於操作數的前面,因此也稱做前綴表示法。如果操作符的元數(arity)是固定的,則語法上不需要括號仍然能被無歧義地解析。波蘭記法是波蘭數學家揚·武卡謝維奇1920年代引入的,用於簡化命題邏輯。
揚·武卡謝維奇本人提到:
“ | 我在1924年突然有了一個無需括號的表達方法,我在文章第一次使用了這種表示法。 | ” |
— Łukasiewicz(1), p. 610, footnote. |
阿隆佐·邱奇在他的經典著作《數理邏輯》中提出該表達方法是一種值得被關注的記法系統,甚至將它與阿弗烈·諾夫·懷海德和伯特蘭·羅素在《數學原理》中的邏輯表達式相提並論。 逆波蘭表示法(Reverse Polish notation,RPN,或逆波蘭記法),是一種是由波蘭數學家揚·武卡謝維奇1920年引入的數學表達式方式,在逆波蘭記法中,所有操作符置於操作數的后面,因此也被稱為后綴表示法。逆波蘭記法不需要括號來標識操作符的優先級。 逆波蘭結構由弗里德里希·鮑爾(Friedrich L. Bauer)和艾茲格·迪科斯徹在1960年代早期提議用於表達式求值,以利用堆棧結構減少計算機內存訪問。逆波蘭記法和相應的算法由澳大利亞哲學家、計算機學家查爾斯·漢布林(Charles Hamblin)在1960年代中期擴充。 在1960和1970年代,逆波蘭記法廣泛地被用於台式計算器,因此也在普通公眾(工程、商業和金融領域)中使用。 下面大部分是關於二元運算,一個一元運算使用逆波蘭記法的例子是階乘的記法。 二、中綴表達式到前綴和后綴表達式轉換過程 波蘭表示法(中綴表達式轉換成前綴表達式算法)
- 首先設定一個操作符棧,從右到左順序掃描整個中綴表達式,如果是操作數,則直接歸入前綴表達式;
- 如果是操作符,則檢測器是否是右括號,如果是右括號,則直接將其入棧;
- 如果是左括號,則將棧中的操作符依次彈棧,歸入前綴表達式,直至遇到右括號,將右括號彈棧,處理結束;
- 如果是其他操作符,則檢測棧頂操作符的優先級與當前操作符的優先級關系,
- 如果棧頂操作符優先級大於當前操作符的優先級,則彈棧,並歸入前綴表達式,直至棧頂操作符優先級小於等於當前操作符優先級,這時將當前操作符壓棧。
- 當掃描完畢整個中綴表達式后,檢測操作符棧是否為空,如果不為空,則依次將棧中操作符彈棧,歸入前綴表達式。最后,將前綴表達式翻轉,得到中綴表達式對應的前綴表達式。
逆波蘭表示法(中綴表達式轉換成后綴表達式算法)
- 從左至右掃描一中綴表達式;
- 若讀取的是操作數,則判斷該操作數的類型,並將該操作數存入操作數堆棧;
- 若讀取的是運算符:
- 當表達式讀取完成后運算符堆棧中尚有運算符時,則依序取出運算符到操作數堆棧,直到運算符堆棧為空。
三、 對波蘭表達式和逆波蘭表達式求解過程 波蘭表示法
- 從右到左依次掃描語法單元的項目。
- 如果掃描的項目是操作數,則將其壓入操作數堆棧,並掃描下一個項目。
- 如果掃描的項目是一個二元運算符,則對棧的頂上兩個操作數執行該運算。
- 如果掃描的項目是一個一元運算符,則對棧的最頂上操作數執行該運算。
- 將運算結果重新壓入堆棧。
- 重復步驟第2-5步,堆棧中即為結果值。
- 從左到右依次掃描語法單元的項目。
- 如果掃描的項目是操作數,則將其壓入操作數堆棧,並掃描下一個項目。
- 如果掃描的項目是一個二元運算符,則對棧的頂上兩個操作數執行該運算。
- 如果掃描的項目是一個一元運算符,則對棧的最頂上操作數執行該運算。
- 將運算結果重新壓入堆棧。
- 重復步驟第2-5步,堆棧中即為結果值。
1 class Element(object): 2 '單個Element可以表示一個操作數或運算符.' 3 '_vtype = 0 - none, _vtype = 1 - 操作數, _vtype = 2 - 運算符' 4 5 def __init__(self, vtype, value) : 6 if type(vtype) == int and type(value) == str : 7 self._vtype = vtype 8 self._value = value 9 10 def setType(self, vtype) : 11 if type(vtype) == int : 12 self._vtype = vtype 13 return 0 14 else : 15 return 1 16 17 def setValue(self, value) : 18 if type(value) == str : 19 self._value = value 20 return 0 21 else : 22 return 1 23 24 def setTypeAndValue(self, vtype, value) : 25 if type(vtype) == int and type(value) == str : 26 self.setType(vtype) 27 self.setValue(value) 28 return 0 29 else : 30 return 1 31 32 def getType(self) : 33 return self._vtype 34 35 def getValue(self) : 36 return self._value 37 38 class Stack(object): 39 '棧' 40 # initialze the stack 41 def __init__(self) : 42 self.items = [] 43 44 # judge the stack is empty 45 def isEmpty(self) : 46 return self.items == [] 47 48 # return the top element 49 def peek(self) : 50 return self.items[len(self.items) - 1] 51 52 # return the size of stack 53 def size(self) : 54 return len(self.items) 55 56 # push element into stack 57 def push(self, item) : 58 self.items.append(item) 59 60 # pop the top element 61 def pop(self) : 62 return self.items.pop()
波蘭表示法
1 def convertInfixToPrefix(infixExp) : 2 '將中綴表達式轉換為前綴表達式' 3 expLen = len(infixExp) 4 if type(infixExp) == str and expLen > 0 : 5 #操作數堆棧 6 operandStack = Stack() 7 #運算符堆棧 8 operatorStack = Stack() 9 index = expLen - 1 10 while index >= 0 : 11 if infixExp[index] == ')' : 12 operatorStack.push(Element(2, infixExp[index])) 13 elif infixExp[index] == '(' : 14 while not operatorStack.isEmpty() : 15 elem = operatorStack.peek() 16 if elem.getType() == 2 : 17 if elem.getValue() == ')' : 18 operatorStack.pop() 19 break; 20 else : 21 operandStack.push(operatorStack.pop()) 22 else : 23 continue; 24 elif optPriority(infixExp[index]) > 0 : # + - * / % 運算符 25 if not operatorStack.isEmpty() : 26 elem = operatorStack.peek() 27 if elem.getType() == 2 : 28 if elem.getValue() == ')': 29 operatorStack.push(Element(2, infixExp[index])) 30 elif optPriority(infixExp[index]) > optPriority(elem.getValue()) : 31 operatorStack.push(Element(2, infixExp[index])) 32 else : 33 operandStack.push(operatorStack.pop()) 34 operatorStack.push(Element(2, infixExp[index])) 35 else : 36 operatorStack.push(Element(2, infixExp[index])) 37 elif infixExp[index].isdecimal() : # 數字 38 if index < expLen - 1 and infixExp[index + 1].isdecimal() and not operandStack.isEmpty() : 39 elem = operandStack.pop() 40 elem.setValue(infixExp[index] + elem.getValue()) 41 operandStack.push(elem) 42 43 else : 44 operandStack.push(Element(1, infixExp[index])) 45 else : 46 pass 47 index = index - 1 48 while not operatorStack.isEmpty() : #檢查運算符堆棧是否為空 49 operandStack.push(operatorStack.pop()) 50 51 result = '' 52 while not operandStack.isEmpty() : 53 elem = operandStack.pop() 54 result = result + ' ' + elem.getValue(); 55 return result 56 else : 57 return ''
逆波蘭表示法
1 def convertInfixToSuffix(infixExp) : 2 '將中綴表達式轉換為后綴表達式' 3 expLen = len(infixExp) 4 if type(infixExp) == str and expLen > 0 : 5 #操作數堆棧 6 operandStack = Stack() 7 #運算符堆棧 8 operatorStack = Stack() 9 for index in range(expLen) : 10 if infixExp[index] == '(' : # 左括號 11 operatorStack.push(Element(2, infixExp[index])) 12 13 elif infixExp[index] == ')' : # 右括號 14 while not operatorStack.isEmpty() : 15 elem = operatorStack.peek() 16 if elem.getType() == 2 : 17 if elem.getValue() == '(' : 18 operatorStack.pop() 19 break; 20 else : 21 operandStack.push(operatorStack.pop()) 22 else : 23 continue; 24 25 elif optPriority(infixExp[index]) > 0 : # + - * / % 運算符 26 if not operatorStack.isEmpty() : 27 elem = operatorStack.peek() 28 if elem.getType() == 2 : 29 if elem.getValue() == '(': 30 operatorStack.push(Element(2, infixExp[index])) 31 elif optPriority(infixExp[index]) > optPriority(elem.getValue()) : 32 operatorStack.push(Element(2, infixExp[index])) 33 else : 34 operandStack.push(operatorStack.pop()) 35 operatorStack.push(Element(2, infixExp[index])) 36 else : 37 operatorStack.push(Element(2, infixExp[index])) 38 39 elif infixExp[index].isdecimal() : # 數字 40 if index > 0 and infixExp[index - 1].isdecimal() and not operandStack.isEmpty() : 41 elem = operandStack.pop() 42 elem.setValue(elem.getValue() + infixExp[index]) 43 operandStack.push(elem) 44 45 else : 46 operandStack.push(Element(1, infixExp[index])) 47 else : 48 pass 49 while not operatorStack.isEmpty() : #檢查運算符堆棧是否為空 50 operandStack.push(operatorStack.pop()) 51 52 result = '' 53 while not operandStack.isEmpty() : 54 elem = operandStack.pop() 55 result = elem.getValue() + ' ' + result; 56 return result 57 else : 58 return ''