什麼是基數排序?

2021-10-24 20:54:51 字數 3547 閱讀 7827

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

在之前的部落格中,我介紹過一種非比較排序——計數排序

計數排序的原理很簡單,就是用乙個陣列來統計每種數字出現的次數,然後按照大小順序將其依次放回原陣列,達成排序的目的。

但是計數排序有乙個很嚴重的問題,就是其只能對整數進行排序,一旦遇到字串時,就無能為力了。

為了彌補上述的缺點,針對於字串基數排序誕生了。

基數排序在計數排序的基礎上進行了改進,將排序工作拆分為多個階段,每乙個階段只根據乙個字元進行排序,一共排序k輪(k為資料長度)

例如我們需要對一組三個英文本母組成的字串進行排序,按照以上規則,進行三輪排序。

(ps:這裡用的lsd法)我們從低位往高位開始排,按照計數排序的思想,統計所有出現過的字元,按照其在ascii表中的順序依次排序,得到以下結果

此時在第一輪的基礎上,對倒數第二個字元進行排序

在第二輪的基礎上,再對第乙個字元進行排序

如此一來,就得到了有序的序列。這種將字串拆分為多位,每位進行計數排序的演算法,就是基數排序。

從上面來看,每一位的排序都基於上一位的基礎,所以這也就要求我們的計數排序必須是穩定的,否則前後順序無法保證,多輪的排序就沒有了意義,下面就介紹如何實現穩定的計數排序。

在之前的部落格中,我當時介紹的計數排序是不穩定的,下面就對其進行改造,將其變為穩定排序。

那要這麼做呢?我們知道,計數排序中的統計陣列中儲存了每個數字出現的次數,而我們還原時也只是按照數字來依次將其放回,這也就是其不穩定的原因,因為統計陣列絲毫沒有關心其在原陣列中的位置。

要改進這一點,可以通過以下方法來實現,只需要加上幾行簡單的**即可。

//保證計數排序穩定,對陣列變形,統計陣列的每乙個位置的值為前面所有數字的數量合

//變形後每個位置的值即為該資料的排序的序號

int sum =0;

for(

int i =

0; i < range; i++

)

如上面**,我們需要讓統計陣列中不再記錄陣列出現的次數,而是記錄該位置前面所有數字出現的次數和,這種方式能讓我們巧妙地得到序號。

例如下圖

這樣做的目的是什麼呢?

//按照原陣列的資料的位置,倒序將資料放回原位,確保穩定性

vector<

int>

temp

(arr.

size()

,0);

for(

int i = arr.

size()

-1; i >=

0; i--

)

因為我們此時統計陣列中每乙個位置的值,變成了由陣列開頭到那個位置所有元素的和,這也就意味著,他此時變成了乙個排名

例如在原資料中有兩個93,乙個在前,乙個在後,並且統計陣列中93的位置為7。

我們通過上述方法,從後往前遍歷時,將後面的93放到第七個位置,接著統計陣列對應位置的排名減一,此時當我們放入前面的93時,他就變成了第六位,這樣就保證了其穩定性。

這個看**更好理解,思路都寫在了注釋中,改造完後的計數排序**如下。

void

countsort

(vector<

int>

& arr)

if(arr[i]

< min)

}int range = max - min +1;

vector<

int>

count

(range,0)

;//統計陣列

//統計每種數字出現的次數

for(

int i =

0; i < arr.

size()

; i++

)//保證計數排序穩定,對陣列變形,統計陣列的每乙個位置的值為前面所有數字的數量合

//變形後每個位置的值即為該資料的排序的序號

int sum =0;

for(

int i =

0; i < range; i++

)//按照原陣列的資料的位置,倒序將資料放回原位,確保穩定性

vector<

int>

temp

(arr.

size()

,0);

for(

int i = arr.

size()

-1; i >=

0; i--

) arr = temp;

//將臨時資料拷貝回原陣列

}

在寫基數排序之前,還有乙個小問題需要說明一下,由於前面我們所說的情況都是字串長度相等的時候,如果字串長度不相同時,怎麼處理呢?

因為字串並不像整數一樣排序依賴於長度,其排序主要依賴於字典序,所以我們以字串中最長的資料為標準,而長度不足的在尾部補零即可。

實現**如下

int

getindex

(const string& str,

int index)

return str[index];}

void

radixsort

(vector

& arr,

int maxlen)

//保證計數排序穩定,對陣列變形,統計陣列的每乙個位置的值為前面所有數字的數量合

//變形後每個位置的值即為該資料的排序的序號

int sum =0;

for(

int j =

0; j < count.

size()

; j++

)//按照原陣列的資料的位置,倒序將資料放回原位,確保穩定性

for(

int j = arr.

size()

-1; j >=

0; j--

) arr = temp;

}}

什麼是基數排序?

基數排序 radix sort 是桶排序的擴充套件,它的基本思想是 將整數按位數切割成不同的數字,然後按每個位數分別比較。具體做法是 將所有待比較數值統一為同樣的數字長度,數字較短的數前面補零。然後,從最低位開始,依次進行一次排序。這樣從最低位排序一直到最高位排序完成以後,數列就變成乙個有序序列。通...

動畫 什麼是基數排序?

基數排序和計數排序一樣無需進行比較和交換,和桶排序一樣利用分布和收集兩種基本操作進行排序。基數排序是把每乙個元素拆成多個關鍵字,乙個關鍵字可以在每乙個元素上同等的位置進行計數排序,乙個元素拆成多個關鍵字可以看作是要進行幾輪分桶,以乙個元素最長的長度為準。基數排序可以看成多 單 關鍵字的排序,可以想象...

排序 基數排序

基數排序 radix sort 是屬於 分配式排序 distribution sort 基數排序法又稱 桶子法 bucket sort 或bin sort,顧名思義,它是透過鍵值的部份資訊,將要排序的元素分配至某些 桶 中,藉以達到排序的作用。排序思想 首先按照資料的最低位 個位 將資料分配到0 9...