关于排序算法可视化只是简单在原来代码后追加了十几行代码,排序算法的可视化重要的是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()