前缀表达式、中缀表达式、后缀表达式及转换实现
前缀表达式
前缀表达式就是不含括号的算术表达式,而且它是将运算符写在前面,操作数写在后面的表达式,为纪念其发明者波兰数学家Jan
Lukasiewicz也称为“波兰式”。例如,- 1 + 2 3,它等价于1-(2+3)。复杂一点的(1+2)*4-(9-6)/3,前缀表达式为 - * + 1 2 4 / - 9 6 3
前缀表达式是一种十分有用的表达式,它将中缀表达式转换为可以依靠简单的操作就能得到运算结果的表达式。例如,(a+b)*(c+d)转换为*,+,a,b,+,c,d。它的优势在于只用两种简单的操作,入栈和出栈就可以解决任何中缀表达式的运算。其运算方式为:如果当前字符(或字符串)为数字或变量,则压入栈内;如果是运算符,则将栈顶两个元素弹出栈外并作相应运算,再将结果压入栈内。当前缀表达式扫描结束时,栈里的就是中缀表达式运算的最终结果。
求值:
对于一个前缀表达式的求值而言,首先要从右至左扫描表达式,从右边第一个字符开始判断,如果当前字符是数字则一直到数字串的末尾再记录下来,如果是运算符,则将右边离得最近的两个“数字串”作相应的运算,以此作为一个新的“数字串”并记录下来。一直扫描到表达式的最左端时,最后运算的值也就是表达式的值。例如,前缀表达式“-
1 + 2 3“的求值,扫描到3时,记录下这个数字串,扫描到2时,记录下这个数字串,当扫描到+时,将+右移做相邻两数字串的运算符,记为2+3,结果为5,记录下这个新数字串,并继续向左扫描,扫描到1时,记录下这个数字串,扫描到-时,将-右移做相邻两数字串的运算符,记为1-5,结果为-4,所以表达式的值为-4。
中缀表达式
(或中缀记法)是一个通用的算术或逻辑公式表示方法, 操作符是以中缀形式处于操作数的中间(例:3 + 4),中缀表达式是人们常用的算术表示方法。与前缀表达式(例:+ 3 4)或后缀表达式(例:3 4 +)相比,中缀表达式不容易被计算机解析,但仍被许多程序语言使用,因为它符合人们的普遍用法。与前缀或后缀记法不同的是,中缀记法中括号是必需的。计算过程中必须用括号将操作符和对应的操作数括起来,用于指示运算的次序。
例:
(1)8+4-6*2用后缀表达式表示为:
84+62*-
(2)2*(3+5)-4+7/1用后缀表达式表示为:
235+*4-71/+
后缀表达式
不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,如:(2 + 1) * 3 , 即2 1 + 3 *
运用后缀表达式进行计算的具体做法:
建立一个栈S 。从左到右读后缀表达式,如果读到操作数就将它压入栈S中,如果读到n元运算符(即需要参数个数为n的运算符)则取出由栈顶向下的n项按操作符运算,再将运算的结果代替原栈顶的n项,压入栈S中 。如果后缀表达式未读完,则重复上面过程,最后输出栈顶的数值则为结束。
===================================================
中缀表达式==》前缀表达式:
(1) 首先构造一个运算符栈(也可放置括号),运算符(以括号分界点)在栈内遵循越往栈顶优先级不降低的原则进行排列。
(2)从右至左扫描中缀表达式,从右边第一个字符开始判断:
如果当前字符是数字,则分析到数字串的结尾并将数字串直接输出。
如果是运算符,则比较优先级。如果当前运算符的优先级大于等于栈顶运算符的优先级(当栈顶是括号时,直接入栈),则将运算符直接入栈;否则将栈顶运算符出栈并输出,直到当前运算符的优先级大于等于栈顶运算符的优先级(当栈顶是括号时,直接入栈),再将当前运算符入栈。
如果是括号,则根据括号的方向进行处理。如果是右括号,则直接入栈;否则,遇左括号前将所有的运算符全部出栈并输出,遇左括号后将左右的两括号一起删除。
(3) 重复上述操作(2)直至扫描结束,将栈内剩余运算符全部出栈并输出,再逆缀输出字符串。中缀表达式也就转换为前缀表达式了。
中缀表达式==》后缀表达式:计算机实现转换:
将中缀表达式转换为后缀表达式的算法思想:
·开始扫描;
·数字时,加入后缀表达式;
·运算符:
a. 若为 '(',入栈;
b. 若为 ')',则依次把栈中的的运算符加入后缀表达式中,直到出现'(',从栈中删除'(' ;
·当扫描的中缀表达式结束时,栈中的的所有运算符出栈;
附中缀转后缀表达式代码:
代码(一)
貌似写的时候一开始转为后缀前没有用自己写的PyStack.py和PyQueue.py,在解析后缀表达式时才用到这两个类。
# -*- coding: utf8 -*- """ 四则运算 5+(23-2*3)/2*5 """ from __future__ import division from util.PyStack import PyStack from util.PyQueue import PyQueue #stack=PyStack() #queue=PyQueue() #print stack.stackSize() #print queue.queueEnd() def proStr(strr): str=[] strr.encode('utf-8') k=0 digit='' #print 'len(strr)',len(strr) while k<len(strr): if strr[k].isdigit() and k<len(strr): digit+=strr[k] if k==len(strr)-1: if digit!='': str.append(digit) digit='' if k<len(strr) and strr[k].isdigit()==False: if digit!='': str.append(digit) digit='' str.append(strr[k]) k=k+1 #print k #print 'str:',str return str def priority(str1,str2): ''' 判断运算符的优先级 if str1>str2: return True else: return Flase ''' if str1=='*' or str1=='/': return True elif str2=='+' or str2=='-': return False elif str2=='(' or str2=='(': return False elif (str1=='+' or str1=='-') and (str2=='*' or str2=='/'): return False def mid2pos(strr): ''' The nifix expression 222222222222222222222 The postfix expression ''' str=proStr(strr) numStack=[] prStack=[] strQueue=[] i=0 while i<len(str): if str[i].isdigit(): numStack.append(str[i]) strQueue.append(str[i]) elif str[i]=='(' or str[i]=='(': prStack.append(str[i]) elif str[i]==')' or str[i]==')': j=len(prStack) while j>0: if prStack[-1]!='(' or prStack[-1]!='(': pr=prStack[-1] #print 'prStack[-1]',prStack[-1] del prStack[-1] strQueue.append(pr) if prStack[-1]=='(' or prStack[-1]=='(': del prStack[-1] break j=j-1 else : if len(prStack)==0: prStack.append(str[i]) else: prTop=len(prStack) while prTop>0: pr=prStack[-1] if priority(pr,str[i]) and prTop>-1: strQueue.append(pr) del prStack[-1] prTop=prTop-1 else: prStack.append(str[i]) prTop=-1 i=i+1 jj=len(prStack) while jj>0: strQueue.append(prStack[-1]) del prStack[-1] jj=jj-1 #print 'numStack:',numStack #print 'prStack:',prStack #print 'strQueue:',strQueue return strQueue def operation(s1,s2,s3): result=0 if s3=='+': result=float(s1)+float(s2) elif s3=='-': result=float(s1)-float(s2) elif s3=='*': result=float(s1)*float(s2) elif s3=='/': result=int(s1)/int(s2) return result def explainThePosExp(str): expStack=PyStack() i=0 while i<len(str): if str[i].isdigit(): expStack.push(str[i]) else: s2=expStack.pop() s1=expStack.pop() res=operation(s1,s2,str[i]) #print 'res,',res expStack.push(res) i=i+1 result=expStack.pop() return result if __name__=="__main__": strr="5+(23-2*3)/2*5" print 'strr:',strr print "strr2pos",mid2pos(strr) print 'str',proStr(strr) print 'the result:',explainThePosExp(mid2pos(strr))代码(二)
PyStack.py和PyQueeue.py
# -*- coding:utf-8 -*- """ 写这个PyQueue,自己写的老是有问题,就从网上别人的改了一下。 放在util目录下 """ class PyQueue: # 创建队 def __init__(self, size = 20): self.queue = [] # 队 self.size = size # 队大小 self.end = -1 # 队尾 def setSize(self, size): # 设置队大小 self.size = size def In(self, element): # 入队 if self.end < self.size - 1: self.queue.append(element) self.end = self.end + 1 else: raise 'the queue is empty!' # 如果队满则引发异常 def Out(self): # 出队 if self.end != -1: element = self.queue[0] self.queue = self.queue[1:] self.end = self.end - 1 return element else: raise 'the queue is empty!' def isEmpty(self): if self.end==-1: return True else: return False def isFull(self): # 输出队尾 if self.end==self.size-1: return True else: return False def getEnd(self): return self.end def empty(self): # 清楚队 self.queue = [] self.end = -1 if __name__ == '__main__': queue = PyQueue() queue.In('a') print queue.Out()
# -*- coding: utf8 -*-
"""
__author__ = 'kuduogedi'
仿照网上程序,编写python的一个堆栈
size为堆栈大小
"""
class PyStack:
def __init__(self,size=50):
self.stack=[]
self.size=size
self.top=-1
def setSize(self,size):
self.size=size
def push(self,element):
if self.isFull():
raise 'the stack is full'
else:
self.stack.append(element)
self.top=self.top+1
def pop(self):
if self.isEmpty():
raise 'nothing in the stack'
else:
element=self.stack[-1]
self.top-=1
del self.stack[-1]
return element
def stackTop(self):#返回栈顶位置
return self.top
def inTop(self):
if self.isEmpty():
raise 'nothing in the stack'
else:
element=self.stack[-1]
return element
def stackSize(self):
return self.size
def clear(self):
self.stack=[]
self.top=-1
def isEmpty(self):
if self.top==-1:
return True
else:
return False
def isFull(self):
if self.top==self.size-1:
return True
else:
return False
if __name__=='__main__':
stack=PyStack()
stack.setSize(30)
stack.push('123')
print stack
s=stack
print stack.pop()
代码(三)
使用以上两个类写的
# -*- coding: utf8 -*- """ 5+(23-2*3)/2*5 """ from __future__ import division from util.PyStack import PyStack from util.PyQueue import PyQueue def proStr(strr): str=[] strr.encode('utf-8') k=0 digit='' #print 'len(strr)',len(strr) while k<len(strr): if strr[k].isdigit() and k<len(strr): digit+=strr[k] if k==len(strr)-1: if digit!='': str.append(digit) digit='' if k<len(strr) and strr[k].isdigit()==False: if digit!='': str.append(digit) digit='' str.append(strr[k]) k=k+1 #print k #print 'str:',str return str def priority(str1,str2): ''' 判断运算符的优先级 if str1>str2: return True else: return Flase ''' if str1=='*' or str1=='/': return True elif str2=='(' or str2=='(': return False elif str2=='+' or str2=='-': return False elif (str1=='+' or str1=='-') and (str2=='*' or str2=='/'): return False def mid2pos(strr): ''' The nifix expression 222222222222222222222 The postfix expression ''' str=proStr(strr) numStack=PyStack() prStack=PyStack() strStack=PyStack() strQueue=PyQueue() i=0 while i<len(str): if str[i].isdigit(): numStack.push(str[i]) strQueue.In(str[i]) elif str[i]=='(' or str[i]=='(': prStack.push(str[i]) elif str[i]==')' or str[i]==')': j=prStack.stackTop()+1 while j>0: pr=prStack.pop() if pr=='(' or pr=='(': j=-1 else: strQueue.In(pr) j=j-1 else : if prStack.isEmpty(): prStack.push(str[i]) else: prTop=prStack.stackSize()+1 #len(prStack) while prTop>0: if prStack.isEmpty()!=True: pr=prStack.pop() if priority(pr,str[i]) and prTop>-1: strQueue.In(pr) prTop=prTop-1 else: prStack.push(pr) prStack.push(str[i]) prTop=-1 prTop=prTop-1 i=i+1 jj=prStack.stackTop()+1 while jj>0: strQueue.In(prStack.pop()) jj=jj-1 return strQueue def operation(s1,s2,s3): result=0 if s3=='+': result=float(s1)+float(s2) elif s3=='-': result=float(s1)-float(s2) elif s3=='*': result=float(s1)*float(s2) elif s3=='/': result=float(s1)/float(s2) return result def explainThePosExp(str): expStack=PyStack() strQueue=str while strQueue.getEnd()>-1: pr=strQueue.Out() #print 'pr',pr if pr.isdigit(): expStack.push(pr) else: s2=expStack.pop() s1=expStack.pop() res=operation(s1,s2,pr) expStack.push(res) result=expStack.pop() return result if __name__=="__main__": strr="5+(23-2*3)/2*5" #strQueue=PyQueue() strQueue=mid2pos(strr) print 'strr:',strr while strQueue.getEnd()>-1: print strQueue.Out() #for i in range(1,strQueue) print 'the result:',explainThePosExp(mid2pos(strr))
写的比较水,学习的练手。