如何在python tkinter中正确实现气泡排序算法?

2024-05-12 18:03:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在写一系列关于排序算法的文章,第一部分是关于气泡排序,我已经准备好了GUI元素,但是排序算法本身不能正常工作。它随机交换一系列不同长度的行,但排序没有按预期工作。它是用PythonTkinter编写的,我想主要的问题来自于我如何编程排序,比如两个列表,一个在屏幕上,一个在内存上。如果你也能向我解释一下我的错误,那会很有帮助的

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()

Tags: theinposfor排序defrandomwindow
1条回答
网友
1楼 · 发布于 2024-05-12 18:03:23

enter image description here

最大的问题是在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]

它总是替换列表中的元素

这样你们在屏幕上就有了错误的结果

您可以从sort_two()返回True/False,以控制何时更改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()

相关问题 更多 >