1. 原理
計數排序不是基於比較的排序算法,其核心在於將輸入的數據值轉化爲鍵存儲在額外開闢的數組空間中。 作爲一種線性時間複雜度的排序,計數排序要求輸入的數據必須是有確定範圍的整數。
計數排序(Counting sort)是一種穩定的排序算法。計數排序使用一個額外的數組C,其中第i個元素是待排序數組A中值等於i的元素的個數。然後根據數組C來將A中的元素排到正確的位置。它只能對整數進行排序。
2. 算法描述
- 找出待排序的數組中最大和最小的元素;
- 統計數組中每個值爲i的元素出現的次數,存入數組C的第i項;
- 對所有的計數累加(從C中的第一個元素開始,每一項和前一項相加);
- 反向填充目標數組:將每個元素i放在新數組的第C(i)項,每放一個元素就將C(i)減去1。
3. 算法分析
當輸入的元素是n個0到k之間的整數時,它的運行時間是 O(n + k)。計數排序不是比較排序,排序的速度快於任何比較排序算法。由於用來計數的數組C的長度取決於待排序數組中數據的範圍(等於待排序數組的最大值與最小值的差加上1),這使得計數排序對於數據範圍很大的數組,需要大量時間和內存。
排序方式:out-place
時間複雜度:
最佳情況:T(n) = O(n+k)
最差情況:T(n) = O(n+k)
平均情況:T(n) = O(n+k)
空間複雜度:O(k)
4. 動圖演示
5. 代碼
public static void main(String[] args) {
int[] arrs = RandomArr.createIntArr(30, 0, 100);
int[] arrs2 = Arrays.copyOf(arrs, arrs.length);
Arrays.stream(arrs).forEach(l -> {
System.out.print(l + " ");
});
System.out.println();
CountSort(arrs);
Arrays.stream(arrs).forEach(l -> {
System.out.print(l + " ");
});
System.out.println();
Arrays.stream(arrs2).sorted().forEach(l -> {
System.out.print(l + " ");
});
}
public static void CountSort(int[] arrs) {
// 1、先找到其最大值
int index = 0;
for (int i = 1; i < arrs.length; i++) {
if (arrs[i] > arrs[index]) {
index = i;
}
}
// 2、創建最大值長度的數組
int[] arrC = new int[arrs[index] + 1];
// 3、對待排序數組進行反相統計
for (int i = 0; i < arrs.length; i++) {
arrC[arrs[i]]++;
}
// 4、排序輸出
index = 0;
for (int i = 0; i < arrs.length; i++) {
for (; ; ) {
if (arrC[index]-- > 0) {
arrs[i] = index;
break;
}
index++;
}
}
}