引言
输入运算表达式,仅由数字、+、-、*、/、()组成,没有空格,要求求其值,
中缀表达式:通常看到的表达式中,操作符介于操作数中间的表示法,如A+B,BC,A+BC(容易混淆)。为了避免混淆,引入优先级或者括号来定义顺序。(A+B)C
前缀表达式:将操作移动到前面的表示法,如+AB, * +ABC
后缀表达式:将操作移动到后面的表示法,如AB+,AB+C
因此,(A+B)*C转化为AB+C *和 * +ABC时括号消失,因此可将中缀表达式转化为前缀或者后缀,消除运算的次序,不在有混淆。
1.通用的中缀转后缀算法原理
从左到右扫描后缀表达式
1.若是操作数,就压栈,直接添加到后缀表达式列表的末尾。
2.若是左括号“(”,则压入栈顶,若是“)”,则反复弹出栈顶操作符,加入到输出列表末尾,直到碰到左括号
2.若是操作符,“*/±”,则压入栈顶,并连续弹出两个操作数,根据操作符计算两个操作数,最后把计算结果再次压到栈顶,
3.栈顶的值即为计算最终结果
输出后缀过程:
2.通用中缀转后缀算法实现
2.1 定义栈及其属性
class Stack(object): #定义栈 属性
"""栈"""
def __init__(self):
self.items = []
def is_empty(self):
"""判断是否为空"""
return self.items == []
def push(self, item):
"""加入元素"""
self.items.append(item)
def pop(self):
"""弹出元素"""
return self.items.pop()
def peek(self):
"""返回栈顶元素"""
return self.items[len(self.items)-1]
def size(self):
"""返回栈的大小"""
return len(self.items)
2.2 中缀转后缀代码
def infixtopostfix(infixexpr): ## 通用中缀表达式转化为后缀表达式
prec={} #记录操作符优先级
prec["*"]=3
prec["/"]=3
prec["+"]=2
prec["-"]=2
prec["("]=1
opstack=Stack()
postfixlist=[]
tokenlist=infixexpr.split() #解析式转换为单词列表
for token in tokenlist:
if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789":
postfixlist.append(token)
elif token=='(':
opstack.push(token)
elif token==')':
toptoken=opstack.pop()
while toptoken !='(':
postfixlist.append(toptoken)
toptoken=opstack.pop()
else: ##操作符
while (not opstack.is_empty()) and \
(prec[opstack.peek()]>=prec[token]):
postfixlist.append(opstack.pop())
opstack.push(token)
while not opstack.is_empty(): #返回后缀表示式字符串
postfixlist.append(opstack.pop())
return postfixlist
注:此处输出表示式字符串为空,后续修正
3. 后缀表达式求值
3.1 求值过程原理
(1)创建空栈用于暂存操作数
(2)将后缀表达式用split方法解析为单词token的列表
(3)从左到右扫描单词列表
(a)若单词为操作数,将单词转为整型int,压入栈顶
(b)若单词为操作符,就从栈顶弹出两操作符并计算其值,压入栈顶
(4)单词列表扫描完后,表达式的值就在栈顶,弹出并返回。
3.2 算法过程实现
def postfieval(postfixexpr):
operandstack=Stack()
tokenlist=postfixexpr.split()
for token in tokenlist:
if token in "0123456789":
operandstack.push(int(token))
else:
operand2=operandstack.pop()
operand1=operandstack.pop()
result=domath(token,operand1,operand2)
operandstack.push(result)
return operandstack.pop()
def domath (op,op1,op2):
if op =="*":
return op1*op2
elif op =="/":
return op1/op2
elif op == "+":
return op1+op2
else:
return op1-op2
最后要问的是有没有人知道转换过程中输出为空,我的代码在哪里出了bug?请在下面留言,感激不尽~