桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。桶排序 (Bucket sort)的工作的原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。
一 桶排序思路
先扫描一遍序列求出最大值 maxV 和最小值 minV ,设桶的个数为 k ,则把区间 [minV, maxV] 均匀划分成 k 个区间,每个区间就是一个桶。将序列中的元素分配到各自的桶。然后对每个桶内的元素进行排序,可以选择任意一种排序算法。最后将各个桶中的元素合并成一个大的有序序列。
假设数据是均匀分布的,则每个桶的元素平均个数为 n/k, 。假设选择用快速排序对每个桶内的元素进行排序,那么每个桶排序的时间复杂度为 O((n/k)log(n/k)) ,总的时间复杂度为:
O(n)+O(k)O((n/k)log(n/k)) = O(n+nlog(n/k)) = O(n+nlogn-nlogk )。
当 k 接近于 n 时,桶排序的时间复杂度就可以近似认为是 O(n) 的。即桶越多,时间效率就越高,而桶越多,空间就越大。
二 实现
package com.sort.s09bucketsort;
import com.sort.s06quicksort.QuickSort;
import org.junit.Test;
import java.util.Arrays;
public class BucketSort {
private int default_bucketSize = 1;
public int[] sort(int[] array,int bucketSize){
if(null == array || array.length<2){
return array;
}
bucketSize = bucketSize<default_bucketSize?default_bucketSize:bucketSize;
int[] arrayToSot = Arrays.copyOf(array,array.length);
return bucketSort(arrayToSot,bucketSize);
}
private int[] bucketSort(int[] arr,int bucketSize){
/** 找到最大值和最小值 */
int minValue = arr[0];
int maxValue = arr[0];
for (int value : arr) {
minValue = value<minValue?value:minValue;
maxValue = value>maxValue?value:maxValue;
}
/** 计算桶的数量,并对桶进行初始化 */
int bucketCount = (int) Math.floor((maxValue - minValue) / bucketSize) + 1;
int[][] buckets = new int[bucketCount][0];
/** 利用映射函数将数据分配到各个桶中 */
for (int i = 0; i < arr.length; i++) {
// 计算落在哪一个桶里面
int index = (int) Math.floor((arr[i] - minValue) / bucketSize);
buckets[index] = arrAppend(buckets[index], arr[i]);
}
/** 对桶内数据进行排序 随意各种排序方式
* 这里便使用快速排序
* */
int arrIndex = 0;// 排序游标
for(int[] bucket :buckets){
QuickSort quickSort = new QuickSort();
int[] sortBucket = quickSort.quickSort(bucket);
for(int value : sortBucket){
arr[arrIndex++] = value;
}
}
return arr;
}
/**
* 自动扩容,并保存数据
* @param arr
* @param value
*/
private int[] arrAppend(int[] arr, int value) {
arr = Arrays.copyOf(arr, arr.length + 1);
arr[arr.length - 1] = value;
return arr;
}
public void println(int [] a) {
for(int x:a) {
System.out.print(" "+x);
}
System.out.println("");
}
// 1 2 3 4 4 5 6 7 8 10 12 22 30 31 34 43 50 55 100
@Test
public void testBucketSort(){
int[] nums = {5, 3, 4, 6, 7, 1, 2, 8, 4, 10, 100, 50, 30, 22, 34, 55, 43, 12, 31};
BucketSort sort = new BucketSort();
sort.println(sort.sort(nums,4));
}
}