基于Python的常用数值排序算法比较分析

Comparison and analysis of common numerical sorting algorithms based on Python

DU Hu-bin ,SHENG Long

(Hebei university of engineering, Handan city, Hebei province)

Abstract:Sorting is one of the important problems in the study field of computer science, good performance of the algorithm, the performance good sorting algorithm of the large-scale disorderly data can be efficient sorting, facilitate the further analysis of data processing. Makes a comparative analysis of the numerical sorting algorithm based on Python, through the bubble sort, selection sort, insertion sort, quick sort, hill sorting for multiple sets of experimental data obtained various sorting algorithm in the performance analysis of specific data environment, and various sorting algorithm in the performance of certain data environment.

Key wordsBubble sort; Select sort; Quicksort; Insertion sort; Hill ordering; Python; Time complexity; Sorting algorithm

1引言

排序是计算机内经常要进行的一种操作,就是将一组对象按照某种逻辑顺序重新排列的过程。现在计算机的广泛使用使得数据无处不在,而整理数据第一步通常就是进行排序。排序在商业数据处理和现代科学计算中都有着重要的地位,能够应用于多种事务处理、组合优化、天体物理学、分子动力学、语言学、天气预报等领域。排序算法的性能对现代计算机发展的有着重要的意义。[2]而排序算法的性能比较通常从三个方面进行评价,分别是时间复杂度,空间复杂度和稳定性。

在计算机科学中,算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。这是一个关于代表算法输入值的字符串的长度的函数。时间复杂度常用大О符号表述,不包括这个函数的低阶项和首项系数。而算法的运行时间的长短也直观的反应了算法的效率,在相同计算环境下通过运行时间可以直观的比较排序算法的性能。[3]

Python语言,是一种面向对象的解释型计算机程序设计语言,由荷兰人Guido van Rossum于1989年发明,由于Python语言的简洁性、易读性以及可扩展性,在国外用Python做科学计算的研究机构日益增多,一些知名大学已经采用Python来教授程序设计课程,2017年7月20日,IEEE发布2017年编程语言排行榜,Python高居首位。[3]但是目前大多数排序算法性能实验数据大多基于c,c++,等语言,虽然Python语言所编写的代码简单易懂,效率极高,且具有高度融合性,而很少有基于python语言的排序算法的性能比较,本文利用python实现数值排序算法并通过比较各算法性能进行分析。

2 算法分析

2.1冒泡排序

冒泡排序的设计思想,是比较相邻的元素,如果第一个元素比第二个元素大,就交换他们两个;然后对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对;最后的元素是最大的数;针对所有的元素重复以上的步骤,除最后一个元素;然后持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较,即完成排序。[4]

冒泡排序算法用Python语言描述如下:

# -*- coding:utf-8 -*-

def bubble_sort(list):

    length=len(list)

    for index in range(length):

        for i in range(1,length-index):

            if list[i-1]<list[i]:

                list[i],list[i-1]=list[i-1],list[i]

    return list

图 1冒泡排序流程图

有上述算法可知,若文件的初始状态是正序的,一趟扫描即可完成排序。所需的关键字比较次数

正在上传…重新上传取消和记录移动次数转存失败重新上传取消均达到最小值:正在上传…重新上传取消,正在上传…重新上传取消。所以,冒泡排序最好的时间复杂度为正在上传…重新上传取消。若初始文件是反序的,需要进行正在上传…重新上传取消趟排序。每趟排序要进行转存失败重新上传取消次关键字的比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值,转存失败重新上传取消,转存失败重新上传取消。冒泡排序的最坏时间复杂度为转存失败重新上传取消。[4]

综上,因此冒泡排序总的平均时间复杂度为

转存失败重新上传取消

2.2选择排序

