計數排序 可在線性時間 即O(n)時間內完成排序。而前幾節中的排序,如插入排序、歸併排序、快速排序、堆排序、希爾排序這幾種
都屬於比較排序,即是排序中均通過比較的方法,且可以證明無論何種比較排序,總的比較次數下確界爲 O(nlogn),性能無法再提高
計數排序是線性時間內完成的排序,其基本思想:
不通過元素的比較,而是通過統計比元素data[i]或者大的元素有多少個,知道這個信息等於知道data[ i ]插入的位置
而統計的基本方法 就是計數。
假設知道待排序的數組 中數值的最大值,即假定data[] 數據,最大值爲K,分佈爲0 ~ k
所以需要一個臨時的計數數組cnt[]來統計 data[]中沒一個數值有多少個 則length( cnt[] )=k+1;
還需要一個與 data 同樣長度的數組 newdata[]來將data[ ]中的元素,根據cnt[ ]的信息插入到 newdata中去
這就是計數排序的基本思想及步驟。
下面用代碼實現:
爲了使思路更清晰,代碼比較多,可以優化:對於純粹數組,則newdata可以省略實現原地排序,因爲cnt的下標即爲data元素數值,對於其他結構則不可以
/*********** counting sort***************/
void CountingSort(int data[],int len,int k) //the value of data distribute from 0 to k k is the max value
{
int *cnt=(int*)malloc((k+1)*sizeof(int)); // get array memory
int *newdata=(int*)malloc(len*sizeof(int)); //new data
int i;
for (i=0;i<=k;i++) //assign cnt array
cnt[i]=0;
for (i=0;i<len;i++) //包含等於i的元素個數
cnt[data[i]]++;
for (i=1;i<=k;i++) //包含小於等於i的元素個數
cnt[i]+= cnt[i-1];
for (i=len-1;i>=0;i--) //根據cnt array直接賦值給newdata,即可完成排序
{
newdata[cnt[data[i]]-1]=data[i]; //-1是因爲數組下標從0開始
cnt[data[i]]--;
}
for (i=0;i<len;i++) //重新賦值給原數組
data[i]=newdata[i];
free(cnt);
free(newdata);
}
算法分析:主要分爲兩部分,以上cnt的賦值操作 運行時間爲O(K),後面是data的計數操作,運行時間爲O(N),
故總的運行時間爲O(k+n)
雖然計數排序能在線性時間內完成排序,效率極高,但必須知道待排序數據的範圍,以及待排序數據分佈不可以太零散,需比較集中