计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中. 作为一种线性时间复杂度的排序, 计数排序要求输入的数据必须是有确定范围的整数.
1. 计数排序的特征
当输入的元素是 n 个 0 到 k 之间的整数时, 它的运行时间是 Θ(n + k). 计数排序不是比较排序, 排序的速度快于任何比较排序算法.
由于用来计数的数组 C 的长度取决于待排序数组中数据的范围 (等于待排序数组的最大值与最小值的差加上 1), 这使得计数排序对于数据范围很大的数组, 需要大量时间和内存. 例如: 计数排序是用来排序 0 到 100 之间的数字的最好的算法, 但是它不适合按字母顺序排序人名. 但是, 计数排序可以用在基数排序中的算法来排序数据范围很大的数组.
通俗地理解, 例如有 10 个年龄不同的人, 统计出有 8 个人的年龄比 A 小, 那 A 的年龄就排在第 9 位, 用这个方法可以得到其他每个人的位置, 也就排好了序. 当然, 年龄有重复时需要特殊处理 (保证稳定性), 这就是为什么最后要反向填充目标数组, 以及将每个数字的统计减去 1 的原因.
算法的步骤如下:
(1) 找出待排序的数组中最大和最小的元素
(2) 统计数组中每个值为 i 的元素出现的次数, 存入数组 C 的第 i 项
(3) 对所有的计数累加 (从 C 中的第一个元素开始, 每一项和前一项相加)
(4) 反向填充目标数组: 将每个元素 i 放在新数组的第 C(i) 项, 每放一个元素就将 C(i) 减去 1
代码实现
- JavaScript
- function countingSort(arr, maxValue) {
- var bucket = new Array(maxValue+1),
- sortedIndex = 0;
- arrLen = arr.length,
- bucketLen = maxValue + 1;
- for (var i = 0; i <arrLen; i++) {
- if (!bucket[arr[i]]) {
- bucket[arr[i]] = 0;
- }
- bucket[arr[i]]++;
- }
- for (var j = 0; j < bucketLen; j++) {
- while(bucket[j]> 0) {
- arr[sortedIndex++] = j;
- bucket[j]--;
- }
- }
- return arr;
- }
- Python
- def countingSort(arr, maxValue):
- bucketLen = maxValue+1
- bucket = [0]*bucketLen
- sortedIndex =0
- arrLen = len(arr)
- for i in range(arrLen):
- if not bucket[arr[i]]:
- bucket[arr[i]]=0
- bucket[arr[i]]+=1
- for j in range(bucketLen):
- while bucket[j]>0:
- arr[sortedIndex] = j
- sortedIndex+=1
- bucket[j]-=1
- return arr
- Go
- func countingSort(arr []int, maxValue int) []int {
- bucketLen := maxValue + 1
- bucket := make([]int, bucketLen) // 初始为 0 的数组
- sortedIndex := 0
- length := len(arr)
- for i := 0; i <length; i++ {
- bucket[arr[i]] += 1
- }
- for j := 0; j < bucketLen; j++ {
- for bucket[j]> 0 {
- arr[sortedIndex] = j
- sortedIndex += 1
- bucket[j] -= 1
- }
- }
- return arr
- }
- Java
- public class CountingSort implements IArraySort {
- @Override
- public int[] sort(int[] sourceArray) throws Exception {
- // 对 arr 进行拷贝, 不改变参数内容
- int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
- int maxValue = getMaxValue(arr);
- return countingSort(arr, maxValue);
- }
- private int[] countingSort(int[] arr, int maxValue) {
- int bucketLen = maxValue + 1;
- int[] bucket = new int[bucketLen];
- for (int value : arr) {
- bucket[value]++;
- }
- int sortedIndex = 0;
- for (int j = 0; j <bucketLen; j++) {
- while (bucket[j]> 0) {
- arr[sortedIndex++] = j;
- bucket[j]--;
- }
- }
- return arr;
- }
- private int getMaxValue(int[] arr) {
- int maxValue = arr[0];
- for (int value : arr) {
- if (maxValue <value) {
- maxValue = value;
- }
- }
- return maxValue;
- }
- }
- PHP
- function countingSort($arr, $maxValue = null)
- {
- if ($maxValue === null) {
- $maxValue = max($arr);
- }
- for ($m = 0; $m < $maxValue + 1; $m++) {
- $bucket[] = null;
- }
- $arrLen = count($arr);
- for ($i = 0; $i < $arrLen; $i++) {
- if (!array_key_exists($arr[$i], $bucket)) {
- $bucket[$arr[$i]] = 0;
- }
- $bucket[$arr[$i]]++;
- }
- $sortedIndex = 0;
- foreach ($bucket as $key => $len) {
- if ($len !== null) $arr[$sortedIndex++] = $key;
- }
- return $arr;
- }
- C
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- void print_arr(int *arr, int n) {
- int i;
- printf("%d", arr[0]);
- for (i = 1; i <n; i++)
- printf("%d", arr[i]);
- printf("\n");
- }
- void counting_sort(int *ini_arr, int *sorted_arr, int n) {
- int *count_arr = (int *) malloc(sizeof(int) * 100);
- int i, j, k;
- for (k = 0; k < 100; k++)
- count_arr[k] = 0;
- for (i = 0; i < n; i++)
- count_arr[ini_arr[i]]++;
- for (k = 1; k < 100; k++)
- count_arr[k] += count_arr[k - 1];
- for (j = n; j> 0; j--)
- sorted_arr[--count_arr[ini_arr[j - 1]]] = ini_arr[j - 1];
- free(count_arr);
- }
- int main(int argc, char **argv) {
- int n = 10;
- int i;
- int *arr = (int *) malloc(sizeof(int) * n);
- int *sorted_arr = (int *) malloc(sizeof(int) * n);
- srand(time(0));
- for (i = 0; i < n; i++)
- arr[i] = rand() % 100;
- printf("ini_array:");
- print_arr(arr, n);
- counting_sort(arr, sorted_arr, n);
- printf("sorted_array:");
- print_arr(sorted_arr, n);
- free(arr);
- free(sorted_arr);
- return 0;
- }
来源: http://www.bubuko.com/infodetail-3314435.html