桶式排序再也不是一種基於比較的排序方法,它是一種比較巧妙的排序方式,但這種排序方式須要待排序的序列知足如下兩個特徵:java
待排序列全部的值處於一個可枚舉的範圍之類;git
待排序列所在的這個可枚舉的範圍不該該太大,不然排序開銷太大。算法
排序的具體步驟以下:數組
(1)對於這個可枚舉範圍構建一個buckets數組,用於記錄「落入」每一個桶中元素的個數;緩存
(2)將(1)中獲得的buckets數組從新進行計算,按以下公式從新計算:spa
buckets[i] = buckets[i] +buckets[i-1] (其中1<=i<buckets.length); .net
桶式排序是一種很是優秀的排序算法,時間效率極高,它只要經過2輪遍歷:第1輪遍歷待排數據,統計每一個待排數據「落入」各桶中的個數,第2輪遍歷buckets用於從新計算buckets中元素的值,2輪遍歷後就能夠獲得每一個待排數據在有序序列中的位置,而後將各個數據項依次放入指定位置便可。code
桶式排序的空間開銷較大,它須要兩個數組,第1個buckets數組用於記錄「落入」各桶中元素的個數,進而保存各元素在有序序列中的位置,第2個數組用於緩存待排數據。blog
桶式排序是穩定的。排序
若是待排序數據的範圍在0~k之間,那麼它的時間複雜度是O(k+n)的
桶式排序算法速度很快,由於它的時間複雜度是O(k+n),而基於交換的排序時間上限是nlg n。
可是它的限制多,好比它只能排整形數組。並且當k較大,而數組長度n較小,即k>>n時,輔助數組C[k+1]的空間消耗較大。
當數組爲整形,且k和n接近時, 能夠用此方法排序。(有的文章也稱這種排序算法爲「計數排序」)
代碼實現:
public class BucketSortTest { public static int count = 0; public static void main(String[] args) { int[] data = new int[] { 5, 3, 6, 2, 1, 9, 4, 8, 7 }; print(data); bucketSort(data, 0, 10); print(data); } public static void bucketSort(int[] data, int min, int max) { // 緩存數組 int[] tmp = new int[data.length]; // buckets用於記錄待排序元素的信息 // buckets數組定義了max-min個桶 int[] buckets = new int[max - min]; // 計算每一個元素在序列出現的次數 for (int i = 0; i < data.length; i++) { buckets[data[i] - min]++; } // 計算「落入」各桶內的元素在有序序列中的位置 for (int i = 1; i < max - min; i++) { buckets[i] = buckets[i] + buckets[i - 1]; } // 將data中的元素徹底複製到tmp數組中 System.arraycopy(data, 0, tmp, 0, data.length); // 根據buckets數組中的信息將待排序列的各元素放入相應位置 for (int k = data.length - 1; k >= 0; k--) { data[--buckets[tmp[k] - min]] = tmp[k]; } } public static void print(int[] data) { for (int i = 0; i < data.length; i++) { System.out.print(data[i] + "\t"); } System.out.println(); } }
運行結果:
5 3 6 2 1 9 4 8 7 1 2 3 4 5 6 7 8 9
基數排序,說白了就是進行屢次的桶式排序。
基數排序已經再也不是一種常規的排序方式,它更多地像一種排序方法的應用,基數排序必須依賴於另外的排序方法。基數排序的整體思路就是將待排序數據拆分紅多個關鍵字進行排序,也就是說,基數排序的實質是多關鍵字排序。
多關鍵字排序的思路是將待排數據裏德排序關鍵字拆分紅多個排序關鍵字;第1個排序關鍵字,第2個排序關鍵字,第3個排序關鍵字......而後,根據子關鍵字對待排序數據進行排序。
多關鍵字排序時有兩種解決方案:
最高位優先法(MSD)(Most Significant Digit first)
最低位優先法(LSD)(Least Significant Digit first)
例如,對以下數據序列進行排序。
192,221,12,23
能夠觀察到它的每一個數據至多隻有3位,所以能夠將每一個數據拆分紅3個關鍵字:百位(高位)、十位、個位(低位)。
若是按照習慣思惟,會先比較百位,百位大的數據大,百位相同的再比較十位,十位大的數據大;最後再比較個位。人得習慣思惟是最高位優先方式。
若是按照人得思惟方式,計算機實現起來有必定的困難,當開始比較十位時,程序還須要判斷它們的百位是否相同--這就認爲地增長了難度,計算機一般會選擇最低位優先法。
基數排序方法對任一子關鍵字排序時必須藉助於另外一種排序方法,並且這種排序方法必須是穩定的。
對於多關鍵字拆分出來的子關鍵字,它們必定位於0-9這個可枚舉的範圍內,這個範圍不大,所以用桶式排序效率很是好。
對於多關鍵字排序來講,程序將待排數據拆分紅多個子關鍵字後,對子關鍵字排序既可使用桶式排序,也可使用任何一種穩定的排序方法。
代碼實現:
package 基數排序; import java.util.Arrays; public class MultiKeyRadixSortTest { public static void main(String[] args) { int[] data = new int[] { 1100, 192, 221, 12, 23 }; print(data); radixSort(data, 10, 4); System.out.println("排序後的數組:"); print(data); } public static void radixSort(int[] data, int radix, int d) { // 緩存數組 int[] tmp = new int[data.length]; // buckets用於記錄待排序元素的信息 // buckets數組定義了max-min個桶 int[] buckets = new int[radix]; for (int i = 0, rate = 1; i < d; i++) { // 重置count數組,開始統計下一個關鍵字 Arrays.fill(buckets, 0); // 將data中的元素徹底複製到tmp數組中 System.arraycopy(data, 0, tmp, 0, data.length); // 計算每一個待排序數據的子關鍵字 for (int j = 0; j < data.length; j++) { int subKey = (tmp[j] / rate) % radix; buckets[subKey]++; } for (int j = 1; j < radix; j++) { buckets[j] = buckets[j] + buckets[j - 1]; } // 按子關鍵字對指定的數據進行排序 for (int m = data.length - 1; m >= 0; m--) { int subKey = (tmp[m] / rate) % radix; data[--buckets[subKey]] = tmp[m]; } rate *= radix; } } public static void print(int[] data) { for (int i = 0; i < data.length; i++) { System.out.print(data[i] + "\t"); } System.out.println(); } }
運行結果:
1100 192 221 12 23 排序後的數組: 12 23 192 221 1100
轉自:http://blog.csdn.net/apei830/article/details/6596104