非交換排序-計數排序和桶排序

木子津發表於2020-11-21

計數排序

空間複雜度:O(n)
時間複雜度: O(n)
穩定

當輸入的元素是 n 個 0 到 k 之間的整數時,它的執行時間是 Θ(n + k)。計數排序不是比較排序,排序的速度快於任何比較排序演算法。

演算法的步驟如下:

  • (1)找出待排序的陣列中最大和最小的元素
  • (2)統計陣列中每個值為i的元素出現的次數,存入陣列C的第i項
  • (3)對所有的計數累加(從C中的第一個元素開始,每一項和前一項相加)
  • (4)反向填充目標陣列:將每個元素i放在新陣列的第C(i)項,每放一個元素就將C(i)減去1

https://www.runoob.com/wp-content/uploads/2019/03/countingSort.gif

桶排序

    空間複雜度:O(n)
    時間複雜度: O(n)
    穩定

桶排序是計數排序的升級版。它利用了函式的對映關係,高效與否的關鍵就在於這個對映函式的確定。為了使桶排序更加高效,我們需要做到這兩點:

  1. 在額外空間充足的情況下,儘量增大桶的數量
  2. 使用的對映函式能夠將輸入的 N 個資料均勻的分配到 K 個桶中

什麼時候最快

當輸入的資料可以均勻的分配到每一個桶中。

元素分佈在桶中:

https://www.runoob.com/wp-content/uploads/2019/03/Bucket_sort_1.svg_.png

然後,元素在每個桶中排序:

https://www.runoob.com/wp-content/uploads/2019/03/Bucket_sort_2.svg_.png

public class BucketSort {
    public static void main(String[] args) {
        int[] arr = {5,8,6,2,4,3};
        bucketSort(arr);
        for (int i : arr) {
            System.out.print(i+" ");
        }
    }

    public static void bucketSort(int[] arr){
        if (arr == null || arr.length < 2){
            return;
        }

        int max = Integer.MIN_VALUE;

        //遍歷找到最大值
        for (int i = 0; i < arr.length; i++) {
            max = Math.max(arr[i],max);
        }

        //因為考慮正整數,所以需要max+1個桶,一個桶代表一個數值,並不是範圍
        int[] bucket = new int[max + 1];
        // 放數入桶的操作,相同的數放在同一個桶中
        for (int i = 0; i < arr.length; i++){
            bucket[arr[i]]++;
        }

        int i = 0;
        //按序遍歷桶即可,桶的計數就是對應數字出現的次數
        for (int j = 0; j < bucket.length; j++) {
            //此while迴圈輸出的是第j個桶存放的數字個j
            while (bucket[j]-->0){
                arr[i++] = j;
            }
        }
    }
}

相關文章