本文的代码适用于多位数的中缀转后缀可用于多括号的计算!
但是暂时无法计算除小括号外的其他括号的计算与转换!
中缀转后缀是一种常见的算法,用于将中缀表达式转换为后缀表达式,也称为逆波兰表达式。后缀表达式更容易计算和理解,因此在计算机科学中经常用于表达算术表达式。
中缀转后缀的一种常见方法是使用栈来实现。具体步骤如下:
- 创建一个操作符栈和一个结果列表。
- 从左到右扫描中缀表达式的每个元素。
- 如果是操作数,则直接加入结果列表。
- 如果是操作符,则判断其优先级:
- 如果操作符的优先级大于栈顶操作符的优先级,直接入栈。
- 如果操作符的优先级小于等于栈顶操作符的优先级,则将栈顶操作符出栈,加入结果列表,重复此步骤直到栈为空或者栈顶操作符的优先级小于当前操作符的优先级。
- 最后将栈中剩余的操作符依次出栈,加入结果列表。
注:本文章可用于计算的计算函数,可自行创造其他的计算函数进行转换与计算。
# 用于测试的计算函数
# 2*(9+6/3-5)+4
# ((12+6)*5+4)*6
# 6*(((12+6)*5+48)*27+90)
# 8/4*9+6*(((12+6)*5+48)*27+90)
一、中缀转后缀函数的代码
def zhuan_huan(b):
infix = str(b) # 转化为字符串
jk = len(infix) # 计算中缀的长度
ii = 0 # 定义一个参数
stack = [] # 堆栈的空列表
postfix = [] # 后缀的空列表
zhan_postfix = [] # 后缀的暂存空列表
pan_duan = {'+': 1, '-': 1, '*': 2, '/': 2} # 建立字典
cd = 0 # 定义一个参数
for char in infix: # 从中缀中的第一个字符读取
if char.isalnum(): # 判断是否包含字母和数字字符,是的话则成立
cd += 1 # 对cd进行累加
zhan_postfix.append(char) # 将char写入暂存列表
elif char == '(': # 判断是否为左括号
stack.append(char) # 将char写入堆栈的列表
cd = 0 # 将cd从新定义等于0
elif char == ')': # 判断是否为右括号
while stack[-1] != '(': # 判断堆栈的最后一个元素是否为左括号
if cd == int(1):
postfix.append(''.join(zhan_postfix)) # 将zhan_postfix列表的元素相加然后写入postfix列表
del zhan_postfix[:] # 清空zhan_postfix列表
elif cd >= 2:
if len(zhan_postfix) != 0: # 判断zhan_postfix列表长度等不等于0
ss = ''.join(zhan_postfix) # 将zhan_postfix列表的元素相加然后赋予ss
del zhan_postfix[:] # 清空zhan_postfix列表
postfix.append(ss) # 将ss写入postfix列表
postfix.append(stack.pop()) # 将stack列表的栈顶写入postfix列表
stack.pop() # stack列表的栈顶出栈
cd = 0 # 将cd从新定义等于0
else:
while stack and pan_duan.get(stack[-1], 0) >= pan_duan.get(char, 0): # 判断stack列表的最后一个元素在pan_duan的字典与char在在pan_duan的字典的大小比较
if cd == int(1):
postfix.append(''.join(zhan_postfix)) # 将zhan_postfix列表的元素相加然后写入postfix列表
del zhan_postfix[:] # 清空zhan_postfix列表
elif cd >= 2:
if len(zhan_postfix) != int(0): # 判断zhan_postfix列表长度等不等于0
ss = ''.join(zhan_postfix) # 将zhan_postfix列表的元素相加然后赋予ss
del zhan_postfix[:] # 清空zhan_postfix列表
postfix.append(ss) # 将ss写入postfix列表
postfix.append(stack.pop()) # 将stack列表的栈顶写入postfix列表
if cd == int(1):
postfix.append(''.join(zhan_postfix)) # 将zhan_postfix列表的元素相加然后写入postfix列表
del zhan_postfix[:] # 清空zhan_postfix列表
elif cd >= 2:
if len(zhan_postfix) != int(0): # 判断zhan_postfix列表长度等不等于0
ss = ''.join(zhan_postfix) # 将zhan_postfix列表的元素相加然后赋予ss
del zhan_postfix[:] # 清空zhan_postfix列表
postfix.append(ss) # 将ss写入postfix列表
stack.append(char) # 将char写入堆栈的列表
cd = 0 # 将cd从新定义等于0
for i in range(jk):
ii += 1
if ii == jk:
ss = ''.join(zhan_postfix) # 将zhan_postfix列表的元素相加然后赋予ss
del zhan_postfix[:] # 清空zhan_postfix列表
postfix.append(ss)
while stack:
postfix.append(stack.pop())
a = ' '.join(postfix) # 将zhan_postfix列表的元素相加然后赋予a
print(a)
return a #返回a
二、后缀函数的计算代码
在后缀计算时如果存在多位数则输入时最后数与数之间、数与计算符号之间加多一个空格符,因为本文暂时 还无法解决此问题,例如“7189+”这个简单的后缀相加,可以有71+89,可以有7+189等,如果输入的是“718 9 +”,这718与9之间有空格符则电脑容易识别718+9然后进行运算。
def jisuan(a):
postfix = str(a) # 转化为字符串
shu = [] # 定义空列表——>数字的列表
fuhao = [] # 定义空列表——>计算符号的列表
for char in postfix.split():
if char.isdigit(): # 判断是否是数字,是的话则成立
shu.append(char) # 将char写入shu列表
else:
fuhao.append(char) # 将char写入fuhao列表
if len(fuhao) == 1: # 判断fuhao列表长度是否为1
a = str(shu.pop()) # 将shu列表的最后一个元素给予a,并转换为str型
b = str(fuhao.pop()) # 将fuhao列表的最后一个元素给予b,并转换为str型
c = str(shu.pop()) # 将shu列表的倒数第二个元素给予c,并转换为str型
han = c + b + a # 字符合成,形成han函数
ji_suan = eval(han) # 运算han函数
shu.append(ji_suan) # 将运算后的han函数写入到shu列表
d = shu.pop() # 将shu列表的最后一个元素给予d,即将最后计算的结果给予d
print(d)
return d # 返回d
三、创建GUI界面用于方便使用及美化
from tkinter import * # 导入tkinter库
root = Tk()
root.geometry("300x200+600+300") # 定义界面的大小位置
root.title("中缀与后缀") # 给界面起名
root.resizable(False, False) # 让界面无法放大
root.wm_attributes("-topmost", 1) # 让界面始终在电脑屏幕表面
def zhuan():
infix = str(entry.get())
b = str(zhuan_huan(infix))
label3.config(text=b)
def zhuan1():
infix = str(entry.get())
postfix = str(zhuan_huan(infix))
x = jisuan(postfix)
label5.config(text=x)
def jisuan1():
postfix = str(entry1.get())
y = jisuan(postfix)
label8.config(text=y)
entry = Entry(root)
entry.place(x=130, y=25)
entry1 = Entry(root)
entry1.place(x=130, y=100)
label1 = Label(root, text="请输入中缀表达式:", fg='blue')
label1.place(x=20, y=25)
label2 = Label(root, text="后缀表达式:", fg='blue')
label2.place(x=20, y=50)
label3 = Label(root, text="", fg='black')
label3.place(x=130, y=50)
label4 = Label(root, text="后缀计算结果:", fg='blue')
label4.place(x=20, y=75)
label5 = Label(root, text="", fg='black')
label5.place(x=130, y=75)
label6 = Label(root, text="请输入后缀表达式:", fg='blue')
label6.place(x=20, y=100)
label7 = Label(root, text="直接计算后缀结果:", fg='blue')
label7.place(x=20, y=125)
label8 = Label(root, text="", fg='black')
label8.place(x=130, y=125)
button = Button(root, text="开始中缀转后缀", fg='red', command=zhuan)
button.place(x=10, y=150)
button1 = Button(root, text="中缀转后缀计算", fg='red', command=zhuan1)
button1.place(x=110, y=150)
button2 = Button(root, text="后缀直接计算", fg='red', command=jisuan1)
button2.place(x=210, y=150)
root.mainloop()
四、完整代码
from tkinter import * # 导入tkinter库
# 用于测试的计算函数
# 2*(9+6/3-5)+4
# ((12+6)*5+4)*6
# 6*(((12+6)*5+48)*27+90)
# 8/4*9+6*(((12+6)*5+48)*27+90)
root = Tk()
root.geometry("300x200+600+300") # 定义界面的大小位置
root.title("中缀与后缀") # 给界面起名
root.resizable(False, False) # 让界面无法放大
root.wm_attributes("-topmost", 1) # 让界面始终在电脑屏幕表面
def zhuan_huan(b):
infix = str(b) # 转化为字符串
jk = len(infix) # 计算中缀的长度
ii = 0 # 定义一个参数
stack = [] # 堆栈的空列表
postfix = [] # 后缀的空列表
zhan_postfix = [] # 后缀的暂存空列表
pan_duan = {'+': 1, '-': 1, '*': 2, '/': 2} # 建立字典
cd = 0 # 定义一个参数
for char in infix: # 从中缀中的第一个字符读取
if char.isalnum(): # 判断是否包含字母和数字字符,是的话则成立
cd += 1 # 对cd进行累加
zhan_postfix.append(char) # 将char写入暂存列表
elif char == '(': # 判断是否为左括号
stack.append(char) # 将char写入堆栈的列表
cd = 0 # 将cd从新定义等于0
elif char == ')': # 判断是否为右括号
while stack[-1] != '(': # 判断堆栈的最后一个元素是否为左括号
if cd == int(1):
postfix.append(''.join(zhan_postfix)) # 将zhan_postfix列表的元素相加然后写入postfix列表
del zhan_postfix[:] # 清空zhan_postfix列表
elif cd >= 2:
if len(zhan_postfix) != 0: # 判断zhan_postfix列表长度等不等于0
ss = ''.join(zhan_postfix) # 将zhan_postfix列表的元素相加然后赋予ss
del zhan_postfix[:] # 清空zhan_postfix列表
postfix.append(ss) # 将ss写入postfix列表
postfix.append(stack.pop()) # 将stack列表的栈顶写入postfix列表
stack.pop() # stack列表的栈顶出栈
cd = 0 # 将cd从新定义等于0
else:
while stack and pan_duan.get(stack[-1], 0) >= pan_duan.get(char, 0): # 判断stack列表的最后一个元素在pan_duan的字典与char在在pan_duan的字典的大小比较
if cd == int(1):
postfix.append(''.join(zhan_postfix)) # 将zhan_postfix列表的元素相加然后写入postfix列表
del zhan_postfix[:] # 清空zhan_postfix列表
elif cd >= 2:
if len(zhan_postfix) != int(0): # 判断zhan_postfix列表长度等不等于0
ss = ''.join(zhan_postfix) # 将zhan_postfix列表的元素相加然后赋予ss
del zhan_postfix[:] # 清空zhan_postfix列表
postfix.append(ss) # 将ss写入postfix列表
postfix.append(stack.pop()) # 将stack列表的栈顶写入postfix列表
if cd == int(1):
postfix.append(''.join(zhan_postfix)) # 将zhan_postfix列表的元素相加然后写入postfix列表
del zhan_postfix[:] # 清空zhan_postfix列表
elif cd >= 2:
if len(zhan_postfix) != int(0): # 判断zhan_postfix列表长度等不等于0
ss = ''.join(zhan_postfix) # 将zhan_postfix列表的元素相加然后赋予ss
del zhan_postfix[:] # 清空zhan_postfix列表
postfix.append(ss) # 将ss写入postfix列表
stack.append(char) # 将char写入堆栈的列表
cd = 0 # 将cd从新定义等于0
for i in range(jk):
ii += 1
if ii == jk:
ss = ''.join(zhan_postfix) # 将zhan_postfix列表的元素相加然后赋予ss
del zhan_postfix[:] # 清空zhan_postfix列表
postfix.append(ss)
while stack:
postfix.append(stack.pop())
a = ' '.join(postfix) # 将zhan_postfix列表的元素相加然后赋予a
print(a)
return a #返回a
def jisuan(a):
postfix = str(a) # 转化为字符串
shu = [] # 定义空列表——>数字的列表
fuhao = [] # 定义空列表——>计算符号的列表
for char in postfix.split():
if char.isdigit(): # 判断是否是数字,是的话则成立
shu.append(char) # 将char写入shu列表
else:
fuhao.append(char) # 将char写入fuhao列表
if len(fuhao) == 1: # 判断fuhao列表长度是否为1
a = str(shu.pop()) # 将shu列表的最后一个元素给予a,并转换为str型
b = str(fuhao.pop()) # 将fuhao列表的最后一个元素给予b,并转换为str型
c = str(shu.pop()) # 将shu列表的倒数第二个元素给予c,并转换为str型
han = c + b + a # 字符合成,形成han函数
ji_suan = eval(han) # 运算han函数
shu.append(ji_suan) # 将运算后的han函数写入到shu列表
d = shu.pop() # 将shu列表的最后一个元素给予d,即将最后计算的结果给予d
print(d)
return d # 返回d
def zhuan():
infix = str(entry.get())
b = str(zhuan_huan(infix))
label3.config(text=b)
def zhuan1():
infix = str(entry.get())
postfix = str(zhuan_huan(infix))
x = jisuan(postfix)
label5.config(text=x)
def jisuan1():
postfix = str(entry1.get())
y = jisuan(postfix)
label8.config(text=y)
entry = Entry(root)
entry.place(x=130, y=25)
entry1 = Entry(root)
entry1.place(x=130, y=100)
label1 = Label(root, text="请输入中缀表达式:", fg='blue')
label1.place(x=20, y=25)
label2 = Label(root, text="后缀表达式:", fg='blue')
label2.place(x=20, y=50)
label3 = Label(root, text="", fg='black')
label3.place(x=130, y=50)
label4 = Label(root, text="后缀计算结果:", fg='blue')
label4.place(x=20, y=75)
label5 = Label(root, text="", fg='black')
label5.place(x=130, y=75)
label6 = Label(root, text="请输入后缀表达式:", fg='blue')
label6.place(x=20, y=100)
label7 = Label(root, text="直接计算后缀结果:", fg='blue')
label7.place(x=20, y=125)
label8 = Label(root, text="", fg='black')
label8.place(x=130, y=125)
button = Button(root, text="开始中缀转后缀", fg='red', command=zhuan)
button.place(x=10, y=150)
button1 = Button(root, text="中缀转后缀计算", fg='red', command=zhuan1)
button1.place(x=110, y=150)
button2 = Button(root, text="后缀直接计算", fg='red', command=jisuan1)
button2.place(x=210, y=150)
root.mainloop()
希望本文章能帮助到你们,谢谢观看!