前言
不知道大家还记不记得计数排序 在计数排序中,需要根据最大值和最小值创建一个列表,如果最大值和最小值的差很大,即使 需要排序的数据并不是很多,那么就会照成不必要的浪费,因为不管需要排序的数有多少,都需 要创建一个长度为(最大值-最小值+1)的列表
桶排序的由来
鉴于上面这一点,我们可以进行分块排序,每一块用一个列表来表示(每一个列表都用来存放对应区间的数),将这个列表看成是一个桶(这也是为什么叫桶排序),将某个数放到对应的桶中,最后合并这些桶就得到了有序的序列。
栗子
''' 例: 对li=[1,5,65,100,3000,990]进行桶排序 我们可以分n=5个桶,每个桶中装size=50个元素 最大值:50*50-1=249(对于大于最大值的元素,我们可以把它放到最后一个桶中) 那么: 第一个桶中的元素的值的范围应该是:[0,49] 第二个桶中的元素的值的范围应该是:[50,99] 第三个桶中的元素的值的范围应该是:[100,149] 第四个桶中的元素的值的范围应该是:[150,199] ... 第n个桶中的元素的值的范围应该是:[(n-1)*50,n*50-1] #1.创建桶列表 bucket_li=[[],[],[],[],[]] #列表中的每一个列表代表一个桶,总共5个桶 遍历li: 第一个元素:1 属于[0,49],因此加到第一个桶中,所以bucket_li=[[1,],[],[],[],[]] 第二个元素:5 属于[0,49],因此加到第一个桶中,所以bucket_li=[[1,5],[],[],[],[]] 第三个元素:65 属于[50,99],因此加到第二个桶中,所以bucket_li=[[1,5],[65,,],[],[],[]] 第四个元素:100 属于[100,199],因此加到第三个桶中,所以bucket_li=[[1,5],[65,],[100,],[],[]] 第五个元素:3000 超过了最大桶的[200,249]范围,因此加到最后一个桶中,所以bucket_li=[[1,5],[65,],[100,],[],[3000,]] 第六个元素:990 超过了最大桶[200,249]范围,因此加到最后一个桶中,所以bucket_li=[[1,5],[65,],[100,],[],[990,3000]] tips:每次入桶之后,都要保持桶是有序的! 最后将所有桶按顺序拼接在一起就得到了有序的序列:[1,5,65,100,990,3000] '''
源码
# 桶排序
@clocked
def bucket_sort(li, n=100, size=100):
# 创建桶列表 n个桶
bucket_li = [[] for i in range(n)]
for cur in li:
bucket_index = cur // size # 当前元素应放的桶的索引
if bucket_index > n - 1: bucket_index = n - 1 # 如果超出范围,将它放到最后一个桶中
# 插入后需要保证桶的有序
if len(bucket_li[bucket_index]) == 0:
bucket_li[bucket_index].append(cur)
else:
for i in range(len(bucket_li[bucket_index])):
if cur < bucket_li[bucket_index][i]:
bucket_li[bucket_index].insert(i, cur)
break
else:
bucket_li[bucket_index].append(cur)
# bucket_li[bucket_index].sort()
print(bucket_li)
# 将所有桶按顺序拼接起来
li.clear()
for bucket in bucket_li: li.extend(bucket)
测试
同步更新于个人博客系统:python实现桶排序,听这名字挺奇怪的?