关于python排序算法可视化二

2022-03-11 14:00:03 浏览数 (1)

关于排序算法可视化只是简单在原来代码后追加了十几行代码,排序算法的可视化重要的是matplotlib.animation.FuncAnimation函数,该函数有几个重要的参数,一个是图表面板,一个是动画播放回调函数,一个数据帧,一个是初始化函数。

关键在于数据帧这一块,一种办法是生成所有待播放的数据,形成数据数组,然后在动画播放回调函数中进行播放,另外一种办法是使用数据迭代器,一边生成数据,一边交给回到函数进行播放。第一种容易理解一些,第二种函数和数据解耦不大容易。

可视化的另一个问题是对于matplotlib各种组件的对象和方法要熟悉,本文只是简单做一下尝试。

代码示例

代码语言:javascript复制
import random
import copy
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

def init_sortdata(datarage=10,datanum=10):
    data = list(range(1,datarage 1))
    data = random.sample(data, k=datanum)
    return data

#计算时间函数
def print_run_time(func):
    def wrapper(*args, **kw):
        start_time = time.time()  # 程序开始时间
        ret=func(*args, **kw)     # 将被装饰函数的返回值接收
        end_time = time.time()   # 程序结束时间
        total_time = int(1000*(end_time - start_time)) #程序执行时间,毫秒计
        print('{}排序算法共计执行{}豪秒,开始时间为{},结束时间为{}'.format(func.__name__,total_time,start_time,end_time))
        return ret                # 返回被装饰函数的返回值
    return wrapper

class SortClass:
    def __init__(self,collection):
        self.collection=collection

    def swapAndDraw(self,tempbar, x1, x2):
        #tempbar 为 <BarContainer object of X artists>
        #tempbar[x1] 为 Rectangle(xy=(9.6, 0), width=0.8, height=98, angle=0) 对象
        temp1height = tempbar[x1].get_height()              #获取待交换图像x1的高度,写入临时变量
        tempbar[x1].set_height(tempbar[x2].get_height())    #将x1的高度置为x2的高度
        tempbar[x2].set_height(temp1height)                 #将x2的高度置为x1的高度
        tempbar[x2].set_fc("red")                           #将要交换的x2置为红色标志
        plt.draw()                                          #绘制图形
        plt.pause(0.1)                                      #为体现动画,设置延迟时间为0.1秒
        tempbar[x2].set_fc("green")                         #再将要交换的x2重置为绿色标志

    @print_run_time
    def bubble_sort(self):
        #冒泡排序,数据来自类的初始化,为了不改变源list数据,采用深拷贝方式
        dataset = copy.deepcopy(self.collection)
        stepdata=[]
        length = len(dataset)   #list长度
        runtimes=0              #交换次数
        looptimes=0             #循环次数
        print('原始数据=',dataset)  #记录原始数据
        plt.figure('bubble_sort')
        plt.title('bubble_sort')
        plt.xticks(range(0,length), rotation=45)                #进行X轴设置
        tempbar = plt.bar(range(length), dataset, fc="green")   #初始化元数据
        for i in range(length - 1):
            print(' 第{}轮外轮,开始数据={}'.format(i, dataset))
            swapped = False
            for j in range(length - 1 - i):
                if dataset[j] > dataset[j   1]:                             #相邻元素间交叉判断
                    swapped = True
                    runtimes=runtimes 1 #记录交换次数
                    dataset[j], dataset[j   1] = dataset[j   1], dataset[j] #数据交换
                    stepdata.append(dataset.copy())                            #
                    self.swapAndDraw(tempbar, j, j   1)                     #绘制动画图
                looptimes=looptimes 1   #记录循环次数
                print('     第{}轮内轮,中间数据={}'.format(j, dataset))  #记录内轮中间数据
            if not swapped:
                break
            print(' 第{}轮外轮,结束数据={}'.format(i,dataset))           #记录外轮中间数据
        print('最终数据=', dataset) #记录最终数据
        plt.ioff()
        return looptimes,runtimes,dataset,stepdata

if __name__ == "__main__":
    import time
    orgdata=init_sortdata(100,8)
    asort=SortClass(orgdata)
    looptimes,runtime,sortdata,stepdata=asort.bubble_sort()
    print('排序前的数据为{}'.format(orgdata))
    print('排序后的数据为{}'.format(sortdata))
    print('循环次数={}'.format(looptimes))
    print('交换次数={}'.format(runtime))
    print('stepdata={}'.format(stepdata))
    #matplotlib动画过程实际上是重构当前帧中图表对象的过程
    def animate(frame):
        for rect, y in zip(bars, stepdata[frame]):  #遍历当前的bars中的rect和数据
            rect.set_height(y)                      #重置每一个bar条的高度
        return bars

    frames=len(stepdata)                            #从步骤数据中获取排序帧数
    xrange=range(len(orgdata))                      #获取bar条的x布局
    fig = plt.figure(2, figsize=(6, 4))             #初始化fig
    plt.title('bubble_sort')
    plt.xticks(range(0, len(orgdata)), rotation=45)  # 进行X轴设置
    bars = plt.bar(xrange, stepdata[0], 0.5)        #初始化bars
    #fig为
    anim = FuncAnimation(fig, animate, frames=frames, interval=200, repeat=False)   #实现动画
    plt.show()

0 人点赞