由于中缀表达式有括号的存在,其运算次序比较复杂,直接分析有些难度。先考虑不带括号的中缀表达式的转换。
由于运算符号具有不同的优先级,当前的运算符不能直接放在操作数的后面,需要考虑下一个运算符的优先级。
对比三个不同的中缀表达式转换为后缀表达式的结果
可以发现:
1.后缀表达式数字的出现顺序和中缀表达式中是完全一样的。
2.中缀表达式中相邻两个运算符的优先级不一样,其在后缀表达式中的位置也不一样。其规则是,如果当前运算符优先级大于等于下个运算符优先级,将该运算符写后操作数后面。否则记下该运算符,在之后写上。
可以利用栈后进先出的特点来临时存运算符号,用一个列表存后缀表达式的结果。以
为例,演示转换的思路:
对于带有括号的中缀表达式的转换,个人理解应该将两括号之间的部分看做一个整体。遇到 ( 应压入栈,在他之后的运算符同样按照上图所示规则压入栈,直到遇到 ),表示该部分结束,应该栈里 ( 上面的所有运算符弹出。
def tokens(exp):
"""生成器函数。将输入的中缀表达式拆成一个个的项返回。但不能处理一元运算符和负数"""
operators="+-*/()"
i,n=0,len(exp)
while i<n:
if exp[i] in operators:
yield exp[i]
i+=1
else:
if exp[i]==" ": #遇到空格跳过
i+=1
continue
else:
if i+1>=n or exp[i+1]==" " or exp[i+1] in operators: #数字后结束,或者是空格或运算符,直接加入
yield exp[i]
i+=1
continue
j=i
while i+1<n and exp[i+1] not in operators and exp[i+1]!=" ": #数字后是数字(小数点也可以),取数字部分切片加入
i+=1
yield exp[j:i+1]
i+=1
def trans_infix_suffix(line):
priority={"(":0,"+":1,"-":1,"*":2,"/":2} #操作优先级,"("优先级最低
operators="+-*/()"
st=SStack()
exp=[]
for x in line:
if x not in operators: #是数字直接加入
exp.append(x)
else:
if st.is_empty() or st.top()=="(" or x=="(": #如果栈为空,或栈顶为(,或x是(,直接入栈
st.push(x)
elif x==")": #如果x是),弹出元素,直到栈顶为(
while st.top()!="(":
exp.append(st.pop())
st.pop()
elif priority[x]<=priority[st.top()]: #如果x是四则运算符,优先级小于等于栈顶元素,弹出栈顶元素,x入栈。否则直接入栈
exp.append(st.pop())
st.push(x)
else:
st.push(x)
while not st.is_empty(): #将栈里剩下元素弹出
exp.append(st.pop())
return exp
if __name__ == '__main__':
exp=input("输入表达式:\n")
suffix=trans_infix_suffix(tokens(exp))
print(suffix)
测试结果:
输入表达式:
5*3*(4+6*7)*(1+1)
['5', '3', '*', '4', '6', '7', '*', '+', '*', '1', '1', '+', '*']