排序動圖
排序思路
將數組按基數進行排序,個位,十位,百位…
排序流程
- 取數組中最大的數,並計算位數
- 從最低位開始取每個位的數組成一個新的數組
- 對新的數組重新按位排序,直到位數排完
代碼實現
public static void radixSort(int[] arr) {
// 找出最大的數
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i ++) {
if (arr[i] > max) {
max = arr[i];
}
}
// 計算最大的數有幾位
int length = (max+"").length();
// 存放每次排序後的數字
int[] temp = arr;
// temp 數組的下標
int index = 0;
// 排序 length 次 n 代表每次的需要取模的值
for (int i = 0, n = 1; i < length; i++, n*=10) {
// 存放每個位置對應的數
int[][] bucket = new int[10][arr.length];
// 存放每個下標放了一個數字
int[] counts = new int[10];
// 排序
for (int j = 0; j < arr.length; j++) {
// 取模放入對應的數組中
int indexVal = temp[j] / n % 10;
bucket[indexVal][counts[indexVal]] = temp[j];
counts[indexVal] = ++counts[indexVal];
}
// 將每個下標的數字按順序取出來
for (int k = 0; k < 10; k++) {
for (int l = 0; l < counts[k]; l++) {
temp[index] = bucket[k][l];
index++;
}
}
// index 歸 0
index = 0;
}
// 將臨時數組賦予真實數組
for (int i = 0; i < arr.length; i++) {
arr[i] = temp[i];
}
}
代碼優化 - 使用隊列記錄數組
- 自定義隊列
MyQueue.java
public class MyQueue {
/**
* 使用數組作爲隊列的底層
*/
private int[] arr;
/**
* 構造方法
*/
public MyQueue() {
arr = new int[0];
}
/**
* 入隊
*
* @param e 入隊的元素
*/
public void add(int e) {
// 創建一個新的數組
int[] newArray = new int[arr.length + 1];
// 將數據複製到新數組
for (int i = 0; i < arr.length; i++) {
newArray[i] = arr[i];
}
// 入隊
newArray[arr.length] = e;
// 將新數組賦值給原來的數組
arr = newArray;
}
/**
* 出隊
*
* @return 出隊的元素
*/
public int poll() {
// 隊列是否爲空
if (isEmpty()) {
throw new RuntimeException("Queue is Empty");
}
// 記錄出隊的元素
int e = arr[0];
// 創建一個新的數組
int[] newArray = new int[arr.length-1];
// 將數據複製到新數組
for (int i = 0; i < newArray.length; i++) {
newArray[i] = arr[i+1];
}
// 將新數組賦值給原來的數組
arr = newArray;
// 返回出隊的元素
return e;
}
/**
* 隊列是否爲空
*
* @return true/false
*/
public boolean isEmpty() {
return arr.length == 0;
}
}
- 使用隊列優化技術排序
RadixQueueSort.java
public class RadixQueueSort {
public static void main(String[] args) {
int[] arr = new int[]{54, 4, 36, 125, 435, 52, 23, 678, 34, 12, 879};
radixQueueSort(arr);
System.out.println(Arrays.toString(arr));
}
/**
* 使用隊列實現基數排序
*
* @param arr 數組
*/
public static void radixQueueSort(int[] arr) {
// 定義最大值,找出最大的數
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
// 計算最大值的位數
int length = (max + "").length();
// 定義一個記錄數字的隊列數組 0 1 2 3 4 ...
MyQueue[] myQueue = new MyQueue[10];
// 爲每個隊列初始化
for (int i = 0; i < myQueue.length; i++) {
myQueue[i] = new MyQueue();
}
// 定義一個記錄排序好的數組
int[] temp = arr;
// 記錄臨時數組的下標
int index = 0;
// 循環基數排序
for (int i = 0, n = 1; i < length; i++, n *= 10) {
// 遍歷所有數據
for (int j = 0; j < temp.length; j++) {
// 計算餘數
int indexVal = temp[j] / n % 10;
// 加入對應餘數的隊列
myQueue[indexVal].add(temp[j]);
}
// 取出隊列中的數據
for (int k = 0; k < myQueue.length; k++) {
while (!myQueue[k].isEmpty()) {
temp[index] = myQueue[k].poll();
index++;
}
}
// 將 index 初始爲 0
index = 0;
}
// 將臨時數組賦值給原來的數組
for (int i = 0; i < arr.length; i++) {
arr[i] = temp[i];
}
}
}