1. 程式人生 > 其它 >圖解經典排序算法系列:計數排序

圖解經典排序算法系列:計數排序

我們之前文章裡面講到的排序基本上都是比較排序,不管是氣泡排序、快速排序還是插入排序等等,都是基於元素之間的比較來進行一個整體的排序,那有沒有一種排序是可以不用進行元素間的對比就可以完成整個序列的升序或者降序呢?當然有,計數排序就不用元素之間的相互比較,而是通過元素的下標來確定每個元素的位置從而進行排序,在某些特殊的時候,它的排序速度甚至比快速排序還要快。
舉個例子,現在有一組待排序的數字(如圖1-1所示),怎麼通過計數排序進行升序排序呢?

圖1-1
首先,通過觀察我們會發現數組裡的元素的取值範圍為0——9,於是我們可以建立一個長度為9(元素最大值)的陣列,元素的初始值都為0,如圖1-2所示:

圖1-2
遍歷原始陣列,讓每一個整數按照值對號入座,對應陣列下標的元素加1,第一個元素為8,就在陣列下標為8的元素加1(如圖1-3所示)

圖1-3
按照此方法,依次遍歷後面的元素,最後得到的結果如圖1-4所示:

圖1-4
最後,按照下標的先後順序依次將下標輸出,該下標的元素是幾,就將下標輸出幾次,最後就會得到一個順序為升序的陣列,如圖1-5所示:

圖1-5
其實從上面的步驟中可以看出來計數排序是比較簡單的排序,效率也是比較高的,但是他還是有一定的侷限性,只適合一些特殊的序列,元素數值跨度不能太大,範圍最好在0~100之間,一組數值比較相鄰的待排序序列更加適合用計數排序。
以上呢,就是對最基礎版的計數排序的詳細解釋,接下來我們來看一下怎麼把這些步驟通過C語言進行實現。
程式碼實現:

#include <stdio.h>

void sort(int *A, int *B, int len, int k)
{
            int C[k+1], i, value, pos;  // 定義一個數組C,為輔助陣列
            for(i=0; i<=k; i++)  // 為C陣列進行初始化,元素值都為0
            {
                C[i] = 0;
            }
            for(i=0; i< len; i++)  // 統計A陣列中i元素的個數
            {
                C[A[i]] ++; 
            }
            for(i=1; i<=k; i++)  // 統計A元素中小於等於I元素的個數 
            {
                C[i] = C[i] + C[i-1];
            }
            for(i=len-1; i>=0; i--)  // 進行排序,將排完序的值放到B陣列中
            {
                value = A[i];
                pos = C[value];
                B[pos-1] = value;
 C[value]--;                                                                                                       
            }
}
int main()
{
 //定義一個原始陣列A,長度為9  定義一個數組B,用來儲存排完序的元素
            int A[9] = {8,4,5,7,3,6,1,0,9}, B[9], i;
            sort(A, B, 9, 9);    // 呼叫sort函式,傳四個引數:陣列A、陣列B 、陣列長度、最大元素值
            for (i=0; i<= 8; i++)
            {
                printf("%d ", B[i]);
            }
            printf("\n");
            return 0;
}