计数排序

计数排序（）是一种稳定的线性时间排序算法。该算法于1954年由哈罗德·H·西华德提出。计数排序使用一个额外的数组formula_1，其中第i个元素是待排序数组formula_2中值等于formula_3的元素的个数。然后根据数组formula_1来将formula_2中的元素排到正确的位置。
计数排序的特征.
当输入的元素是formula_6个formula_7到formula_8之间的整数时，它的运行时间是formula_9。计数排序不是比较排序，因此不被 formula_10的下界限制。
由于用来计数的数组formula_1的长度取决于待排序数组中数据的范围（等于待排序数组的最大值与最小值的差加上1），这使得计数排序对于数据范围很大的数组，需要大量时间和内存。例如：计数排序是用来排序0到100之间的数字的最好的算法，但是它不适合按字母顺序排序人名。但是，计数排序可以用在基数排序算法中，能够更有效的排序数据范围很大的数组。
通俗地理解，例如有10个年龄不同的人，统计出有8个人的年龄比A小，那A的年龄就排在第9位，用这个方法可以得到其他每个人的位置，也就排好了序。当然，年龄有重复时需要特殊处理（保证稳定性），这就是为什么最后要反向填充目标数组，以及将每个数字的统计减去1。算法的步骤如下：
Java语言的实现.
public class CountingSort {
 public static void main(String[] args) {
 int[] A = CountingSort.countingSort(new int[]{16, 4, 10, 14, 7, 9, 3, 2, 8, 1});
 Utils.print(A);
 public static int[] countingSort(int[] A) {
 int[] B = new int[A.length];
 // 假设A中的数据a'有，0&lt;=a' &amp;&amp; a' &lt; k并且k=100
 int k = 100;
 countingSort(A, B, k);
 return B;
 private static void countingSort(int[] A, int[] B, int k) {
 int[] C = new int[k];
 // 计数
 for (int j = 0; j &lt; A.length; j++) {
 int a = A[j];
 C[a] += 1;
 Utils.print(C);
 // 求计数和
 for (int i = 1; i &lt; k; i++) {
 C[i] = C[i] + C[i - 1];
 Utils.print(C);
 // 整理
 for (int j = A.length - 1; j &gt;= 0; j--) {
 int a = A[j];
 B[C[a] - 1] = a;
 C[a] -= 1;
//针对c数组的大小，优化过的计数排序
public class CountSort{
 public static void main(String []args){
 //排序的数组
 int a[] = {100, 93, 97, 92, 96, 99, 92, 89, 93, 97, 90, 94, 92, 95};
 int b[] = countSort(a);
 for(int i : b){
 System.out.print(i + " ");
 System.out.println();
 public static int[] countSort(int []a){
 int b[] = new int[a.length];
 int max = a[0], min = a[0];
 for(int i : a){
 if(i &gt; max){
 max = i;
 if(i &lt; min){
 min = i;
 //这里k的大小是要排序的数组中，元素大小的极值差+1
 int k = max - min + 1;
 int c[] = new int[k];
 for(int i = 0; i &lt; a.length; ++i){
 c[a[i]-min] += 1;//优化过的地方，减小了数组c的大小
 for(int i = 1; i &lt; c.length; ++i){
 c[i] = c[i] + c[i-1];
 for(int i = a.length-1; i &gt;= 0; --i){
 b[--c[a[i]-min]] = a[i];//按存取的方式取出c的元素
 return b;
//另一种参考，
//缺点:不适合数据落差大、浮点数，数据落差大会生成大a数组，数少用其他演算更好。
//优点:线性快，固定重复巨量数据适用，没有更快，理论，只统计，不做多余运算或搬移。
import java.util.Arrays;
import java.util.Random;
public class Csoft {
 public static void main(String[] args) {
 // int arr[] = { -535000000, 0, -372, -299,830000}; 
 // int arr[] = {100, 93, 97, 92, 96, 99, 92, 89, 93, 97, 90, 94, 0, -1,-1,-95};
 // int arr[] = Random_Numbers(500000000); 
 int arr[] = Random_Numbers(20); 
 System.out.println(Arrays.toString(arr));
 new Csoft(arr);
 System.out.println(Arrays.toString(arr));
 private int min;
 Csoft(int[] arr) {
 b(arr);
 public static int[] b(int[] arr) {
 int max = 0, min = 0;
 for (int i = 0; i &lt; arr.length; i++) {
 max = arr[i] &gt; arr[max] ? i : max;
 min = arr[i] &lt; arr[min] ? i : min;
 int k = -arr[min]; //k=基数
 max = arr[max] + 1;
 int[] a = new int[max + k];
 for (int i = 0; i &lt; arr.length; i++) {
 int o = arr[i] + k;
 a[o]++;
 int t = 0;
 for (int j = 0; j &lt; a.length; j++) {
 if (a[j] &gt; 0) {
 for (int i = 0; i &lt; a[j]; i++) {
 arr[t] = j - k;
 t++;
 return arr;
 public static int[] Random_Numbers(int num) { //乱数负数
 Random r = new Random();
 int[] c = new int[num];
 for (int i = 0; i &lt; num; i++) {
 c[i] = r.nextInt(1000) - 500;
 return c;
C语言的实现.
void print_arr(const int *arr, const int n) {
 printf("%d", arr[0]);
 for (int i = 1; i &lt; n; i++)
 printf(" %d", arr[i]);
 printf("\n");
void counting_sort(const int *ini_arr, int *sorted_arr, const int n, const int max_val) {
 int *count_arr = (int *) calloc(max_val, sizeof(int));
 for (int i = 0; i &lt; n; i++)
 count_arr[ini_arr[i]]++;
 for (int i = 1; i &lt; max_val; i++)
 count_arr[i] += count_arr[i - 1];
 for (int i = n; i &gt; 0; i--)
 sorted_arr[--count_arr[ini_arr[i - 1]]] = ini_arr[i - 1];
 free(count_arr);
int main(int argc, char **argv) {
 int n = 10;
 int max_val = 100;
 int *arr = (int *) calloc(n, sizeof(int));
 int *sorted_arr = (int *) calloc(n, sizeof(int));
 srand(time(0));
 for (int i = 0; i &lt; n; i++)
 arr[i] = rand() % max_val;
 printf("ini_array: ");
 print_arr(arr, n);
 counting_sort(arr, sorted_arr, n, max_val);
 printf("sorted_array: ");
 print_arr(sorted_arr, n);
 free(arr);
 free(sorted_arr);
 return 0;
javascript实现.
Array.prototype.countSort = function() {
 const C = []
 for(let i = 0; i &lt; this.length; i++) {
 const j = this[i]
 C[j] &gt;= 1 ? C[j] ++ : (C[j] = 1)
 const D = []
 for(let j = 0; j &lt; C.length; j++) {
 if(C[j]) {
 while(C[j] &gt; 0) {
 D.push(j)
 C[j]--
 return D
const arr = [11, 9, 6, 8, 1, 3, 5, 1, 1, 0, 100]
console.log(arr.countSort())
Golang的实现.
 func countingSort(arr []int, minvalue, maxValue int) []int {
 bucketLen := maxValue - minvalue + 1
 bucket := make([]int, bucketLen)
 for _, v := range arr {
 bucket[v-minvalue]++
 result := make([]int, len(arr))
 index := 0
 for k, v := range bucket {
 kk := k + minvalue
 for j := v; j &gt; 0; j-- {
 result[index] = kk
 index++
 return result
Python3的实现.
def count_sort(a: list) -&gt; list:
 a_min: int = min(a)
 k: int = max(a) - a_min + 1
 c: list = [0 for _ in range(k)]
 for i in a:
 c[i - a_min] += 1
 for i, v in enumerate(c):
 if i == 0:
 continue
 c[i] = v + c[i-1]
 result: list = [None for _ in range(len(a))]
 for i in a:
 result[c[i - a_min] - 1] = i
 c[i - a_min] -= 1
 return result
if __name__ == '__main__':
 print(count_sort([652, 721, 177, 977, 24, 17, 126, 515, 442, 917]))