波兰表示法和逆波兰表示法
一、简介 波兰表示法(Polish notation,或波兰记法),是一种逻辑、算术和代数表示方法,其特点是操作符置于操作数的前面,因此也称做前缀表示法。如果操作符的元数(arity)是固定的,则语法上不需要括号仍然能被无歧义地解析。波兰记法是波兰数学家扬·武卡谢维奇1920年代引入的,用于简化命题逻辑。
扬·武卡谢维奇本人提到:
“ | 我在1924年突然有了一个无需括号的表达方法,我在文章第一次使用了这种表示法。 | ” |
— Łukasiewicz(1), p. 610, footnote. |
阿隆佐·邱奇在他的经典著作《数理逻辑》中提出该表达方法是一种值得被关注的记法系统,甚至将它与阿弗烈·诺夫·怀海德和伯特兰·罗素在《数学原理》中的逻辑表达式相提并论。 逆波兰表示法(Reverse Polish notation,RPN,或逆波兰记法),是一种是由波兰数学家扬·武卡谢维奇1920年引入的数学表达式方式,在逆波兰记法中,所有操作符置于操作数的后面,因此也被称为后缀表示法。逆波兰记法不需要括号来标识操作符的优先级。 逆波兰结构由弗里德里希·鲍尔(Friedrich L. Bauer)和艾兹格·迪科斯彻在1960年代早期提议用于表达式求值,以利用堆栈结构减少计算机内存访问。逆波兰记法和相应的算法由澳大利亚哲学家、计算机学家查尔斯·汉布林(Charles Hamblin)在1960年代中期扩充。 在1960和1970年代,逆波兰记法广泛地被用于台式计算器,因此也在普通公众(工程、商业和金融领域)中使用。 下面大部分是关于二元运算,一个一元运算使用逆波兰记法的例子是阶乘的记法。 二、中缀表达式到前缀和后缀表达式转换过程 波兰表示法(中缀表达式转换成前缀表达式算法)
- 首先设定一个操作符栈,从右到左顺序扫描整个中缀表达式,如果是操作数,则直接归入前缀表达式;
- 如果是操作符,则检测器是否是右括号,如果是右括号,则直接将其入栈;
- 如果是左括号,则将栈中的操作符依次弹栈,归入前缀表达式,直至遇到右括号,将右括号弹栈,处理结束;
- 如果是其他操作符,则检测栈顶操作符的优先级与当前操作符的优先级关系,
- 如果栈顶操作符优先级大于当前操作符的优先级,则弹栈,并归入前缀表达式,直至栈顶操作符优先级小于等于当前操作符优先级,这时将当前操作符压栈。
- 当扫描完毕整个中缀表达式后,检测操作符栈是否为空,如果不为空,则依次将栈中操作符弹栈,归入前缀表达式。最后,将前缀表达式翻转,得到中缀表达式对应的前缀表达式。
逆波兰表示法(中缀表达式转换成后缀表达式算法)
- 从左至右扫描一中缀表达式;
- 若读取的是操作数,则判断该操作数的类型,并将该操作数存入操作数堆栈;
- 若读取的是运算符:
1. 该运算符为左括号"(",则直接存入运算符堆栈;
2. 该运算符为右括号")",则输出运算符堆栈中的运算符到操作数堆栈,直到遇到左括号为止;
3.该运算符为非括号运算符:
(1) 若运算符堆栈栈顶的运算符为括号,则直接存入运算符堆栈。
(2) 若比运算符堆栈栈顶的运算符优先级高或相等,则直接存入运算符堆栈。
(3) 若比运算符堆栈栈顶的运算符优先级低,则输出栈顶运算符到操作数堆栈,并将当前运算符压入运算符堆栈
- 当表达式读取完成后运算符堆栈中尚有运算符时,则依序取出运算符到操作数堆栈,直到运算符堆栈为空。
三、 对波兰表达式和逆波兰表达式求解过程 波兰表示法
- 从右到左依次扫描语法单元的项目。
- 如果扫描的项目是操作数,则将其压入操作数堆栈,并扫描下一个项目。
- 如果扫描的项目是一个二元运算符,则对栈的顶上两个操作数执行该运算。
- 如果扫描的项目是一个一元运算符,则对栈的最顶上操作数执行该运算。
- 将运算结果重新压入堆栈。
- 重复步骤第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 ''