桶排序
上学第一次听到桶排序时候一脸蒙蔽,心想数据结构也学习了,有堆、栈、队列等,没听说还有个桶的数据结构。看完代码才算明白原来桶只是打个比方的意思。其实网上关于排序算法的博客一大把,写这篇的目的主要是记录一下,因为今天突然兴起撸一遍桶排序时候竟然想不起来怎么写的了,好气所以干脆记录起来,好记性不如烂笔头。算法这东西不经常用的话忘得是真快。
桶排序 (Bucket sort)或所谓的箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间(Θ(n))。但桶排序并不是 比较排序,他不受到 O(n log n) 下限的影响。
上面是百度百科的定,看完感觉解释的是啥玩意,其实所谓桶排序就是将待排序数组中的数,当做辅助数组的索引,而辅助数组索引对应的值代表这个数在原数组中出现的个数。
画个简单的草图,待排数组3,1,0,5 。 我们只需要将他们放到辅助的数组里面就行了。然后正序或者逆序遍历辅助数组就行了,所以这是个典型的以空间换时间的算法。
了解了原理实现起来就简单了,下面是java的代码实现:
public class Sort {
//待排序数组
private static int[] test={1,3,5,0,-2,9,33,-20,0};
public static void main(String[] args){
int[] result = bucketSort(test);
for (int i:result){
System.out.println(i);
}
}
private static int[] bucketSort(int[] array){
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
//找出数组中的最大值和最小值并记录下来
for (int i:array) {
min = Math.min(min,i);
max = Math.max(max,i);
}
//辅助数组的大小为max-min+1
int[] bucket = new int[max - min+1];
for (int i=0;i<array.length;i++){
//减去min是为了防止array[i]小于0,数组索引可是不能小于0的,相当于做了个偏移。++是为了记录次数
bucket[array[i] - min] ++;
}
int j = 0;
//遍历辅助数组,取出结果
for (int i=0;i<bucket.length;i++){
while (bucket[i]-- > 0){
array[j++] = i+min;
}
}
return array;
}
}
下面是运行结果,可以看到已经按照从小到大排序完成,是不是感觉也没啥难的,我倒是觉得桶排序是所有排序算法里最容易写的。
时间复杂度和空间复杂度
关于桶排序的时间复杂度网上怎么说的都有,所有特地翻了翻大学时候的课本。教科书上给的结果是:
桶排序时间复杂度为O(m+n),m是待排序数组长度、n是桶数组的长度,也就是辅助数组长度。
空间复杂度是O(m),就是桶数组的大小。