本文我準備用Java實現基數排序。基數排序由於其獨有的排序方式,只適合待排序的數字都是非負整數的情況。基數排序和計數排序名字很相像,不要搞混淆了。接下來我列舉一下二者的共同點和不同點:
計數排序和基數排序的共同點:
1、都是隻適合對非負整數的排序
2、都是線性的時間複雜度
計數排序和基數排序的區別:
1、計數排序不能接受有很大值的待排序元素;而基數排序可以接受
2、計數排序實現和操作簡單,只需要額外的一個數組(最大值大了,這個空間就大了);而基數排序還要算待排序數字的每一位,還要輔以10個桶的額外空間
具體的排序算法過程已經在註釋裏面了,大家可以複製代碼到IDE裏面,用DEBUG模式研究算法的過程:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
/**
* @author LiYang
* @ClassName RadixSort
* @Description 基數排序算法
* @date 2019/11/5 16:45
*/
public class RadixSort {
/**
* 基數排序算法(RadixSort)
* 基數排序,需要排序元素是非負整數
* @param arr 待排序數組
*/
public static void radixSort(int[] arr){
//先求出所有元素的最大位數
int maxDigit = 0;
//遍歷待排序數組
for (int i = 0; i < arr.length; i++) {
//遍歷比較,得到最大整數位數
maxDigit = Math.max(maxDigit, (int)Math.ceil(Math.log10(arr[i])));
}
//查看本次待排序數組的最大整數的位數
//System.out.println("最大整數位:" + maxDigit);
//用於基數排序的桶,容量爲10,也就是數字位0-9
List[] bucket = new ArrayList[10];
//初始化桶:List[] bucket
for (int i = 0; i < bucket.length; i++) {
bucket[i] = new ArrayList();
}
//從個位開始,一位一位地往高位進行基數排序
for (int digit = 1; digit <= maxDigit; digit++) {
//將每一個待排序元素,取當前數位,進入對應下標的桶
for (int i = 0; i < arr.length; i++) {
//得到元素當前數位的數字
int radix = arr[i] / (int)Math.pow(10, (digit - 1)) % 10;
//裝入對應下標的桶
bucket[radix].add(arr[i]);
}
/*
* 當前數位的基數排序後,重新按照0-9號桶的順序遍歷
* 遍歷中的每個桶按從左到右的順序重新放入原數組
* 也就是每個桶的ArrayList從下標0開始,到size-1
*/
//記錄arr的下標值
int index = 0;
//遍歷每個桶,從0號桶到9號桶
for (int i = 0; i < bucket.length; i++) {
//每個桶從左到右遍歷元素
for (int j = 0; j < bucket[i].size(); j++) {
//0-9號桶,每桶從左到右,依次賦值回原數組進行記錄
//以便於下一次基數排序,提供中間排序的序列
arr[index++] = (int)bucket[i].get(j);
}
}
//當前基數排序結束,清空所有桶,以便於下一次基數排序
for (int i = 0; i < bucket.length; i++) {
//清空所有桶
bucket[i].clear();
}
}
}
/**
* 驗證基數排序算法
* @param args
*/
public static void main(String[] args) {
//待排序數組
int[] arr = new int[30];
//隨機數類
Random random = new Random();
//隨機生成排序數組(1000以內的整數)
for (int i = 0; i < arr.length; i++) {
arr[i] = random.nextInt(1000);
}
//打印待排序數組
System.out.println("基數排序前:" + Arrays.toString(arr));
//進行基數排序
radixSort(arr);
//打印基數排序後的數組
System.out.println("基數排序後:" + Arrays.toString(arr));
}
}
運行 RadixSort 類的main方法,基數排序算法測試通過:
基數排序前:[329, 695, 789, 151, 103, 311, 339, 566, 680, 353, 652, 222, 911, 385, 556, 444, 575, 108, 75, 998, 649, 398, 358, 26, 568, 954, 383, 24, 6, 701]
基數排序後:[6, 24, 26, 75, 103, 108, 151, 222, 311, 329, 339, 353, 358, 383, 385, 398, 444, 556, 566, 568, 575, 649, 652, 680, 695, 701, 789, 911, 954, 998]