八大排序演算法(八)桶排序

2021-07-04 14:39:09 字數 3256 閱讀 8260

說基數排序之前,我們先說桶排序:

基本思想:是將陣列分到有限數量的桶子裡。每個桶子再個別排序(有可能再使用別的排序演算法或是以遞迴方式繼續使用桶排序進行排序)。桶排序是鴿巢排序的一種歸納結果。當要被排序的陣列內的數值是均勻分配的時候,桶排序使用線性時間(θ(n))。但桶排序並不是 比較排序,他不受到 o(n log n) 下限的影響。

簡單來說,就是把資料分組,放在乙個個的桶中,然後對每個桶裡面的在進行排序。  

例如要對大小為[1..1000]範圍內的n個整數a[1..n]排序  

首先,可以把桶設為大小為10的範圍,具體而言,設集合b[1]儲存[1..10]的整數,集合b[2]儲存   (10..20]的整數,……集合b[i]儲存(   (i-1)*10,   i*10]的整數,i   =   1,2,..100。總共有  100個桶。  

然後,對a[1..n]從頭到尾掃瞄一遍,把每個a[i]放入對應的桶b[j]中。  再對這100個桶中每個桶裡的數字排序,這時可用冒泡,選擇,乃至快排,一般來說任  何排序法都可以。

最後,依次輸出每個桶裡面的數字,且每個桶中的數字從小到大輸出,這  樣就得到所有數字排好序的乙個序列了。  

假設有n個數字,有m個桶,如果數字是平均分布的,則每個桶裡面平均有n/m個數字。如果  

對每個桶中的數字採用快速排序,那麼整個演算法的複雜度是  

o(n   +   m   *   n/m*log(n/m))   =   o(n   +   nlogn   -   nlogm)  

從上式看出,當m接近n的時候,桶排序複雜度接近o(n)  

當然,以上複雜度的計算是基於輸入的n個數字是平均分布這個假設的。這個假設是很強的  ,實際應用中效果並沒有這麼好。如果所有的數字都落在同乙個桶中,那就退化成一般的排序了。  

前面說的幾大排序演算法 ,大部分時間複雜度都是o(n2),也有部分排序演算法時間複雜度是o(nlogn)。而桶式排序卻能實現o(n)的時間複雜度。但桶排序的缺點是:

1)首先是空間複雜度比較高,需要的額外開銷大。排序有兩個陣列的空間開銷,乙個存放待排序陣列,乙個就是所謂的桶,比如待排序值是從0到m-1,那就需要m個桶,這個桶陣列就要至少m個空間。

2)其次待排序的元素都要在一定的範圍內等等。

桶式排序是一種分配排序。分配排序的特定是不需要進行關鍵碼的比較,但前提是要知道待排序列的一些具體情況。

分配排序的基本思想:說白了就是進行多次的桶式排序。

基數排序過程無須比較關鍵字,而是通過「分配」和「收集」過程來實現排序。它們的時間複雜度可達到線性階:o(n)。

例項:

撲克牌中52 張牌,可按花色和面值分成兩個字段,其大小關係為:

花色:梅花< 方塊< 紅心< 黑心

面值:2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < 10 < j < q < k < a

若對撲克牌按花色、面值進行公升序排序,得到如下序列:

即兩張牌,若花色不同,不論面值怎樣,花色低的那張牌小於花色高的,只有在同花色情況下,大小關係才由面值的大小確定。這就是多關鍵碼排序。

為得到排序結果,我們討論兩種排序方法。

方法1:先對花色排序,將其分為4 個組,即梅花組、方塊組、紅心組、黑心組。再對每個組分別按面值進行排序,最後,將4 個組連線起來即可。

