一些其他的排序算法
希尔排序
时间复杂度随切片的变化而变化
思路
首先取一个整数d1=n/2,将元素分为d1分组,每组相邻元素之间距离为d1,每组进行插入排序,然后取第二个整数d2=d1/2,重复上述分组排序过程,知道di=1
例如这个列表长度为9,所以d1=4,并分组
然后5 3 8,7 1,4 2,6 9分别进行插入排序
然后d2=2,并分组
然后3 2 5 4 8,1 6 7 9分别进行插入排序
然后d3=1
对整个列表进行插入排序
代码实现
gap版插入排序
只需将原来的插入排序的所有1改成gap
def insert_gap_sort(li,gap):
for i in range(gap,len(li)):
tmp = li[i]
j = i - gap
while j >= 0 and li[j] > tmp:
li[j+gap] = li[j]
j = j - gap
li[j+gap] = tmp
return li
主函数
def shell_sort(li):
d = len(li) // 2
while d >= 1:
insert_gap_sort(li,d)
d = d // 2
return li
li = [3,6,4,74,8,2,6,9,3]
print('原列表:',li)
print(shell_sort(li))
计数排序 时间复杂度:O(n)
已知0-100内的一些数,进行排序
思路
例如1,4,5,7,8,4,2,7,首先得到每个数字出现的次数:
1:1 2:1 4:2 5:1 7:2 8:1
所以排序得到:1 2 4 4 5 7 7 8
代码实现
def count_sort(li,max_count=100):
count = [0 for _ in range(max_count+1)]
for val in li:
count[val] += 1
li.clear()
for index,val in enumerate(count): #index是数字 val是出现的次数
for i in range(val):
li.append(index)
import random
li = [random.randint(0,100) for _ in range(20)]
print("原列表为:",li)
count_sort(li)
print(li)
桶排序
桶排序的表现取决于数据的分布
平均情况时间复杂度: O(n+k)
最坏情况时间复杂度: O(n平方k)
空间复杂度: O(nk)
思路
桶排序是对计数排序的改进,如果元素的范围比较大
桶排序就是先把元素分在不同的桶中,再对每个桶中的元素排序
代码实现
def bucket_sort(li,n=100,max_num=10000):
"""
:param li: 列表
:param n: 桶的个数
:param max_num: 范围 最大数
:return:
"""
buckets = [[] for _ in range(n)] #创建桶
for val in li:
i = min(val //(max_num // n),n-1) #用min是为了防止当10000时,val //(max_num // n)为100,超过范围
buckets[i].append(val) #把val加到桶里面
for j in range(len(buckets[i])-1,0,-1): #反向插入排序
if buckets[i][j] < buckets[i][j-1]:
buckets[i][j],buckets[i][j-1] = buckets[i][j-1],buckets[i][j]
else:
break
sorted_li = []
for buc in buckets:
sorted_li.extend(buc)
return sorted_li
import random
li = [random.randint(0,10000) for _ in range(100)]
print("原列表为:",li)
print(bucket_sort(li))
结果较长,没有截全
基数排序
思路
多关键字排序:现有一个员工表,现要求首先按照薪资排序,然后年龄相同的员工按照年龄排序
先按照年龄进行排序,再按照薪资进行稳定对的排序
那么对于一组数字,也可以看做多关键字排序——>从个位 十位…
时间复杂度: O(nk)
空间复杂度: O(n+k)
k表示最大的数字位数
首先按照个位数字大小入桶
然后全部取出
然后按照十位数字排序
然后全部取出
代码实现
def radix_sort(li):
max_num = max(li)
it = 0
while 10 ** it <= max_num:
buckets = [[] for _ in range(10)] #每个位数有10种可能
for val in li:
digit = (val // 10 ** it) % 10 #依次获取每个数字 相同位数的数字 eg.i=0 就是获取个位数字
buckets[digit].append(val) #位数上相同数字的放入同一个桶
li.clear()
for buc in buckets:
li.extend(buc)
it += 1
return li
import random
li = [random.randint(0,100) for _ in range(20)]
print("原列表为:",li)
print(radix_sort(li))