introduction to algorithms sorting lesson_6 Counting sort (計數排序)

   計數排序 可在線性時間 即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)

雖然計數排序能在線性時間內完成排序,效率極高,但必須知道待排序數據的範圍,以及待排序數據分佈不可以太零散,需比較集中



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章