計數排序(Counting sort)是一種穩定的線性時間排序算法。計數排序使用一個額外的數組C,其中第i個元素是待排序數組A中值等於i的元素的個數。然后根據數組C來將A中的元素排到正確的位置。
本文地址:http://www.cnblogs.com/archimedes/p/counting-sort-algorithm.html,轉載請注明源地址。
計數排序的特征
當輸入的元素是 n 個 0 到 k 之間的整數時,它的運行時間是 Θ(n + k)。計數排序不是比較排序,排序的速度快於任何比較排序算法。
由於用來計數的數組C的長度取決於待排序數組中數據的范圍(等於待排序數組的最大值與最小值的差加上1),這使得計數排序對於數據范圍很大的數組,需要大量時間和內存。例如:計數排序是用來排序0到100之間的數字的最好的算法,但是它不適合按字母順序排序人名。但是,計數排序可以用在基數排序中的算法來排序數據范圍很大的數組。
通俗地理解,例如有10個年齡不同的人,統計出有8個人的年齡比A小,那A的年齡就排在第9位,用這個方法可以得到其他每個人的位置,也就排好了序。當然,年齡有重復時需要特殊處理(保證穩定性),這就是為什么最后要反向填充目標數組,以及將每個數字的統計減去1的原因。
算法的步驟如下:
-
找出待排序的數組中最大和最小的元素
-
統計數組中每個值為i的元素出現的次數,存入數組C的第i項
-
對所有的計數累加(從C中的第一個元素開始,每一項和前一項相加)
-
反向填充目標數組:將每個元素i放在新數組的第C(i)項,每放一個元素就將C(i)減去1
對於數據2 5 3 0 2 3 0 3程序執行的過程如下圖所示:
算法實現
C代碼如下:
// Completed on 2014.10.10 20:37 // Language: C99 // // 版權所有(C)codingwu (mail: oskernel@126.com) // 博客地址:http://www.cnblogs.com/archimedes/ #include<stdio.h> #include<stdlib.h> int* countingSort(int *a, int n, int k) { int c[k + 1], i, value, pos; int *b = (int *)malloc(n * sizeof(int)); for(i = 0; i <= k; i++) //初始化 c[i] = 0; for(i = 0; i < n; i++) c[a[i]]++; for(i = 1; i <= k; i++) c[i] = c[i] + c[i - 1]; for(i = n - 1; i >= 0; i--) { value = a[i]; pos = c[value]; b[pos - 1] = value; c[value]--; } return b; } int maxArr(int *a, int n) //返回數組中最大的元素 { int i, max; max = a[0]; i = 1; int *p; p = a + 1; while(i++ < n) { if(max < *p) max = *p; p++; } return max; } int main() { int a[] = {2, 5, 3, 0, 2, 3, 0, 3}; int N, max; N = sizeof(a) / sizeof(a[0]); max = maxArr(a, N); int *p = countingSort(a, N, max); for(int k = 0; k < N; k++) printf("%d ", p[k]); printf("\n"); free(p); return 0; }
對代碼有疑惑的可以參考《C語言指針傳遞詳解》