百度百科上对于桶排序的描述是这样的:
桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。
说的更清楚一些,可以这样理解:假设现在全国有500w考生参加考试,我们现在需要对所有考生的成绩进行排序,那么即便用我们前面讲过的“归并排序”,“快速排序”等方法也依然计算量庞大。然而,我们假设如果考试的卷子都一样,满分100,那么,所有人的成绩就有了一个值域:[0, 100],如果情况再特殊一点,老师批卷子只给整数分,那么所有人的成绩就最多只有101中可能性了。
原理非常简单,但是可以稍微复杂一点,实现原地(in - place)桶排序:
需要注意的是:这两段代码都是非常脆弱的,只能对从1开始的连续的, 不重复的正整数排序。当然,现实操作中可根据情况做相应修改
桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。
说的更清楚一些,可以这样理解:假设现在全国有500w考生参加考试,我们现在需要对所有考生的成绩进行排序,那么即便用我们前面讲过的“归并排序”,“快速排序”等方法也依然计算量庞大。然而,我们假设如果考试的卷子都一样,满分100,那么,所有人的成绩就有了一个值域:[0, 100],如果情况再特殊一点,老师批卷子只给整数分,那么所有人的成绩就最多只有101中可能性了。
好了,现在我们建立101个“桶”,分别标有“0~100”的编号,如果对于相同分数的同学排名不分先后的话,我们可以这样排序:扫描整个数组(长500w的成绩数据),将相应的成绩同学信息“扔”进和他分数一样编号的桶中。如下图:
现在,只需对数组遍历一次,就完成了排序。时间复杂度:O(n),优于快速排序等比较排序的时间效率。总结一下:
1. 如果这个问题再复杂一点,比如分数可以出现小数。那么我们就设立桶的编号为一个区间,在这个区间内的分数所代表的学生信息被“扔”进来,然后再对这个桶内所有的数据使用别的排序或者递归地使用更加细分的桶排序(正如开篇给出的定义那样)。
2. 桶排序有局限性,如果需要排序的数据可能的结果非常多(例如不是[0, 100],而是[0, 1000000000000000])那么我们需要建立的桶的个数也就非常多,这是很不划算的,一般不选择。
搞明白了基本原理,代码实现也就很简单了,我们可以尝试对一组连续的,不重复的,且无序的正整数排序,例如:[6,5,3,1,8,7,2,4],是由从1到8,8个连续的正整数构成的无序数组。
def bucket_sort(aList):
n = len(aList)
result = [0 for i in range(n)]
for i in range(n):
result[aList[i] - 1] = aList[i]
return result
原理非常简单,但是可以稍微复杂一点,实现原地(in - place)桶排序:
def bucket_sort(aList):
n = len(aList)
for i in range(n):
# aList第i位不符合,一直执行此循环
while aList[i] != i + 1:
# 以下三行代码实现aList[i]与aList[aList[i] - 1]的交换
temp = aList[i]
aList[i] = aList[temp - 1]
aList[temp - 1] = temp
需要注意的是:这两段代码都是非常脆弱的,只能对从1开始的连续的, 不重复的正整数排序。当然,现实操作中可根据情况做相应修改