資料結構與演算法 計數排序

2021-10-12 10:25:09 字數 2885 閱讀 8085

計數排序(counting sort)是一種穩定的線性時間排序演算法。該演算法於2023年由 harold h. seward 提出。計數排序使用乙個額外的陣列c ,其中第i個元素是待排序陣列a中值等於i的元素的個數。然後根據陣列c來將a中的元素排到正確的位置。

當輸入的元素是 n 個 0 到 k 之間的整數時,它的執行時間是 θ(n + k)。計數排序不是比較排序,排序的速度快於任何比較排序演算法。

由於用來計數的陣列c的長度取決於待排序陣列中資料的範圍(等於待排序陣列的最大值與最小值的差加上1),這使得計數排序對於資料範圍很大的陣列,需要大量時間和記憶體。例如:計數排序是用來排序0到100之間的數字的最好的演算法,但是它不適合按字母順序排序人名。但是,計數排序可以用在基數排序中的演算法來排序資料範圍很大的陣列。

我們使用下面的例子進行說明。

假設有20個隨機整數,其取值範圍在0~10之間,對其進行排序,由於這20個隨機整數的取值範圍是固定的,那麼我們可以定義乙個長度為11的陣列,陣列下標為從0到10,並且元素初始值全為0,然後遍歷要排序的20個隨機整數,將遍歷到的數值對應的陣列下標進行+1,直到遍歷結束。如下圖所示:

假設我們要遍歷的20個隨機數為:9,3,5,4,8,9,1,2,7,8,5,3,6,7,9,0,4,7,2,4。建立乙個長度為11的陣列如下所示:

然後我們開始遍歷,遍歷的第乙個數字是9,則給新建立的陣列下標為9的值+1,即:

接著我們依此類推,直到遍歷完要排序的數,遍歷完之後的結果是:

根據上面的陣列的結果,我們就可以得到乙個有序的數列,即:0,1,2,2,3,3,4,4,4,5,5,6,7,7,7,8,8,9,9,9。

public

static

int[

]sort

(int

arr)

// 根據數列最大值確定統計陣列的長度

int[

] cntarr =

newint

[max+1]

;// 遍歷陣列,填充統計陣列

for(

int i: arr)

// 遍歷統計陣列,得到排好序後的陣列

int index =0;

for(

int i=

0; i

return res;

}

問題1:對於上面的計數排序,我們不難發現存在這樣乙個問題:如果要排序的20個隨機整數的範圍在81~93之間,那麼我們就需要建立乙個長度為94的陣列,這樣就會造成新建的陣列的前面81個空間位置就白白浪費了。

解決方法:

我們可以通過使用使用數列的最大值-最小值+1作為統計陣列的長度即可,同時使用最小值作為乙個偏移量,用於計算整數在統計陣列中的下標。

問題2:

以上的計數排序只是按照輸入數列從小到大的乙個順序對其進行輸出而已,並沒有對原始數列進行排序。如果遇到類似於對學生分數進行排序這樣的現實問題,比如對於相同分數的學生就會造成分不清分數對應的是誰這樣的問題。

解決方法:

假如現在有5個學生的分數為:(學生a:90,學生b:99,學生c:95,學生d:94,學生e:95),使用上面的方法得到的統計陣列如下所示:

我們首先對統計陣列進行變形,即從統計陣列的第2個元素開始,每個元素都加上前面的所有元素之和,得到的新的統計陣列如下所示:

然後,我們從後向前依次遍歷5位學生的分數,第1個為學生e95分,找到統計陣列下標為5的元素,值是4,代表學生e成績排名在第4位,然後對陣列下標為5的元素的值-1,表示下次再遇到成績為95分的,其位置就會在第3位,按照此方法就會得出最終的成績排名順序為:(學生a:90,學生b:94,學生c:95,學生d:95,學生e:99)。

優化後的計數排序的實現:

public

static

int[

]sort

(int

arr)

// 根據數列最大最小值確定統計陣列的長度

int[

] cntarr =

newint

[max-min+1]

;// 遍歷陣列,填充統計陣列

for(

int i: arr) cntarr[i-min]++;

// 遍歷統計陣列累加計數

for(

int i=

1; i

) cntarr[i]

+=cntarr[i-1]

;// 倒序遍歷陣列,得到排好序後的陣列

for(

int i=arr.length-

1; i>=

0; i--

) res[

--cntarr[arr[i]

-min]

]= arr[i]

;return res;

}

資料結構與演算法 計數排序

排序的思路常規的就是基於比較,比如常見的快排,冒泡等,這種排序最快也是onlogn。非比較的排序思路基本是用乙個輔助陣列,把待排陣列的元素大小作為索引放入輔助陣列,用輔助陣列的位置來記錄大小,空間換時間。適用場景 待排元素的值有乙個範圍,並且範圍是可以接受的。方法 這裡會涉及幾個引數,作為接受引數,...

資料結構與演算法之計數排序

計數排序的基本思想 在乙個陣列中對每個元素按大小進行排名次,乙個元素的名次是陣列中比他小的元素的個數加上左邊出現的與之相等的元素的個數 備註 這裡名次越高說明元素越大 例如陣列a 5,4,2,5,8,9 新建乙個相同大小的陣列用於儲存陣列元素的名次,得到名次陣列 r 2,1,0,3,4,5 名次計算...

資料結構與演算法(十二) 計數排序

計數排序是桶排序的乙個特例,即 桶的大小為1。這樣一來,分桶之後,每個桶內部就不需要排序了,只需將不同桶的資料合併到一起,組成排序好的序列。計數排序對資料的要求十分嚴格 找出原始陣列l中最大的元素值max 構造乙個計數陣列count,count的下標為從0到max,儲存的值為原陣列中元素值等於下標的...