方法2:先按13 個面值給出13 個編號組(2 號,3 號,...,a 號),將牌按面值依次放入對應的編號組,分成13 堆。再按花色給出4 個編號組(梅花、方塊、紅心、黑心),將2號組中牌取出分別放入對應花色組,再將3 號組中牌取出分別放入對應花色組,……,這樣,4 個花色組中均按面值有序,然後,將4 個花色組依次連線起來即可。

設n 個元素的待排序列包含d 個關鍵碼,則稱序列對關鍵碼有序是指:對於序列中任兩個記錄r[i]和r[j](1≤i≤j≤n)都滿足下列有序關係:

其中k1 稱為最主位關鍵碼,kd 稱為最次位關鍵碼     。

兩種多關鍵碼排序方法:

多關鍵碼排序按照從最主位關鍵碼到最次位關鍵碼或從最次位到最主位關鍵碼的順序逐次排序,分兩種方法:

最高位優先(most significant digit first)法,簡稱msd 法:

1)先按k1 排序分組,將序列分成若干子串行,同一組序列的記錄中,關鍵碼k1 相等。

2)再對各組按k2 排序分成子組,之後,對後面的關鍵碼繼續這樣的排序分組,直到按最次位關鍵碼kd 對各子組排序後。

3)再將各組連線起來,便得到乙個有序序列。撲克牌按花色、面值排序中介紹的方法一即是msd 法。

最低位優先(least significant digit first)法,簡稱lsd 法:

1) 先從kd 開始排序,再對kd-1進行排序,依次重複,直到按k1排序分組分成最小的子串行後。

2) 最後將各個子串行連線起來,便可得到乙個有序的序列, 撲克牌按花色、面值排序中介紹的方法二即是lsd 法。

基於lsd方法的鏈式基數排序的基本思想

「多關鍵字排序」的思想實現「單關鍵字排序」。對數字型或字元型的單關鍵字,可以看作由多個數字或多個字元構成的多關鍵字,此時可以採用「分配-收集」的方法進行排序,這一過程稱作基數排序法,其中每個數字或字元可能的取值個數稱為基數。比如,撲克牌的花色基數為4,面值基數為13。在整理撲克牌時,既可以先按花色整理,也可以先按面值整理。按花色整理時,先按紅、黑、方、花的順序分成4摞(分配),再按此順序再疊放在一起(收集),然後按面值的順序分成13摞(分配),再按此順序疊放在一起(收集),如此進行二次分配和收集即可將撲克牌排列有序。   

基數排序:

是按照低位先排序,然後收集;再按照高位排序,然後再收集;依次類推,直到最高位。有時候有些屬性是有優先順序順序的,先按低優先順序排序,再按高優先順序排序。最後的次序就是高優先順序高的在前,高優先順序相同的低優先順序高的在前。基數排序基於分別排序,分別收集,所以是穩定的。

演算法實現:

void radixsort(node l,length,maxradix)  

{ int m,n,k,lsp;

k=1;m=1;

int temp[10][length-1];

empty(temp); //清空臨時空間

while(k

八大排序演算法

1.直接插入排序 原理 將陣列分為無序區和有序區兩個區,然後不斷將無序區的第乙個元素按大小順序插入到有序區中去,最終將所有無序區元素都移動到有序區完成排序。要點 設立哨兵,作為臨時儲存和判斷陣列邊界之用。實現 void insertsort node l,int length void shell ...

八大排序演算法

一 概述 八大排序演算法包括 1 插入排序之直接插入排序 straight insertion sort 2 插入排序之希爾排序 shells sort 3 選擇排序之簡單選擇排序 selection sort 4 選擇排序之堆排序 heap sort 5 交換排序之氣泡排序 bubble sort...

八大排序演算法

排序的定義 輸入 n個數 a1,a2,a3,an 輸出 n個數的排列 a1 a2 a3 an 使得a1 a2 a3 an in place sort 不占用額外記憶體或占用常數的記憶體 插入排序 選擇排序 氣泡排序 堆排序 快速排序。out place sort 歸併排序 計數排序 基數排序 桶排序...