社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

3min利用Python实现9种经典排序算法可视化!(附源代码)

数据派THU • 5 年前 • 365 次点击  

来源:恋习Python

本文附视频建议收藏

本文为你分享实现9种经典排序算法可视化的方法,3分钟即可实现。


[导 读]近在某网站上看到一个视频,是关于排序算法的可视化的,看着挺有意思的,也特别喜感。


不知道作者是怎么做的,但是突然很想自己实现一遍,而且用python实现特别快,花了一天的时间,完成了这个项目。主要包括希尔排序(Shell Sort)、选择排序(Selection Sort)、快速排序(Quick Sort)、归并排序(Merge Sort)等九种排序。


▲6分钟演示15种排序算法


具体讲解需要解决问题的实现思路如下:


  • 如何表示数组

  • 如何得到随机采样数组,数组有无重复数据

  • 如何实现排序算法

  • 如何把数组可视化出来


如何表示数组


Python提供了list类型,很方便表示C++中的数组。标准安装的Python中用列表(list)保存一组值,可以用来当作数组使用,不过由于列表的元素可以是任何对象,因此列表中所保存的是对象的指针。这样为了保存一个简单的[1,2,3],需要有3个指针和三个整数对象。


对于数值运算来说这种结构显然比较浪费内存和CPU计算时间,在此就不详细论述。


如何得到随机采样数组,数组有无重复数据


假设我希望数组长度是100,而且希望数组的大小也是在[0,100)内,那么如何得到100个随机的整数呢?可以用random库。


示例代码:


import random
data = list(range(100))
data = random.choices(data, k=100 )
print(data)
[523345334825682878237835244469886629827784121910
27245742717525177944481866225 69978656473151402141
21175688419246568023704996835416368224686016981681,
 10131124 6835563923446303605666382847472590893868
21]


但是以上代码有个问题,random.choices是对一个序列进行重复采样,得到的数组存在重复数据,那如果不希望存在重复数据,而是希望进行无重复采样,怎么办?


可以用random.sample函数,示例代码:


data = random.sample(data, k=100)
print(data)
[49285628446281254833 5438301613192356606641246868,
 77927824663809478418488215625257524388231522310
71 402746333556511231225891621211142474481358688
293677163965769966824869790691068 98564483477017
47826045]


这样就可以得到无重复采样数据了。


如何实现排序算法


算法种类较多,就不一一举例;在此就以希尔排序(Shell Sort)为例讲讲:


希尔排序的原理:希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。


希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

基础的插入法排序是两重循环,希尔排序是三重循环,最外面一重循环,控制增量gap,并逐步减少gap的值。二重循环从下标为gap的元素开始比较,依次逐个跨组处理。最后一重循环是对组内的元素进行插入法排序。


这样进行排序的优点在于每次循环,整个序列的元素都将小元素的值逐步向前移动,数值比较大的值向后移动。


示例代码:


from data import DataSeq

def ShellSort(ds):
    assert isinstance(ds, DataSeq), "Type Error"

    Length = ds.length
    D = Length//2
    while D>0:
        i=0
        while i             tmp = ds.data[i]

            j=i
            while j>=1 and ds.data[j-D]>tmp:
                ds.SetVal(j, ds.data[j-D])
                j-=D
            ds.SetVal(j, tmp)

            i+=D
        D//=2

if __name__ == "__main__":
    ds=DataSeq(64)
    ds.Visualize()
    ds.StartTimer()
    ShellSort(ds)
    ds.StopTimer()
    ds.SetTimeInterval(0)
    ds.Visualize()


如何把数组可视化出来


有了随机数组初始化方法,再实现好排序函数,我们还差一步,就是把排序函数中每次移动数组后将数组可视化并输出。


对数组进行可视化,很容易想到python的可视化工具matplotlib!但是在项目中我并没有用matplotlib,而是用了numpy+opencv。


为什么不用matplotlib?


因为在排序过程中,每次修改数组,都希望能够实时修改图片并输出,matplotlib确实很方便,但是matplotlib的效率实在是不高,而且每次修改数组前后的两幅图片其实是差不多的。如果用matplotlib,每次都是要重新绘制图片,非常耗时!!!


所以考虑自己生成图片,在每次修改数组后,只将图片中改动的那两列进行修改即可!这样就比用matplotlib每次重新绘制图片效率高得多!


数组中主要有两种操作,一种是对某个idx赋值,一种是交换某两个idx的值。


示例代码:


class DataSeq:
    WHITE = (255,255,255)
    RED = (0,0,255)
    BLACK = (0 ,0,0)
    YELLOW = (0,127,255)
    def __init__(self, Length, time_interval=1, sort_title="Figure", repeatition=False):
        pass
    def Getfigure(self):
        _bar_width = 5
        figure = np.full((self.length*_bar_width,self.length*_bar_width,3), 255,dtype=np.uint8)
        for i in range(self.length):
            val = self.data[i]
            figure[-1-val*_bar_width:, i*_bar_width:i*_bar_width+_bar_width] = self.GetColor(val, self.length)
        self._bar_width = _bar_width
        self.figure = figure
    def _set_figure(self, idx, val):
        min_col = idx*self._bar_width
        max_col = min_col+self._bar_width
        min_row = -1-val*self._bar_width
        self.figure[ : , min_col:max_col] = self.WHITE
        self.figure[ min_row: , min_col:max_col] = self.GetColor(val, self.length)
    def SetVal(self, idx, val):
        self.data[idx] = val
        self._set_figure(idx, val)

        self.Visualize((idx,))

    def Swap(self, idx1, idx2):
        self.data[idx1], self.data[idx2] = self.data[idx2], self.data[idx1]
        self._set_figure(idx1, self.data[idx1])
        self._set_figure(idx2, self.data[idx2])

        self.Visualize((idx1, idx2))


附上一张效果图:



附上源码链接:

https://github.com/ZQPei/Sorting_Visualization


编辑:文婧

校对:龚力

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/29629
 
365 次点击