1 说明:
=====
1.1 冒泡排序:
1.1.1 原理:比较两个相邻的元素,将值大的元素交换至右端。
1.1.2 来源:由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端,故得名。
1.1.3 是一种最简单直观的排序算法之一。
1.2 冒泡排序可视化:
1.2.1 Bubble Sort Visualizer。
1.2.2 更能直观了解这种排序。
1.2.3 通过多种方法实现,理解该算法,同时复习Python。
1.2.4 python法,采用:matplotlib法、pygame法、turtle法(2d+3d)、opencv法。
1.2.5 代码来源网络,来源已注明,仅供学习,感谢网友,适合收藏。
============
具体代码和讲解
============
2 python法:
========
2.1 matplotlib法
2.1.1 效果图:
2.1.2 代码来源:
#https://blog.csdn.net/m1090760001/article/details/103217052
2.1.3 代码一:
from matplotlib import pyplot as plt
import random
LIST_SIZE = 10 #10个组bar
PAUSE_TIME = 4 / LIST_SIZE
# 冒泡算法
def bubble_sort(nums):
for i in range(len(nums) - 1):
for j in range(len(nums) - i - 1):
if nums[j] > nums[j + 1]:
nums[j], nums[j + 1] = nums[j + 1], nums[j]
plt.cla() # 清除内容
plt.bar(range(len(nums)), nums, align='center')
plt.bar(j, nums[j], color="r", align="center")
plt.bar(j + 1, nums[j + 1], color="r", align="center")
plt.pause(PAUSE_TIME)
plt.show()
if __name__ == "__main__":
nums = []
for i in range(LIST_SIZE):
nums.Append(random.randint(0, 1000)) #随机生成
bubble_sort(nums)
print(nums)
2.2 turtle法:
2.2.1 2d-turtle法:
2.2.1.1 来源:
#https://blog.csdn.net/avskya/article/details/82958907
2.2.1.2 效果图:
2.2.1.3 代码二:
from turtle import *
from random import randint
from time import sleep
class Column(Turtle):
def __init__(self,x):
Turtle.__init__(self,shape='square')
self.up() #抬笔
r = randint(0,255)
g = randint(0,255)
b = randint(0,255)
self.fillcolor(r,g,b)
self.scale = randint(1,38) # 20 * self.scale 为柱子高度
self.setx(x)
self.__half__ = self.screen.window_height()//2 #屏幕的半高
self.shapesize(self.scale,1) #相对于自身坐标系前进的垂直方向放大
self.sety(0- self.__half__ + 10*self.scale + 30)
if __name__=="__main__":
width,height=800,800
screen = Screen()
screen.colormode(255)
screen.setup(width,height)
screen.title("冒泡排序动态演示")
screen.delay(0)
xcors = [x for x in range(40-width//2,width//2-20,40) ]
columns = [Column(x) for x in xcors ] #生成所有柱子
length = len(columns)
while True:
Flag = False #描述是否交换了数据的标志
for i in range(0,length-1 ): #由于越往后,越不要排这么多次数了.
c1 = columns[i] #代表前面柱子
c2 = columns[i + 1] #代表后面柱子
if c1.scale > c2.scale: #如果前面的柱子更高,则交换位置
x1 = c1.xcor() #保留前面柱子c1的x坐标
x2 = c2.xcor() #保留后面柱子c2的x坐标
columns[i] = c2 #让前面的柱子赋值为后面柱子
columns[i+1] = c1 #让后面的柱子赋值为前面柱子
columns[i].setx(x1) #交换列表中项目后,重新设置x坐标
columns[i+1].setx(x2) #交换列表中项目后,重新设置x坐标
Flag = True
screen.update()
sleep(0.1)
length = length - 1
if Flag == False:break #如果一次都没有排序,则退出while循环
2.2.2 3d-turtle法:
2.2.2.1 来源:
#https://blog.csdn.net/magicdoubi/article/details/88843825
2.2.2.2 效果图:
2.2.2.3 代码三:
from turtle import *
from random import *
import time
def bubble_sort(rectangle_list):
for passnum in range(0, 10 - 1):
for i in range(0, 10 - passnum - 1, 1):
if rectangle_list[i].num > rectangle_list[i + 1].num:
rectangle_list[i].replace(rectangle_list[i + 1])
time.sleep(0.5) # 休眠1秒
class Cube():
def __init__(self, x, y, num, leng=10):
self.x = x
self.y = y
self.num = num
self.side_len = leng
self.create_cube()
def create_side(self):
fillcolor("#639CD3")
begin_fill()
left(170)
forward(self.side_len)
right(80)
forward(20 * self.num)
right(100)
forward(self.side_len)
right(80)
forward(20 * self.num)
end_fill()
setheading(0) # 恢复向右默认
def create_top(self):
fillcolor("#95CEFF")
penup()
goto(self.x, self.y + 20 * self.num)
pendown()
begin_fill()
forward(20)
left(170)
forward(self.side_len)
left(10)
forward(20)
left(170)
forward(self.side_len)
end_fill()
setheading(0) # 恢复向右默认
def create_rectangle(self):
color("#639CD3")
penup()
goto(self.x, self.y)
pendown()
#柱的正面颜色
fillcolor("green")
begin_fill()
for x in range(1, 5):
if x % 2 == 1:
n = 20
else:
n = 20 * self.num
forward(n)
left(90)
end_fill()
def create_cube(self):
tracer(False)
self.create_rectangle()
self.create_side()
self.create_top()
tracer(True)
def erase_rectangle(self):
setheading(0)
color("white")
penup()
goto(self.x, self.y)
pendown()
fillcolor("white")
begin_fill()
for x in range(1, 5):
if x % 2 == 1:
n = 20
else:
n = 20 * self.num
forward(n)
left(90)
end_fill()
def erase_side(self):
fillcolor("white")
begin_fill()
left(170)
forward(self.side_len)
right(80)
forward(20 * self.num)
right(100)
forward(self.side_len)
right(80)
forward(20 * self.num)
end_fill()
setheading(0) # 恢复向右默认
def erase_top(self):
fillcolor("white")
penup()
goto(self.x, self.y + 20 * self.num)
pendown()
begin_fill()
forward(20)
left(170)
forward(self.side_len)
left(10)
forward(20)
left(170)
forward(self.side_len)
end_fill()
setheading(0) # 恢复向右默认
def erase_cube(self):
tracer(False)
self.erase_rectangle()
self.erase_side()
self.erase_top()
tracer(True)
def replace(self, n):
self.erase_cube()
n.erase_cube()
self.num, n.num = n.num, self.num
self.create_cube()
n.create_cube()
if __name__ == '__main__':
hideturtle()
var = list()
for i in range(0, 10):
var.append(Cube(35 * i, 0, randint(1, 10)))
bubble_sort(var)
done()
2.3 opencv法:
2.3.1 来源:
#https://blog.csdn.net/u011983560/article/details/106195385
2.3.2 效果图:
2.3.3 代码四:
import numpy as np
import os
import cv2
class Dataseq():
WHITE = (255,255,255)
RED = (0,0,255)
BLACK = (0,0,0)
YELLOW = (0,127,255)
def __init__(self, data=None,sort_type='figure'):
self.sort_type=sort_type
self.interval=400 #原来是5,太小了
#注意与data数据最大值和最小值也有关系,与跳跃时间也有关
self.inter=2
if data==None:
print("there are no data to sort!!!")
os.exit()
else:
self.data=data
self.maxd=max(self.data) #最大值
self.mind=min(self.data) #最小值
self.getfigure()
self.Visualize()
self.sortdata()
def getfigure(self):
datanum=len(self.data)
maxd=max(self.data)
mind=min(self.data)
self.figure=np.full((500*(maxd-mind)+50, (datanum)*(self.interval+self.inter), 3), 255,dtype=np.uint8)
for i in range(len(self.data)):
self.figure[-50-(self.data[i]-mind)*500:,(i)*(self.interval+self.inter):(i)*(self.interval+self.inter)+self.interval]=self.YELLOW
def choice(self, i, j):
mind=self.mind
self.figure[-50-(self.data[i]-mind)*500:,(i)*(self.interval+self.inter):(i)*(self.interval+self.inter)+self.interval]=self.BLACK
self.figure[-50-(self.data[j]-mind)*500:,(j)*(self.interval+self.inter):(j)*(self.interval+self.inter)+self.interval]=self.BLACK
self.Visualize()
def change(self,i,j):
mind=self.mind
self.figure[-50-(self.data[i]-mind)*500:,(i)*(self.interval+self.inter):(i)*(self.interval+self.inter)+self.interval]=self.WHITE
self.figure[-50-(self.data[j]-mind)*500:,(j)*(self.interval+self.inter):(j)*(self.interval+self.inter)+self.interval]=self.WHITE
indata=self.data[i]
self.data[i]=self.data[j]
self.data[j]=indata
self.figure[-50-(self.data[i]-mind)*500:,(i)*(self.interval+self.inter):(i)*(self.interval+self.inter)+self.interval]=self.BLACK
self.figure[-50-(self.data[j]-mind)*500:,(j)*(self.interval+self.inter):(j)*(self.interval+self.inter)+self.interval]=self.BLACK
self.Visualize()
def Visualize(self):
figure1=self.figure
cv2.namedWindow('img',cv2.WINDOW_NORMAL)
cv2.imshow('img',figure1)
cv2.waitKey(1000)
def sortdata(self):
for di in range(len(self.data)):
for dj in range(len(self.data)-di-1):
self.choice(dj,dj+1)
if self.data[dj]>self.data[dj+1]:
self.change(dj,dj+1)
self.getfigure()
datat=Dataseq([10,20,30,15,25,18],'sort')
datat.Visualize()
cv2.destroyAllwindows()
2.4 pygame法:
2.4.1 来源:
#https://github.com/zetaleee/Visualization-algorithm
2.4.2 效果图:
2.4.3 代码五:
import pygame
from random import randint
gap = 10 #竖条的间隔
width = 30 #竖条的宽度
screenSize = (600, 250) #显示屏幕的尺寸
barXPosition = [] #竖条在坐标轴的位置
Bars = [] #竖条对象列表
#生成颜色
class color(object):
@staticmethod
def RandomColor():
r,g,b = randint(0,225),randint(0,255),randint(0,255)
return (r,g,b)
@staticmethod
def CalculateColor(self,num):
pass
class bar(object):
def __init__(self, n,num,screen,width = 30):
self.n = n
self.locationX = barXPosition[n]
self.locationY = screenSize[1]-50-num
self.num = num
self.color = color.RandomColor()
self.width = width
self.font = pygame.font.Font(None, 20)
self.screen = screen
#绘制竖条及其上方的数字
def BarDraw(self):
pygame.draw.rect(self.screen, self.color,
((self.locationX,self.locationY), (self.width, self.num)))
self.txt = self.font.render("{}".format(self.num), True, self.color)
self.screen.blit(self.txt, (self.locationX+5,self.locationY-20))
#移动竖条,flag是用于判断移动方向 True向右 False向左
def move(self,flag):
pace = 2 #移动的步长
#消除移动前的竖条
pygame.draw.rect(self.screen, (255, 255, 235),
((self.locationX, self.locationY), (self.width, self.num)))
if flag:
self.locationX += pace
else:
self.locationX -= pace
# 绘制移动后的竖条
pygame.draw.rect(self.screen, self.color,
((self.locationX , self.locationY), (self.width, self.num)))
#交换相邻两个竖条
def ChangeLocation(self,otherBall):
#清除当前位置图像与文字
pygame.draw.rect(self.screen, (255, 255, 235),
((self.locationX, self.locationY-20), (self.width, self.num+20)))
pygame.draw.rect(otherBall.screen, (255, 255, 235),
((otherBall.locationX, otherBall.locationY - 20), (otherBall.width, otherBall.num + 20)))
#竖条移动的动画
for n in range(20):
self.move(True)
otherBall.move(False)
pygame.time.delay(40)
pygame.display.flip()
#移动后,重新写上竖条对应的数字
self.screen.blit(self.txt, (self.locationX + 5, self.locationY - 20))
otherBall.screen.blit(otherBall.txt, (otherBall.locationX + 5, otherBall.locationY - 20))
#交换竖条对象在列表的位置,同时交换排位数字
Bars[self.n],Bars[otherBall.n] = Bars[otherBall.n],Bars[self.n]
self.n,otherBall.n = otherBall.n,self.n
pygame.display.flip()
pygame.time.delay(200) #此延时控制排序动画的快慢
#冒泡排序
def algorithm(nums):
for i in range(len(nums) - 1):
for j in range(len(nums) - 1 - i):
if nums[j] > nums[j + 1]:
Bars[j].ChangeLocation(Bars[j + 1])
nums[j], nums[j + 1] = nums[j + 1], nums[j]
#计算十二个竖条在轴上的位置
def barX(gap,width,barXs):
for n in range(12):
barX = 50 + gap + (gap + width) * n
barXs.append(barX)
def main():
nums = []
pygame.init()
screen = pygame.display.set_mode(screenSize)
pygame.display.set_caption("算法") #标题
screen.fill((255, 255, 235)) #背景色
barX(gap,width,barXPosition) #计算bar位置并存于barXs
pygame.draw.aaline(screen,(0,255,0),(50,screenSize[1]-50),
(screenSize[0]-50,screenSize[1]-50)) #绘制坐标轴
pygame.display.flip()
#生成十二个竖条并绘制
for n in range(12):
num = randint(20,160)
tempBar = bar(n,num,screen)
tempBar.BarDraw()
nums.append(num)
Bars.append(tempBar)
pygame.time.delay(50) #此处延时是为了开始时演示动画效果
pygame.display.flip()
algorithm(nums) #排序
#等待关闭窗口事件
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if __name__ == "__main__":
main()
===自己整理并分享出来===
喜欢的人,请点赞、关注、评论、转发和收藏。