1. 程式人生 > 實用技巧 >每天一點點之資料結構與演算法 - 線性排序:計數排序(Counting sort)(未完待續)

每天一點點之資料結構與演算法 - 線性排序:計數排序(Counting sort)(未完待續)

個人覺得,記數排序其實是桶排序的一直特殊情況。當要排序當資料是n,所處的資料範圍不大的時候,最大值為k,我們就可以把資料劃分為k個桶。每個桶內大資料都相同,省去了桶內快排的時間。

我們拿高考查分系統來說明。我們查分時,系統會現實我們的成績以及所在省的排名。如果所在省有100萬考生,如何通過成績快速排序得出名次?

考生的滿分是900分,最小是0分,這個資料範圍很小,我們可以劃分為901個桶,對應分數0-900分。根據考生成績,我們將100萬考生成績劃分到901個桶內。桶內的的資料都是分數相同的考生,所以並不需要再進行排序。因為只涉及到了掃描,所以時間複雜度是O(n)。

計數排序的思想就是這樣,跟桶排序非常類似,只是桶的大小粒度不同。不過為什麼要叫做計數呢?

我們還是拿考生那個例子來解釋。為了理解方便,我們對資料進行簡化。假設只有8個考生,分數在0-5分之間。我們把考生的成績放在一個數組A[8]中。

A[8] = [2, 5, 3, 0, 2, 3, 0, 3]

考生的成績0-5分,我們使用C[6]來表是桶,其中下標對應分數。不過,C[6]儲存的不是考生成績,而是對應的考生個數。例如:下標為0標示成績為0的考生有2個,下標為1標示成績為1的考生有0個,以此類推。

C[6] = [2, 0, 2, 3, 0, 1]

可以看出,分數為3分的考生有3個,小於3分的考生有4個,所以,成績為3的考生在排序之後的有序陣列R[8]中,會儲存在下標為4,5,6的位置。

那麼如何計算出,剋個分數的考生在有序陣列中對應的儲存位置呢?

思路是這樣的:我們對C[6]陣列順序求和,C[6]儲存的資料就變成下面陣列。C[k]裡儲存小於等於分數k的考生個數。

C[6] = [2, 2, 4, 7, 7, 8]