python - 如何在 python tkinter 中正确实现冒泡排序算法?
问题描述
我正在写一系列关于排序算法的文章,第一部分是关于冒泡排序的,我有 GUI 元素,但是排序算法本身不能正常工作。它随机交换一系列不同长度的行,但排序没有按预期工作。它是用 python Tkinter 编写的,我认为主要问题来自我如何编程排序,比如两个列表,一个在屏幕上,一个在内存上。如果您也可以向我解释我的错误,那将会很有帮助。
import tkinter as tk
import random
def swap_two_pos(pos_0, pos_1):
"""This does the graphical swapping of the rectangles on the canvas
by moving one rectangle to the location of the other, and vice versa
"""
x_00, _, x_01, _ = canvas.coords(pos_0)
x_10, _, x_11, _ = canvas.coords(pos_1)
# moves each rectangle to the x position of the other; y remains unchanged
canvas.move(pos_0, x_10-x_00, 0)
canvas.move(pos_1, x_01-x_11, 0)
def sort_two(pos_0, pos_1):
x_00, y1, x_01, _ = canvas.coords(pos_0)
x_10, y2, x_11, _ = canvas.coords(pos_1)
# moves each rectangle to the x position of the other; y remains unchanged
if y2 > y1:
canvas.move(pos_0, x_10-x_00, 0)
canvas.move(pos_1, x_01-x_11, 0)
def rand_sort():
for i in range(50000):
rd1 = random.randint(0, 58)
rd2 = random.randint(0, 58)
pos_1 = barList[rd1]
pos_2 = barList[rd2]
sort_two(pos_1, pos_2)
barList[rd1], barList[rd2] = barList[rd2], barList[rd1]
def sort ():
n = len(barList)
# Traverse through all array elements
for i in range(n):
# Last i elements are already in place
for j in range(0, n-i-1):
sort_two(barList[j], barList[j+1])
barList[j], barList[j+1] = barList[j+1], barList[j]
else:
break
def random_swap():
"""Not a sort yet, but you have the bare bones operations
so the swap is executed
"""
for i in range(500):
rd1 = random.randint(0, 58)
rd2 = random.randint(0, 58)
pos_0 = barList[rd1]
pos_1 = barList[rd2]
swap_two_pos(pos_0, pos_1)
# it is necessary to swap the values in the list too
barList[rd1], barList[rd2] = barList[rd2], barList[rd1]
window = tk.Tk()
window.title('Sorting')
window.geometry('600x400')
# button to command the swap
tk.Button(window, text='swap', command=random_swap).pack()
tk.Button(window, text='sort', command=sort).pack()
xstart = 5
xend = 15
canvas = tk.Canvas(window, width='900', height='900')
canvas.pack()
barList = []
lengthList = []
Y = 5
for x in range(1,60):
bar = canvas.create_rectangle(xstart, Y, xend, 395, fill='red')
barList.append(bar)
xstart += 10
xend += 10
Y += 5
for bar in barList:
x = canvas.coords(bar)
length = x[3]-x[1]
lengthList.append(length)
window.mainloop()
解决方案
最大的问题是sort_two
你里面有if
if y2 > y1:
canvas.move(pos_0, x_10-x_00, 0)
canvas.move(pos_1, x_01-x_11, 0)
仅在以下情况下替换元素y2 > y1
但是在sort_two()
你使用之后barList
sort_two(pos_1, pos_2)
barList[rd1], barList[rd2] = barList[rd2], barList[rd1]
它总是替换列表中的元素。
这样你在屏幕上就会得到错误的结果。
您可以返回True/False
以sort_two()
控制何时更改元素barList
if y2 > y1:
canvas.move(pos_0, x_10-x_00, 0)
canvas.move(pos_1, x_01-x_11, 0)
return True
else:
return False
和
if sort_two(pos_1, pos_2):
barList[rd1], barList[rd2] = barList[rd2], barList[rd1]
这里最终代码
我使用简单的计算来替换画布上的元素
x1, _, _, _ = canvas.coords(pos_0)
x2, _, _, _ = canvas.coords(pos_1)
diff = x1 - x2
canvas.move(pos_0, -diff, 0)
canvas.move(pos_1, +diff, 0)
我也删了
else:
break
每次替换后都会停止动画,并且需要sort
一次又一次地单击按钮-我使用
window.update()
time.sleep(0.1)
所以它会(慢慢地)显示动画到排序结束,我不必点击按钮sort
import tkinter as tk
import random
import time
def swap_two_pos(pos_0, pos_1):
"""This does the graphical swapping of the rectangles on the canvas
by moving one rectangle to the location of the other, and vice versa
"""
x1, _, _, _ = canvas.coords(pos_0)
x2, _, _, _ = canvas.coords(pos_1)
diff = x1 - x2
canvas.move(pos_0, -diff, 0)
canvas.move(pos_1, +diff, 0)
def sort_two(pos_0, pos_1):
x1, y1, _, _ = canvas.coords(pos_0)
x2, y2, _, _ = canvas.coords(pos_1)
diff = x1 - x2
# moves each rectangle to the x position of the other; y remains unchanged
if y2 > y1:
canvas.move(pos_0, -diff, 0)
canvas.move(pos_1, +diff, 0)
return True
else:
return False
def rand_sort():
for i in range(50000):
rd1 = random.randint(0, 58)
rd2 = random.randint(0, 58)
pos_1 = barList[rd1]
pos_2 = barList[rd2]
if sort_two(pos_1, pos_2):
barList[rd1], barList[rd2] = barList[rd2], barList[rd1]
def sort ():
n = len(barList)
# Traverse through all array elements
for i in range(n):
# Last i elements are already in place
for j in range(0, n-i-1):
if sort_two(barList[j], barList[j+1]):
barList[j], barList[j+1] = barList[j+1], barList[j]
window.update()
time.sleep(0.1)
def random_swap():
"""Not a sort yet, but you have the bare bones operations
so the swap is executed
"""
for i in range(500):
rd1 = random.randint(0, 58)
rd2 = random.randint(0, 58)
pos_0 = barList[rd1]
pos_1 = barList[rd2]
swap_two_pos(pos_0, pos_1)
# it is necessary to swap the values in the list too
barList[rd1], barList[rd2] = barList[rd2], barList[rd1]
window = tk.Tk()
window.title('Sorting')
window.geometry('600x400')
# button to command the swap
tk.Button(window, text='swap', command=random_swap).pack()
tk.Button(window, text='sort', command=sort).pack()
xstart = 5
xend = 15
canvas = tk.Canvas(window, width='900', height='900')
canvas.pack()
barList = []
lengthList = []
Y = 5
for x in range(1,60):
bar = canvas.create_rectangle(xstart, Y, xend, 395, fill='red')
barList.append(bar)
xstart += 10
xend += 10
Y += 5
for bar in barList:
x = canvas.coords(bar)
length = x[3]-x[1]
lengthList.append(length)
window.mainloop()
推荐阅读
- android - 在 FirebaseMessagingService 中收到消息时弹出消息
- android - 遍历 Firestore 以获取文档 ID
- django - Heroku Django 部署成功,但应用程序 url 显示“应用程序错误”
- javascript - 具有多个字段的 Mongoose 查询文档,包括子字段 Mongodb
- node.js - 快递:快递——除非打破简单的例子
- ios - iOS 应用内购买卡在“正在购买”状态
- reactjs - 即使我设置了环境变量,Reg 也无法识别
- javascript - 变量未从异步函数更新/承诺未提供最终变量
- python - 减少由于 Azure Databricks 中 GC 分配失败而导致的时间延迟的步骤
- hyperledger-fabric - 运行时执行期间出现意外信号 [信号 SIGSEGV:分段违规 ..] 创建通道时