引言
本篇是排序算法的第八篇,桶排序,桶排序是計數排序的升級版。
1、算法步驟
1、設定一個基準,將待排序的數字按照一定範圍,從小到大的平均分在N個桶中,此時桶已經排好序,桶中的元素還未排序;
2、將桶中的元素進行排序。
3、將每個桶按照從小到大的編號,依次取出裏面的元素放入到待排序數組中,排序完成。
2、時間複雜度
平均時間複雜度O(n + k)
3、算法實現
public class BucketSort {
public static void main(String[] args) {
int[] numbers = {12,2,24,30,6,16};
int[] result = BucketSort.bucketSort(numbers,3);
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < result.length; i++) {
stringBuffer.append(result[i] + " ");
}
System.out.println(stringBuffer.toString());
}
//bucketSize是初始化桶個數的一個基準值
public static int[] bucketSort(int[] arg,int bucketSize){
if(arg.length == 0){
return arg;
}
int maxValue = arg[0];
int minVaule = arg[0];
for (int i = 1; i < arg.length; i++) {
if(arg[i] < minVaule){
minVaule = arg[i];
} else if(arg[i] > maxValue){
maxValue = arg[i];
}
}
//桶的數量
int bucketCount = (int)Math.floor((maxValue - minVaule) / bucketSize) + 1;
//初始化一個二維數組,橫座標是桶的編號,縱座標是值
int[][] buckets = new int[bucketCount][0];
//將待排序值按照一定規則映射到數組中
for (int i = 0; i < arg.length; i++) {
int index = (int)Math.floor((arg[i] - minVaule) / bucketSize);
buckets[index] = arrAppend(buckets[index], arg[i]);
}
int arrIndex = 0;
//循環每個桶
for (int i = 0; i < buckets.length; i++) {
if(buckets[i].length <= 0){
continue;
}
//將每個桶中的數組按照插入排序算法進行排序
int[] bucket = insertSort(buckets[i]);
//按照桶的順序,將桶中排好序的值,依次放入到數組中
for (int j = 0; j < bucket.length; j++) {
arg[arrIndex++] = bucket[j];
}
}
return arg;
}
//插入排序算法
public static int[] insertSort(int[] arr){
for (int i = 1; i < arr.length; i++) {
// 記錄要插入的數據
int tmp = arr[i];
// 從已經排序的序列最右邊的開始比較,找到比其小的數
int j = i;
while (j > 0 && tmp < arr[j - 1]) {
arr[j] = arr[j - 1];
j--;
}
// 存在比其小的數,插入
if (j != i) {
arr[j] = tmp;
}
}
return arr;
}
//自動擴容,並保存數據
public static int[] arrAppend(int[] arr,int value){
arr = Arrays.copyOf(arr, arr.length + 1);
arr[arr.length - 1] = value;
return arr;
}
}
結束語
桶排序的高效與否的關鍵就在於這個映射函數的確定,在空間足夠的時候,儘量增加桶的數量,將數據儘量均勻的分到K個桶中。