桶排序 (Bucket Sort) 又称箱排序,是鸽巢排序的一种归纳结果(有关鸽巢排序的内容留待后补)。
桶排序是比较特殊的排序,它不属于比较排序,即有序的建立不是基于元素的比较与交换而消除逆序得到的,比较形象的讲,其对有序的建立是基于桶数组在物理内存上本身的连续性和有序性,将其作为索引,然后建立该索引与待排序数组的映射关系,然后通过遍历索引而倾倒出待排序元素,则倾倒的过程自然遵循桶数组的物理内存连续性而得到有序的结果。基于这一分析,桶排序不受到 O(nlogn) 的下限影响。
其工作的过程是先建立有限个数量的桶,每个桶内可以使用别的排序。然后将元素投入对应的桶中,对每个子桶进行排序。完成以后依次将子桶中的元素倒出到原始数组,得到结果。
比较特殊的情况是建立的桶的数量与待排序数组中的最大元素减去最小元素再加一的个数相同,这样的话可以实现一对一的映射,也免去了对子桶的排序。举例来说,如果原数组中有元素3,则 Bucket[3]++; 这样还有一个附加的好处是,重复的元素只要对应的桶再加一即可,在倾倒的时候,只要桶不为空则继续倾倒,也很好实现。下面的java代码给出的正是这种桶排序的实现。
java代码实现 (该实现中默认已知输入的最小值是0,实际上这是不太恰当的,比较好的做法是对最大最小值都寻找,然后分配桶空间):
//This algorithm is limited and impractical because there exists a pre-assumption
//for the input. In this case the minimum input cannot be negative and the maximum
//input should be reachable.
public class BucketSort{
public static void BucketSort(Integer[] a){
//Find the max
int max=a[0];
for(int i=0;i<a.length;i++)
if(a[i]>max) max=a[i];
// System.out.println("max="+max);
//Fill the bucket;
int[] Bucket=new int[max+1];
for(int i=0;i<a.length;i++){
Bucket[a[i]]++;
}
/* System.out.println("Bucket status:");
for(int i=0;i<Bucket.length;i++) System.out.print(Bucket[i]+" ");
System.out.println();
*/
//Dump back into the array from the bucket;
int j=0;
for(int i=0;i<=max;i++){
while(Bucket[i]!=0){
a[j]=i;
Bucket[i]--;
j++;
}
}
}
public static void main(String[] args){
System.out.println("Bucket Sort:");
Integer[] elements={3,4,1,8,10,2,0,6,5};
System.out.print("Original elements: ");
for(int i=0;i<elements.length;i++) System.out.print(elements[i]+" ");
System.out.println();
BucketSort(elements);
System.out.print("After sorting: ");
for(int i=0;i<elements.length;i++) System.out.print(elements[i]+" ");
System.out.println();
}
}
平均时间复杂度:O(n+k).
附图一张,图中的情况是每个桶是作为一个数据范围的索引,与代码实现的不太一样: