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 代码来源:
#
2.1.3 代码一:
from matplotlib import pyplot as pltimport randomLIST_SIZE = 10 #10个组barPAUSE_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 来源:
#
2.2.1.2 效果图:
2.2.1.3 代码二:
from turtle import *from random import randintfrom time import sleepclass 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 来源:
#
2.2.2.2 效果图:
2.2.2.3 代码三:
from turtle import *from random import *import timedef 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 来源:
#
2.3.2 效果图:
2.3.3 代码四:
import numpy as npimport osimport cv2class 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 pygamefrom random import randintgap = 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): passclass 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 = Falseif __name__ == "__main__": main()
===自己整理并分享出来===
喜欢的人,请点赞、关注、评论、转发和收藏。