选择排序算法的设计思想:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果:①初始状态:无序区为R[1..n],有序区为空。②第1趟排序,在无序区R[1..n]中选出关键字最小的记录R[k],将它与无序区的第1个记录R[1]交换,使R[1]和R[2..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。③第i趟排序,第i趟排序开始时,当前有序区和无序区分别为R[1..i-1]和R(i..n)。[5]该趟排序从当前无序区中选出关键字最小的记录 R[k],将它与无序区的第1个记录R交换,使R[1..i]和R分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。

选择排序算法用Python语言描述如下:

def select_sort(list):

    length=len(list)

    for index in range(length):

        for i in range(index,length):

            if list[index]<list[i]:

 list[index],list[i]=list[i],list[index]

    return list

图 2选择排序算法流程图

正在上传…重新上传取消

由上可得,在直接选择排序中所记录的移动次数最少的的次数是0,最大值为3(n-1)。但是,无论初始排序如何,都不会影响数据得比较次数,均为n(n-1)/2,算法的时间复杂度为

转存失败重新上传取消

2.3插入排序

  插入排序算法的思想是,每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。从第一个元素开始,该元素可以认为已经被排序;取出下一个元素,在已经排序的元素序列中从后向前扫描;如果该元素(已排序)大于新元素,将该元素移到下一位置;重复上步,直到找到已排序的元素小于或者等于新元素的位置;将新元素插入到该位置后;重复以上步骤,直至比较完文件中的所有数据。

插入排序算法的Python语言描述如下:

  def insert_sort(lists):

    count = len(lists)

    for i in range(1, count):

        key = lists[i]

        j = i - 1

        while j >= 0:

            if lists[j] > key:

                lists[j + 1] = lists[j]

                lists[j] = key

            j -= 1

return lists

图 3插入排序算法流程图

转存失败重新上传取消

有上述可得,如果文件中的数据为正序排列,在这种情况下,需要进行的比较操作需(n-1)次即可。最坏情况就是,序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次。插入排序的赋值操作是比较操作的次数加上 (n-1)次,因此时间复杂度为

转存失败重新上传取消

2.4快速排序

快速排序算法的思想是,快速排序算法是对冒泡排序的一种改进,通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。一趟快速排序算法,设置两个变量i、j,排序开始的以第一个数组元素作为关键数据,赋值给base,即base=arr[0]时候:i=0,j=N-1;以第一个数组元素作为关键数据,赋值给base,即base=arr[0];从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值arr[j],将arr[j]和arr[i]互换;从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于base的arr[i],将arr[i]和arr[j]互换;[4]重复上述步骤,直至i=j。

快速排序算法用Python语言描述如下:

def kp(arr,i,j):

    if i<j:

        base=kpgc(arr,i,j)

        kp(arr,i,base)

        kp(arr,base+1,j)

def kpgc(arr,i,j):

    base=arr[i]

    while i<j:

        while i<j and arr[j]>=base:

            j-=1

        while i<j and arr[j]<base:

            arr[i]=arr[j]

            i+=1

            arr[j]=arr[i]

        arr[i]=base

    return i

ww=[random.randint(0, 1000) for _ in range(10)]

kp(ww,0,len(ww)-1)

print (ww)

快速排序算法需要通过两种情况讨论;第一种情况,当需要排序的文件中数据为有序时,  此时为最优情况,最优的情况就是每一次取到的元素都刚好平分整个数组此时的时间复杂度公式则为:T[n] = 2T[n/2] + F(n);T[n/2]为平分后的子数组的时间复杂度,F[n] 为平分这个数组时所花的时间;快速排序最优的情况下时间复杂度为:O( nlogn )。[5]

最差的情况就是每一次取到的元素就是数组中最小/最大的,这种情况其实就是冒泡排序了(每一次都排好一个元素的顺序) 这种情况时间复杂度就好计算了,就是冒泡排序的时间复杂度:T[n] = n * (n-1) = n²+ n;综上所述:快速排序最差的情况下时间复杂度为:O( n²)。

快速排序的平均时间复杂度也是:

转存失败重新上传取消

2.5希尔排序

希尔排序算法的基本设计思想先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量即所有记录放在同一组中进行直接插入排序为止。

希尔排序算法用Python语言描述如下:

def shell_sort(list):

length=len(list)

dist=length/2

while dist>0:

for i in range(dist,length):

temp=list[i]

j=i

while j>=dist and temp<list[j-dist]:

list[j]=list[j-dist]

j-=dist

list[j]=temp

dist/=2

return list

图 4希尔排序算法流程图

转存失败重新上传取消

希尔排序算法的时间复杂度,由于涉及到一些数学上未解决的难题,无法准确算出时间复杂度, 时间复杂度经过大量研究为接近为

转存失败重新上传取消

3.实验方法

实验测试在以下条件下进行:

编程语言:Python语言

编译器:PyCharm

测试数据:

   数据规模:1000~1000000

   数据组数:5*4组,每种排序算法分别进行1000,10000,100000,1000000数据量测试,多次测试取平均值。[4]

   数据获取方式:随机获取

实验环境

OS:Windows 10

处理器:Intel® Core™ i5-6200U CPU 2.30GHz  2.40GHz

RAM:4.00GB

系统类型:64位操作系统,基于x64处理器。

4.数据分析

 实验采用随机产生数组,数据值取值区间为0~1000,数据容量分别为1000,10000,100000,1000000组数据值。即实验过程中分别将冒泡排序,插入排序,选择排序,快速排序,希尔排序分别记录其在1k,10k,100k,1000k数据量的进行排序所需要的时间,分别比较算法运行的时间,从而比较出算法的性能优劣。

第一组数据为五种算法在数据量为1k情况下的运行时间对比:

图 5  算法在1k情况下运行时间

转存失败重新上传取消

有上述图表可知五种算法在数据容量为为1k的情况下所需要的时间对比,冒泡排序和插入排序相差不大,时间集中于0.17s~0.15s之间,选择排序算法的时间约为冒泡排序和插入排序算法的一半,而希尔排序与快速排序明显优于其他排序算法,运行时间集中于0.02s~0.01s之间,由第二部分对算法的分析可知,冒泡排序,插入排序,选择排序的时间复杂度都为

转存失败重新上传取消,其三个算法的同样较小数据量的时间较为接近,而希尔排序和快速排序在数据量较小时,时间较短无法准确的确定优劣。

第二组数据为五种算法在数据量为10k情况下的运行时间对比:

  图 6 算法在10k情况下运行时间

转存失败重新上传取消

当数据量增加到10k是可明显观察到冒泡排序,插入排序,选择排序存在明显的时间差,由于冒泡排序重复遍历数据的次数要多于插入排序和选择排序,所以消耗的时间较长,选择排序优于插入排序,插入排序优于冒泡排序,而希尔排序和快速排序时间较为接近,由于可能数据量还是较少的原因,时间集中于0.15s~0.10s,快速排序稍微优于希尔排序,但仍然无法的到较为优劣的算法。

第二组数据为五种算法在数据量为100k情况下的运行时间对比:

图 7算法在100k情况下运行时间

转存失败重新上传取消

在数据量为100k情况下,冒泡排序,插入排序,选择排序运行仍然呈阶梯状的,优劣明显,而希尔排序算法的运行的平均时间为4.845293s,快速排序算法的平均运行时间为1.940293s,实验数据表明希尔排序算法要优于快速排序算法,希尔排序算法的时间复杂度为

转存失败重新上传取消,快速排序的时间复杂度为转存失败重新上传取消,当数据量级达到100k时可以观察出希尔排序算法和快速排序算法的优劣程度。

第二组数据为五种算法在数据量为1000k情况下的运行时间对比:

图 8 算法在1000k情况下运行时间

转存失败重新上传取消

当数据量超过1000k时,冒泡排序,插入排序,选择排序,所需要的时间量过于庞大无法有效测出,当数据量大时希尔排序,和快速排序运行时间对比明显,快速排序明显优于希尔排序。[6-10]

5.总结

由上述实验数据可知,在Python语言编写的冒泡排序,插入排序,选择排序,希尔排序,快速排序的排序算法的性能差别。一个算法的优劣取决本身时间复杂度和空间复杂度,还有程序所运行的环境不同,算法的需求不同,优劣也会不同。[9]

图 9 五种排序算法时间

转存失败重新上传取消

根据以上的实验结果,当数据量小于1k时,冒泡排序,插入排序,选择排序的时间复杂度相同,所以时间消耗接近,随着数据量的逐渐增加,冒泡排序算法消耗的时间要高于两种算法。当数据量在1k~100k时,根据折线图9,可明显看出选择排序优于插入排序,插入排序优于冒泡排序,而希尔排序和快速排序明显优于上述三种排序算法。由于希尔排序算法的时间复杂度为

转存失败重新上传取消,快速排序的时间复杂度为转存失败重新上传取消,所以在数据量较小的时候,无法明显得出两种算法的优劣程度,而在数据量超过100k时,快速排序算法所消耗的时间要远远短于希尔排序。[6-10]

本次实验仅仅是从数据量的大小来判断算法的优劣,而影响一个排序算法性能的影响因素多种多样,所以在接下的研究中会有更多的考虑方面,使算法可以更好的利用在合适的方面中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值