当前位置: 首页 > 面试题库 >

排序算法可视化:如何从紧密的循环内部拉取值以对画布进行动画处理

丌官盛
2023-03-14
问题内容

我正在使用tkinter使用不同条形的高度来可视化不同排序算法。我已经能够重新整理酒吧,并在得到一些帮助后对其进行排序。我现在遇到的问题是减慢条形的排序速度,因此可以看出每种算法的工作原理。这是我到目前为止的内容:

import tkinter as tk
import random

def swap_two_pos(pos_0, pos_1):
    Bar1x1, _, Bar1x2, _ = canvas.coords(pos_0)
    Bar2x1, _, Bar2x2, _ = canvas.coords(pos_1)
    canvas.move(pos_0, Bar2x1-Bar1x1, 0)
    canvas.move(pos_1, Bar1x2-Bar2x2, 0)


def insertion_sort():
    global barList
    global lengthList

    for i in range(len(lengthList)):
        cursor = lengthList[i]
        cursorBar = barList[i]
        pos = i

        while pos > 0 and lengthList[pos - 1] > cursor:
            lengthList[pos] = lengthList[pos - 1]
            barList[pos], barList[pos - 1] = barList[pos - 1], barList[pos]
            canvas.after(1000,swap_two_pos(barList[pos],barList[pos-1]))
            pos -= 1

        lengthList[pos] = cursor
        barList[pos] = cursorBar
        swap_two_pos(barList[pos],cursorBar)

def shuffle():
    global barList
    global lengthList
    canvas.delete('all')
    xstart = 5
    xend = 15
    barList = []
    lengthList = []

    for x in range(1,60):
        randomY = random.randint(1,390)
        x = canvas.create_rectangle(xstart,randomY,xend,395, fill='red')
        barList.append(x)
        xstart += 10
        xend += 10

    for bar in barList:
        x = canvas.coords(bar)
        length = x[3]-x[1]
        lengthList.append(length)

    for i in range(len(lengthList)-1):
        if lengthList[i] == min(lengthList):
            canvas.itemconfig(barList[i], fill='blue')
        elif lengthList[i] == max(lengthList):
            canvas.itemconfig(barList[i], fill='green')

window = tk.Tk()
window.title('Sorting')
window.geometry('600x435')
canvas = tk.Canvas(window, width='600', height='400')
canvas.grid(column=0,row=0, columnspan = 50)

insert = tk.Button(window, text='Insertion Sort', command=insertion_sort)
shuf = tk.Button(window, text='Shuffle', command=shuffle)
insert.grid(column=1,row=1)
shuf.grid(column=0, row=1)

shuffle()
window.mainloop()

如您所见,我尝试after()在插入排序函数中使用该方法,但是它所做的只是冻结窗口并使其不响应。如果没有该方法,它将无法正常工作,只是步伐不明显。


问题答案:

利用生成器函数(关键字yield),您可以暂停代码中间循环的执行,以花时间显示已更改的画布元素,更新计算等,然后在next反复调用生成器时恢复执行,直到排序完成。

我在代码中添加了一些注释,但是最好的方法可能是凝视它,直到您确信自己可以按预期工作为止。这是您需要了解的一种模式,因为它对构造您想要构建的动画非常有用。

import tkinter as tk
import random


def swap_two_pos(pos_0, pos_1):
    Bar1x1, _, Bar1x2, _ = canvas.coords(pos_0)
    Bar2x1, _, Bar2x2, _ = canvas.coords(pos_1)
    canvas.move(pos_0, Bar2x1-Bar1x1, 0)
    canvas.move(pos_1, Bar1x2-Bar2x2, 0)


def _insertion_sort():
    global barList
    global lengthList

    for i in range(len(lengthList)):
        cursor = lengthList[i]
        cursorBar = barList[i]
        pos = i

        while pos > 0 and lengthList[pos - 1] > cursor:
            lengthList[pos] = lengthList[pos - 1]
            barList[pos], barList[pos - 1] = barList[pos - 1], barList[pos]
            swap_two_pos(barList[pos],barList[pos-1])   # <-- updates the display
            yield                                       # <-- suspends the execution
            pos -= 1                                    # <-- execution resumes here when next is called

        lengthList[pos] = cursor
        barList[pos] = cursorBar
        swap_two_pos(barList[pos],cursorBar)


