排序算法之桶排序【Java版】

引言

本篇是排序算法的第八篇,桶排序,桶排序是計數排序的升級版。

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個桶中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章