Python 3 对几种常见的内排序算法的比较

前言:开创者必然伟大并且多数是旷世之才,但很多时候,开创者中只出现了极少数能把这些成果发扬光大的(商业化)。。。反倒是一些敏锐的准商人,才会使这些创造地枝繁叶茂,这是《硅谷之光》所传达的神谕。

下面进入正题:

说道排序(内排序),按照原始数据的多少和散列特性来选择合适的排序非常重要,数据量少(几千)插排、交换排、选择排都可以,要是数据达到w级别呢?前面那些几乎都会慢死,所以介绍下面的几种排序:

#coding=utf-8,
import random,time,sys
'''Author:Frank.ZhangLongQi
   Date:2018-3-23
   e-mail:Zlonqi@qq.com
   Descrip:比较shell、快排、基数排序、堆排、归并排序处理10w,100w级别数据时表现的   性能
'''
sys.setrecursionlimit(100000000)#设置递归深度
def radix_sort(array):
    bucket, digit = [[]], 0
    while len(bucket[0]) != len(array):
        bucket = [[], [], [], [], [], [], [], [], [], []]
        for i in range(len(array)):
            num = (array[i] // 10 ** digit) % 10
            bucket[num].append(array[i])
        array.clear()
        for i in range(len(bucket)):
            array += bucket[i]
        digit += 1
    return array

def quickSort(L, low, high):#快排是很实用的一种排序算法,结合了归并和插排的优点,平均时间复杂度为nlgn,
    i = low                 #受主元是否划分均衡的影响,当划分较均衡时,性能突出,但当划分极不均衡时
    j = high                #比如极限情况下的已经排序的数据或存在大量重复数据,此时快排的复杂度为n的平方,此时,插排的复杂度仅为n
    if i >= j:
        return L
    key = L[i]
    while i < j:
        while i < j and L[j] >= key:
            j = j-1                                                         
        L[i] = L[j]
        while i < j and L[i] <= key:    
            i = i+1 
        L[j] = L[i]
    L[i] = key 
    quickSort(L, low, i-1)
    quickSort(L, j+1, high)
    return L

def merge(nums, first, middle, last):  
    ''''' merge '''  
    lnums = nums[first:middle+1]   
    rnums = nums[middle+1:last+1]  
    lnums.append(sys.maxsize)  #sys.maxsize为一个64位的十进制数
    rnums.append(sys.maxsize)  
    l = 0  
    r = 0  
    for i in range(first, last+1):  
        if lnums[l] < rnums[r]:  
            nums[i] = lnums[l]  
            l+=1  
        else:  
            nums[i] = rnums[r]  
            r+=1  
def merge_sort(nums, first, last):  
    ''''' merge sort 
    merge_sort函数中传递的是下标,不是元素个数 
    '''  
    if first < last:  
        middle = (first + last)//2  #mid要取整
        merge_sort(nums, first, middle)  
        merge_sort(nums, middle+1, last)  
        merge(nums, first, middle,last)  
def shell(arr):
    n=len(arr)
    h=1
    while h<n/3:
        h=3*h+1
    while h>=1:
        for i in range(h,n):
            j=i
            while j>=h and arr[j]<arr[j-h]:
                arr[j], arr[j-h] = arr[j-h], arr[j]
                j-=h
        h=h//3
def heap_sort2(lst):
    for start in range((len(lst)-2)//2,-1,-1):
        sift_down(lst,start,len(lst)-1)
     
    for end in range(len(lst)-1,0,-1):
        lst[0],lst[end]=lst[end],lst[0]
        sift_down(lst,0,end-1)
    return lst
 
def sift_down(lst,start,end):
    root=start
    while True:
        child=2*root+1
        if child>end:
            break
        if child+1<=end and lst[child]<lst[child+1]:
            child+=1
        if lst[root]<lst[child]:
            lst[root],lst[child]=lst[child],lst[root]
            root=child
        else:
            break

if __name__=='__main__':
    N=1000000 #设置数据量
    nums = []
    for _ in range(N):#随机生成
        n=random.randint(1,10000000)
        nums.append(n)
    A=nums.copy() #确保每种算法的测试数据一致
    B=nums.copy()
    C=nums.copy()
    D=nums.copy()

    start1=time.clock()
    shell(nums)         #希尔排序
    end1=time.clock()
    print('shell time is',end1-start1)

    start3=time.clock()
    merge_sort(A,0, len(A)-1) #归并排序
    end3=time.clock()
    print('merge time is',end3-start3)

    start4=time.clock()
    B=quickSort(B,0,len(B)-1)   #快速排序
    end4=time.clock()
    print('quick time is',end4-start4)

    start2=time.clock()
    C=heap_sort2(C)         #堆排序
    end2=time.clock()
    print('heap time is',end2-start2)

    start5=time.clock()
    D=radix_sort(D)     #基数排序
    end5=time.clock()
    print('radix time is',end5-start5)

    if  nums==A and A==B and B==C and C=D :#相互验证排序结果的正确性
        print('True')
    else:
        print('False')

Demon:

10w数据:


可以看出,在10w级水平,快排和归并和基数排序都较快,不到2秒,可以接受

100w数据:


据结果可以看出,对于百万级别的数据,shell排序和堆排序已经不能满足用户需求了,快排(通过优化移位过程还可以加快1秒)、基数排序和归并排序稍微快点(不到20秒)但也不行,可能用其他语言(C/C++)会稍微快点,对于更大的数据就得采用外排序和其他技术(流水线)了。

欢迎转载,大牛勿喷

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值