通用算法 -[排序算法] -計數排序

1、算法思想

計數排序是一種適合於最大值和最小值的差值不是不是很大的排序。

基本思想:就是把數組元素作爲數組的下標,然後用一個臨時數組統計該元素出現的次數,例如 temp[i] = m, 表示元素 i 一共出現了 m 次。最後再把臨時數組統計的數據從小到大彙總起來,此時彙總起來是數據是有序的。

爲方便理解我還準備了動圖:
在這裏插入圖片描述

2、代碼實現

void countSort(int[] arr) {
        if(arr == null || arr.length < 2) return arr;

        int n = arr.length;
        int max = arr[0];
        // 尋找數組的最大值
        for (int i = 1; i < n; i++) {
            if(max < arr[i])
                max = arr[i];
        }
        //創建大小爲max的臨時數組
        int[] temp = new int[max + 1];
        //統計元素i出現的次數
        for (int i = 0; i < n; i++) {
            temp[arr[i]]++;
        }
        int k = 0;
        //把臨時數組統計好的數據重寫原數組
        for (int i = 0; i <= max; i++) {
            for (int j = temp[i]; j > 0; j--) {
                arr[k++] = i;
            }
        }
       
    }

上面的代碼中,我們是根據 max 的大小來創建對應大小的數組,假如原數組只有10個元素,並且最小值爲 min = 10000,最大值爲 max = 10005,那我們創建 10005 + 1 大小的數組不是很喫虧,最大值與最小值的差值爲 5,所以我們創建大小爲6的臨時數組就可以了。

也就是說,我們創建的臨時數組大小 (max - min + 1)就可以了,然後在把 min作爲偏移量。優化之後的代碼如下所示:

void countSort(int* arr) {
        if(arr == null || arr.length < 2) return arr;
        
        int n = arr.length;
        int min = arr[0];
        int max = arr[0];
        // 尋找數組的最大值與最小值
        for (int i = 1; i < n; i++) {
            if(max < arr[i])
                max = arr[i];
            if(min > arr[i])
                min = arr[i];
        }
        int d = max - min + 1;
        //創建大小爲max的臨時數組
        int[] temp = new int[d];
        //統計元素i出現的次數
        for (int i = 0; i < n; i++) {
            temp[arr[i] - min]++;
        }
        int k = 0;
        //把臨時數組統計好的數據彙總到原數組
        for (int i = 0; i < d; i++) {
            for (int j = temp[i]; j > 0; j--) {
                arr[k++] = i + min;
            }
        }
   
 }

3、算法分析

  • 時間複雜度:O(n+k)
  • 空間複雜度:O(k)
  • 穩定性:穩定排序
  • 非原地排序
    注:K表示臨時數組的大小。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章