worker = None    # <-- Not a thread in spite of the name.

def insertion_sort():     # <-- commands the start of both the animation, and the sort
    global worker
    worker = _insertion_sort()
    animate()


def animate():      # <-- commands resuming the sort once the display has been updated
                    # controls the pace of the animation
    global worker
    if worker is not None:
        try:
            next(worker)
            window.after(10, animate)    # <-- repeats until the sort is complete,
        except StopIteration:            # when the generator is exhausted
            worker = None
        finally:
            window.after_cancel(animate) # <-- stop the callbacks


def shuffle():
    global barList
    global lengthList
    canvas.delete('all')
    xstart = 5
    xend = 15
    barList = []
    lengthList = []

    for x in range(1, 60):
        randomY = random.randint(1, 390)
        x = canvas.create_rectangle(xstart, randomY, xend, 395, fill='red')
        barList.append(x)
        xstart += 10
        xend += 10

    for bar in barList:
        x = canvas.coords(bar)
        length = x[3] - x[1]
        lengthList.append(length)

    for i in range(len(lengthList)-1):
        if lengthList[i] == min(lengthList):
            canvas.itemconfig(barList[i], fill='blue')
        elif lengthList[i] == max(lengthList):
            canvas.itemconfig(barList[i], fill='green')


window = tk.Tk()
window.title('Sorting')
window.geometry('600x435')
canvas = tk.Canvas(window, width='600', height='400')
canvas.grid(column=0,row=0, columnspan = 50)

insert = tk.Button(window, text='Insertion Sort', command=insertion_sort)
shuf = tk.Button(window, text='Shuffle', command=shuffle)
insert.grid(column=1,row=1)
shuf.grid(column=0, row=1)

shuffle()
window.mainloop()


 类似资料:
  • 我想这样做:https://storage.googleapis.com/spec-host/mio-staging/mio-design/1563837804615/assets/1XlKhaQFU9aS84ACmF-EDjVKDgI4pPldv/02-overflowmenu.mp4 我想挤压一个“ViewGroup”,正如你在视频中看到的。与此同时,我想淡出ViewGroup中的内容在其原始

  • 我正在创建一个我想要的相对布局,应该从上面滑到布局,所以这里是我所做的 使布局不可见 在oncreate中将屏幕上方的布局动画化 在onWindowsFocusChanged()中,我调用了动画,使布局可见,并希望布局滑入屏幕 但是 当视图被创建时,布局在其正确的位置,显示任何来自屏幕顶部的滑动效果 布局 这是activity的主题

  • 我的应用程序使用张量流精简模型来检测上传图像中的对象。 因此,我需要在用户上传的图像上绘制对象的边界框。 这是我的activity_camera.xml上传图像的地方。 这里是我运行tflite模型的地方。(CameraActivity.java) 边界框的绘制不起作用,因为我需要先绘制画布。 为了从视图中获取画布对象,我需要在该视图中修改或创建什么?

  • 我以前从未使用过自动布局约束。我有一个新的小应用程序,我正在开发,并注意到NIB的视图默认为自动布局。所以,我想我会借此机会使用它,并尝试弄清楚苹果公司在这方面的进展。 第一个挑战: 我需要调整MKMapView的大小,并将其设置为新位置的动画。如果我按照我习惯的方式来做: ...然后,每当更新同级视图时,MKMapView将“捕捉”回其原始高度(在我的例子中,UISegmentedControl

  • 问题内容: 在c ++或c编程语言中,我们知道要使用gotoxy(x,y)来更改坐标,并且可以使用循环和睡眠来更改坐标并制作动画。像这样; 但是我的问题是在JAVAFX 2.0编程中如何?我正在使用netbeans 7.2。感谢您的帮助。 问题答案: 看一下使用时间轴动画。它是JavaFX中动画的关键组成部分, 用于确定动画的关键部分何时以及以什么顺序出现。 这是一个例子

  • 我做了一些挖掘,似乎在任何地方都找不到简单的答案,也许我找错了地方。我只想按文件的修改时间排序,从最旧到最新。这可能吗?