# 在计数排序中,如果元素的范围比较大(比如在到1亿之间)如何改造算法?
# 桶排序(Bucket Sort):首先将元素分在不同的桶中,在对每个桶中的元素排序
# 桶排序的表现取决于数据的分布。也就是需要对不同数据排序时采取不同的分桶策略。
# 平均情况时间复杂度:O(n+k)
# 最坏情况时间复杂度:O(n2k)
# 空间复杂度:O(nk)
def bucket_sort(li, n= 100, max_num=10000): #li:列表, n:我们需要创建的桶的个数 max_num:在排序的列表中,最大的值
buckets = [[] for _ in range(n)] # 创建桶 , _ :表示占位符。二维列表中创建一个空的一维列表
# 循环我们创建的桶
for var in li: # 循环需要排序的列表
i = min(var // (max_num // n), n-1) #min作用,当存在比我们设定的最大值还大的值存在的时候,把这个值存到最大的桶里面d
# i:表示var(var :列表里循环出来的数字)需要放到几号桶
# var // (max_num // n):循环出来的数字 除以(排序列表中最大的值 除以 我们创建的桶)
# n-1:表示我们桶的索引总数
buckets[i].append(var) # var数字 放到 桶[i]
# 进行桶内排序
for j in range(len(buckets[i])-1, 0, -1): # len(buckets[i])-1:桶索引 ; 0 :从第二个值的索引; -1:最后一个值的索引 j : 表示循环出来桶的编号
# 我们没有从第一个值开始循环,是为了把这个值的空位留下来,作为需要插入排序等待其他值比较后有位置放值
if buckets[i][j] < buckets[i][j-1]: # 前面的桶比后面的桶小 第i,j个桶 小于 第i,j-1 个桶 (为了比较i桶 与 i-1桶 的大小)
buckets[i][j], buckets[i][j-1] = buckets[i][j-1], buckets[i][j-1] # 两个桶交换位置
else: # 否则
break
sorted_li = [] #创建空列表
for buc in buckets: # 循环我们的二维列表的桶(buckets), buc:我们一维列表的桶
sorted_li.extend(buc) # 把我们的列表(sorted_li)加到一维列表(buc)的桶里面
return sorted_li # 返回列表
import random
li = [random.randint(0, 10000) for i in range(1000)]
li = bucket_sort(li)
print(li)