计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(n*log(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(n*log(n)), 如归并排序,堆排序)
1. 算法步骤
1、找出待排序的数组中最大和最小的元素
2、统计数组中每个值为i的元素出现的次数,存入数组C的第i项
3、对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)
4、反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1
2. 动图演示
3. 时间复杂度
复杂度为Ο(n+k)(其中k是整数的范围)
4. 算法实现
计数排序C语言
#include<stdio.h> #include<stdlib.h> #define MAXNUM 10 void main() { void CountSort(int data[],int n); int i,data[MAXNUM]; for(i=0;i<MAXNUM;i++) scanf("%d",&data[i]); CountSort(data,MAXNUM); for(i=0;i<MAXNUM;i++) printf("%d ",data[i]); printf("\n"); } void CountSort(int data[],int n) { int i,j,count,*data_p,temp; data_p=(int*)malloc(sizeof(int)*n); for(i=0;i<n;i++)//初始化data_p data_p[i]=0; for(i=0;i<n;i++) { count=0; for(j=0;j<n;j++)//扫描待排序数组 if(data[j]<data[i])//统计比data[i]值小的值的个数 count++; while(data_p[count]!=0)//对于相等非0的数据,应向后措一位。数据为0时,因数组data_p被初始化为0,故不受影响。 /* 注意此处应使用while循环进行判断,若用if条件则超过三个重复值后有0出现 */ count++; data_p[count]=data[i];//存放到data_p中的对应位置 } //用于检查当有多个数相同时的情况 i=0,j=n; while(i<j) { if(data_p[i]==0) { temp=i-1; data_p[i]=data_p[temp]; }//of if i++; }//of while for(i=0;i<n;i++)//把排序完的数据复制到data中 data[i]=data_p[i]; free(data_p);//释放data_p }
计数排序C++
#include <iostream> using namespace std; const int MAXN = 100000; const int k = 1000; // range(范围) int a[MAXN], c[MAXN], ranked[MAXN]; int main() { int n; cin >> n; for (int i = 0; i < n; ++i) { cin >> a[i]; ++c[a[i]]; } for (int i = 1; i < k; ++i) c[i] += c[i-1]; for (int i = n-1; i >= 0; --i) ranked[--c[a[i]]] = a[i];//如果是i表达的是原数标号,a[i]就是排序后的正确序列 for (int i = 0; i < n; ++i) cout << ranked[i] << endl; return 0; }
计数排序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; if($len !== null){ for($j = 0; $j < $len; $j++){ $arr[$sortedIndex++] = $key; } } } return $arr; }
计数排序JAVA
//针对c数组的大小,优化过的计数排序 publicclassCountSort{ publicstaticvoidmain(String[]args){ //排序的数组 int a[]={100,93,97,92,96,99,92,89,93,97,90,94,92,95}; int b[]=countSort(a); for(inti: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>max){ max=i; } if(i<min){ min=i; } }//这里k的大小是要排序的数组中,元素大小的极值差+1 int k=max-min+1; int c[]=new int[k]; for(int i=0;i<a.length;++i){ c[a[i]-min]+=1;//优化过的地方,减小了数组c的大小 } for(int i=1;i<c.length;++i){ c[i]=c[i]+c[i-1]; } for(int i=a.length-1;i>=0;--i){ b[--c[a[i]-min]]=a[i];//按存取的方式取出c的元素 } return b; } }
计数排序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; }
计数排序C#语言
public int[] CountSort(int[] a) { int[] b = new int[a.Length]; int max = a[0]; int min = a[0]; foreach (int item in a) { if(item > max) { max = item; } else if (item < min) { min = item; } } int k = max - min + 1; int[] c = new int[k]; for (int i = 0; i < a.Length; i++) { c[a[i] - min] += 1; } for (int i = 1; i < c.Length; i++) { c[i] = c[i] + c[i - 1]; } for (int i = a.Length-1; i >= 0; i--) { b[--c[a[i] - min]] = a[i]; } return b; }
计数排序Python
def count_sort(input_list): length = len(input_list) if length < 2: return input_list max_num = max(input_list) count = [0] * (max_num + 1) for element in input_list: count[element] += 1 output_list = [] for i in range(max_num + 1): for j in range(count[i]): # count[i]表示元素i出现的次数,如果有多次,通过循环重复追加 output_list.append(i) return output_list
计数排序Go语言
func countSort(arr []int) { maxVal := 0 length := len(arr) for i := 0; i < length; i ++ { if arr[i] > maxVal { maxVal = arr[i] } } tmp := make([]int, maxVal+1) for i := 0; i < length; i ++ { tmp[arr[i]] += 1 } j := 0 for i := 0; i < maxVal+1; i ++ { for tmp[i] > 0 { arr[j] = i j ++ tmp[i] -- } } }
计数排序PASCAL
实现方法1: program counting_sort1; var a,b,c:Array[1..max] of longint; i,j,k,n:longint; begin readln(n); for i:=1 to n do read(a[i]); fillchar(c,sizeof(c),0); for j:=1 to n do inc(c[a[j]]); for i:=2 to x{x是大于a[i]中任意值的任意数且x≤max}do c[i]:=c[i]+c[i-1]; for j:=n downto 1 do begin b[c[a[j]]]:=a[j]; dec(c[a[j]]); end; for i:=1 to n do writeln(b[i],' '); end. 实现方法2: program counting_sort2; const max=100; var a:array[1..max] of longint; i,j,k,n,m,x:longint; begin readln(n); fillchar(a,sizeof(a),0);//初始清空 m:=0; for i:=1 to n do begin read(x); inc(a[x]); if x>m then m:=x;//找到最大的数 end; for i:=1 to m do if a[i]>0 then for j:=1 to a[i] do write(i,' '); end.