Java排序算法(十一):基數排序
基數排序已經不再是一種常規的排序方式,它更多地像一種排序方法的應用,基數排序必須依賴於另外的排序方法。基數排序的總體思路就是將待排序數據拆分成多個關鍵字進行排序,也就是說,基數排序的實質是多關鍵字排序。
多關鍵字排序的思路是將待排數據裏德排序關鍵字拆分成多個排序關鍵字;第1個排序關鍵字,第2個排序關鍵字,第3個排序關鍵字......然後,根據子關鍵字對待排序數據進行排序。
多關鍵字排序時有兩種解決方案:
最高位優先法(MSD)(Most Significant Digit first)
最低位優先法(LSD)(Least Significant Digit first)
例如,對如下數據序列進行排序。
192,221,12,23
可以觀察到它的每個數據至多隻有3位,因此可以將每個數據拆分成3個關鍵字:百位(高位)、十位、個位(低位)。
如果按照習慣思維,會先比較百位,百位大的數據大,百位相同的再比較十位,十位大的數據大;最後再比較個位。人得習慣思維是最高位優先方式。
如果按照人得思維方式,計算機實現起來有一定的困難,當開始比較十位時,程序還需要判斷它們的百位是否相同--這就認爲地增加了難度,計算機通常會選擇最低位優先法。
基數排序方法對任一子關鍵字排序時必須藉助於另一種排序方法,而且這種排序方法必須是穩定的。
對於多關鍵字拆分出來的子關鍵字,它們一定位於0-9這個可枚舉的範圍內,這個範圍不大,因此用桶式排序效率非常好。
對於多關鍵字排序來說,程序將待排數據拆分成多個子關鍵字後,對子關鍵字排序既可以使用桶式排序,也可以使用任何一種穩定的排序方法。
代碼實現:
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