基數排序
基數排序是經典的拿空間換時間的排序算法。當預排數據中有重複數據時,該算法排完序後,重複數據的相對順序仍然不變,即表明基數排序是一種穩定排序算法。其基本思想如下:第一輪按每個數的個位數的順序,將數放入0-9的10個桶中,然後按順序取出來放回原數組;第二輪按每個數的十位數的順序,將數放入0-9的10個桶中,然後按順序取出來放回原數組;依次類推。
其代碼步驟如下:
- 得到數組中最大數的位數,確定需要排幾輪;
- 定義一個長度爲10的二維數組模擬10個桶,其中每個桶的長度爲原數組的長度;
- 定義一個一維數組用來記錄每一輪的每個桶中放了多少個數據;
- 每一輪先按每個數個位、十位、百位.的順序放入桶中;放完之後再按桶的順序將每個數放回到原數組。直至排完
特別注意:
- 基數排序是經典的拿空間(內存)換時間的排序算法,當預排數據量過於龐大時,耗費的內存也會很大,一定要注意硬件內存是否夠用,否則會出現內存不足的錯誤。
- 上述過程不滿足於預排數據中有負數的情況,當預排數據中存在負數,算法步驟要進行相應調整。
每一步的詳細說明已在代碼中註釋,如有錯誤,還望指出,我會及時改正。
package com.sort.radixSort;
import java.util.Arrays;
/*
* 基數排序
*/
public class RadixSortDemo1 {
public static void main(String[] args) {
int[] array = { 53, 3, 542, 748, 14, 214 };
System.out.println("排序前:" + Arrays.toString(array));
radixSort(array);
System.out.println("排序後:" + Arrays.toString(array));
}
// 基數排序
public static void radixSort(int[] array) {
// 1.首先要拿到數組中最大的數,確定需要幾輪排序
int max = array[0];
for (int i = 0; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
}
// 得到最大數的位數,確定循環幾輪
int maxLength = (max + "").length();
// 2.定義一個二維數組用來模擬10個桶,爲了防止每個桶在插入數據的時候發生溢出,每個桶的長度規定爲數組的長度
int[][] bucket = new int[10][array.length];
// 3.定義一個一維數組用來記錄每個桶中放了多少個數據(也是下次新數據的下標)
int[] bucketEleCounts = new int[10];
// 4.所有準備工作完畢,開始排序
// 一共需要排maxLength輪
for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {// n專門用來輔助得到每輪的位數
// 4.1.循環數組,按位數順序放入對應的桶中
for (int j = 0; j < array.length; j++) {
// 每輪得到數組中每個數相應的位數
int ele = array[j] / n % 10;
// 放入到對應的桶中,找到第ele個桶,然後得到第ele個桶中放新數據的下標bucketEleCounts[ele]
bucket[ele][bucketEleCounts[ele]] = array[j];
// 每次放完,需要將第ele個桶的數量+1;
bucketEleCounts[ele]++;
}
// 4.2.放完數據後,按桶的順序依次把數據取出來放回原來的數組
int index = 0;
for (int k = 0; k < bucket.length; k++) {
// 如果第k個桶有數據,那就取出來
if (bucketEleCounts[k] != 0) {
// 第k個桶裏面的數據循環取出來,並且放回原數組
for (int l = 0; l < bucketEleCounts[k]; l++) {
array[index] = bucket[k][l];
index++;
}
}
// 每次取完一個桶的數據,就要將這個桶的數據個數清空,等待下一輪排序
bucketEleCounts[k] = 0;
}
System.out.println("第" + (i + 1) + "輪排序後:" + Arrays.toString(array));
}
}
}