JAVA十大排序算法之桶排序詳解

桶排序

桶排序是計數排序的升級,計數排序可以看成每個桶隻存儲相同元素,而桶排序每個桶存儲一定范圍的元素,通過函數的某種映射關系,將待排序數組中的元素映射到各個對應的桶中,對每個桶中的元素進行排序(有可能再使用別的排序算法或是以遞歸方式繼續使用桶排序),最後將非空桶中的元素逐個放入原序列中。

桶排序需要盡量保證元素分散均勻,否則當所有數據集中在同一個桶中時,桶排序失效。

image-20210808133137559

代碼實現

1.找出數組中的最大值max和最小值min,可以確定出數組所在范圍min~max

2.根據數據范圍確定桶的數量

1.若桶的數量太少,則桶排序失效

2.若桶的數量太多,則有的桶可能,沒有數據造成空間浪費

所以桶的數量由我們自己來確定,但盡量讓元素平均分佈到每一個桶裡,這裡提供一個方式

(最大值 – 最小值)/每個桶所能放置多少個不同數值+1

3.確定桶的區間,一般是按照(最大值 – 最小值)/桶的數量來劃分的,且左閉右開

public class BucketSort {
    public static final int[] ARRAY = {35, 23, 48, 9, 16, 24, 5, 11, 32, 17};
    /**
     * @param bucketSize 作為每個桶所能放置多少個不同數值,即數值的類型
     *                   例如當BucketSize==5時,該桶可以存放{1,2,3,4,5}這幾種數字,
     *                   但是容量不限,即可以存放100個3
     */
    public static List<Integer> sort(List<Integer> array, int bucketSize) {
        if (array == null || array.size() < 2)
            return array;
        int max = array.get(0), min = array.get(0);
        // 找到最大值最小值
        for (int i = 0; i < array.size(); i++) {
            if (array.get(i) > max)
                max = array.get(i);
            if (array.get(i) < min)
                min = array.get(i);
        }
        //獲取桶的數量
        int bucketCount = (max - min) / bucketSize + 1;
        //構建桶,初始化
        List<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketCount);
        List<Integer> resultArr = new ArrayList<>();
        for (int i = 0; i < bucketCount; i++) {
            bucketArr.add(new ArrayList<>());
        }
        //將原數組的數據分配到桶中
        for (int i = 0; i < array.size(); i++) {
            //區間范圍
            bucketArr.get((array.get(i) - min) / bucketSize).add(array.get(i));
        }
        for (int i = 0; i < bucketCount; i++) {
            if (bucketSize == 1) {
                for (int j = 0; j < bucketArr.get(i).size(); j++)
                    resultArr.add(bucketArr.get(i).get(j));
            } else {
                if (bucketCount == 1)
                    bucketSize--;
                //對桶中的數據再次用桶進行排序
                List<Integer> temp = sort(bucketArr.get(i), bucketSize);
                for (int j = 0; j < temp.size(); j++)
                    resultArr.add(temp.get(j));
            }
        }
        return resultArr;
    }
    public static void print(List<Integer> array) {
        for (int i : array) {
            System.out.print(i + "  ");
        }
        System.out.println("");
    }
    public static void main(String[] args) {
        print(Arrays.stream(ARRAY).boxed().collect(Collectors.toList()));
        System.out.println("============================================");
        print(sort(Arrays.stream(ARRAY).boxed().collect(Collectors.toList()), 2));
    }
}

時間復雜度

桶排序算法遍歷瞭2次原始數組,運算量為2N,最後,遍歷桶輸出排序結果的運算量為N,初始化桶的運算量為M。

對桶進行排序,不同的排序算法算法復雜度不同,冒泡排序算法復雜度為O(N^2),堆排序、歸並排序算法復雜度為O(NlogN),我們以排序算法復雜度為O(NlogN)進行計算,運算量為N/M * log(N/M) * M

最終的運算量為3N+M+N/M * log(N/M) * M,即3N+M+N(logN-logM),去掉系數,時間復雜度為O(N+M+N(logN-logM))

算法穩定性

桶排序算法在對每個桶進行排序時,若選擇穩定的排序算法,則排序後,相同元素的位置不會發生改變,所以桶排序算法是一種穩定的排序算法。

總結

本篇文章就到這裡瞭,希望能給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!

推薦閱讀: