基於桶的排序之計數排序
作者:Grey
原文地址:
說明
基於桶的排序有兩種,分別是計數排序和基數排序。
但是這兩種排序應用範圍有限,需要樣本的資料狀況滿足桶的劃分
計數排序
這個排序適用於非負數陣列,如果包含負數,需要先將負數轉換成正數,處理邏輯如下
如果陣列最小值是負數,假設最小值為 min,則把陣列中所有的數加上(-min),就轉換成了非負陣列,最後排序結束後,再統一減去(-min)即可。
整個排序流程如下,首先獲取到整個陣列的最大值,假設是 max,則可以確定,陣列中的所有數都不超過 max,所以,只需要開闢一個長度為 max + 1 的陣列,假設為 helper,然後遍歷原始陣列 arr, 將
helper[arr[i]]++
helper[i]
表示原始陣列中 i 這個值出現的的次數
最後從 0 到 max 依次取出 helper 陣列中的非 0 值,就是排序後的結果。
例如: arr 陣列是如下資料
int[] arr = {1,4,3,3,6,4,5}
arr 中的最大值是 6,得到的 helper 陣列長度是 7,每個數出現的次數記錄在 helper 中以後,helper 陣列如下:
int[] helper = {0,1,0,2,2,1,1}
然後找 helper 中不等於 0 的值,
helper[1] = 1; // 1 這個值出現了1次
helper[3] = 2; // 3 這個值出現了2次
helper[4] = 2; // 4 這個值出現了2次
helper[5] = 1; // 5 這個值出現了1次
helper[6] = 1; // 6 這個值出現了1次
然後按順序依次寫回 arr 中去
int[] arr = {1, 3, 3, 4, 4, 5, 6}
完整程式碼如下
public class Code_CountSort {
// 非負數
public static void countSort(int[] arr) {
if (null == arr || arr.length <= 1) {
return;
}
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
max = Math.max(arr[i], max);
}
int[] help = new int[max + 1];
for (int j : arr) {
help[j]++;
}
int t = 0;
for (int i = 0; i < help.length; i++) {
while (help[i] != 0) {
arr[t++] = i;
help[i]--;
}
}
}
}
時間複雜度為O(N)
,額外空間複雜度為O(M)
,其中 M 是陣列的最大值。