基本思想
基數排序的思想是將整數按位數切割成不同的數字,然后按每個位數分別比較從而得到有序的序列。
例子
本文以數組中元素均為正整數來演示思想。
給定一個數組 arr = [ 6, 56, 89 , 12 ,39 ,21,11,156,657 ];
初始狀態如下:
按照個位裝桶
十進制的每位數字都是從0-9的,所以我們分配10個桶,每個桶有一定的容量(本文將設定為數組長度大小);
第一輪先按照個位數進行裝桶,6的個位數為6,所以將其放入代表數字6的桶;
56的個位數也為6,所以也將其放入代表數字6的桶;
以此類推,將每一個數按照個位數字進行裝桶,如下:
然后按照這個順序將它們放回原數組,即為:
[ 11,21,12,6,56,156,657,89,39 ];
如下圖:
按照十位裝桶
10的十位數字是1;
21的十位數字是2;
12的十位數字是1;
6的十位數字是0;
...
如此將它們按照十位數字進行裝桶如下:
然后再按照這個順序放回原數組如下:
[ 6,11 ,12, 21,39,56,156,657,89];
如下圖
按照百位進行裝桶
6的百位是0;
11的百位是0;
12的百位也是0;
同理21,39,56的百位都是0;
156的百位是1;
...
等等
按照百位進行裝桶如下:
再按照百位放回原數組如下:
[ 6,11 ,12, 21,39,56,89,156,657];
如下圖:
此時從最低為到最高位都已經裝桶放回完畢,已經有序。
代碼
像上面的例子,我們知道最大位數是百位,但是計算機沒有肉眼,需要用程序進行求解,得到位數如下:
int maxNum = arr[0]; //假設第一數就是最大數
for (int i = 1; i < arr.length; i++) {
if (arr[i] > maxNum)
maxNum = arr[i];
}
}
//得到位數
int maxLength = (maxNum + "").length();
整體代碼
import java.util.Arrays;
public class Solution {
public static void main(String[] args) {
int arr[] = {6, 56, 89, 12, 39, 21, 11, 156, 657};
radixSort(arr);
}
public static void radixSort(int[] arr) {
//得到數組中最大的數的位數
int maxNum = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > maxNum) {
maxNum = arr[i];
}
}
//得到最大數是幾位數
int maxLength = (maxNum + "").length();
//定義一個二維數組,表示10個桶, 每個桶就是一個一維數組
int[][] bucket = new int[10][arr.length];
//每個桶存入了幾個數字
int[] everyBucketNum = new int[10];
// n* = 10 的原因是
//123取出個位數字是 123 % 10,即 123 / 1 %10
//123 取出十位數字是123 / 10 % 10;
//123 去除百位數字是123 /100 % 10
//以此類推
for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
for (int j = 0; j < arr.length; j++) {
//取出每個元素的對應位的值
int digit = arr[j] / n % 10;
//放入到對應的桶中
bucket[digit][everyBucketNum[digit]] = arr[j];
everyBucketNum[digit]++;
}
//按照這個桶的順序(一維數組的下標依次取出數據,放入原來數組)
int index = 0;
//遍歷每一桶,並將桶中是數據,放入到原數組
for (int k = 0; k < everyBucketNum.length; k++) {
if (everyBucketNum[k] != 0) {
for (int l = 0; l < everyBucketNum[k]; l++) {
arr[index++] = bucket[k][l];
}
}
//放回原數組后,需要將每個 everyBucketNum[k] = 0
everyBucketNum[k] = 0;
}
System.out.println("第" + (i + 1) + "輪,對個位的排序處理 arr =" + Arrays.toString(arr));
}
}
}
時間復雜度
由代碼可知,時間復雜度為 $O(n)$;
穩定性:
在基數排序過程中,每一次裝桶都是將當前位數上相同數值的元素進行裝桶,並不需要交換位置。所以基數排序是穩定的算法。
拓展
如果負數可以使用正負數桶,負數的排負數,正數的排正數,然后就可以達到要求。
還有其他更好的,本文不過多介紹,大家可以自行查閱資料。
歡迎關注
掃下方二維碼即可關注微信公眾號:code隨筆