前言:开创者必然伟大并且多数是旷世之才,但很多时候,开创者中只出现了极少数能把这些成果发扬光大的(商业化)。。。反倒是一些敏锐的准商人,才会使这些创造地枝繁叶茂,这是《硅谷之光》所传达的神谕。
下面进入正题:
说道排序(内排序),按照原始数据的多少和散列特性来选择合适的排序非常重要,数据量少(几千)插排、交换排、选择排都可以,要是数据达到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++)会稍微快点,对于更大的数据就得采用外排序和其他技术(流水线)了。
欢迎转载,大牛勿喷