1.基數排序(桶排序)介紹
基數排序(radix sort)屬於“分配式排序”(distribution sort),又稱“桶子法”(bucket sort)-或bin sort,顧名思義,它是通過鍵值的各個位的值,將要排序的元素分配至某些“桶”中,達到排序的作用
基數排序法是屬於穩定性的排序,基數排序法的是效率高的穩定性排序法
基數排序(Radix Sort)是桶排序的擴展
基數排序是1887年赫爾曼·何樂禮發明的。它是這樣實現的:將整數按位數切割成不同的數字,然後按每個位數分別比較。
2.基數排序基本思想
- 將所有待比較數值統一爲同樣的數位長度,數位較短的數前面補零。然後,從最低位開始,依次進行一次排序。這樣從最低位排序一直到最高位排序完成以後, 數列就變成一個有序序列。
3.java代碼推導過程
package cn.smallmartial.sort;
import java.util.Arrays;
/**
* @Author smallmartial
* @Date 2019/6/9
* @Email [email protected]
*/
public class RadixSort {
public static void main(String[] args) {
int arr[] = {53, 3, 542, 748, 14, 214};
radixSort(arr);
}
public static void radixSort(int[] arr){
//定一個二維數組,表示10個桶
int[][] bucket = new int[10][arr.length];
//爲了記錄每個桶中存放的數據,定義一個一維數組記錄各個桶中的數據
int[] bucketElementCounts = new int[10];
//第一輪 對各位進行處理
for (int j = 0; j < arr.length; j++) {
int digitOfElement = arr[j]%10;
//放入對應的桶中
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
bucketElementCounts[digitOfElement]++;
}
//按照桶的順序,依次取出下標
int index = 0;
for (int k = 0; k < bucketElementCounts.length; k++) {
//如果桶中有數據 放入一維數組
if (bucketElementCounts[k] != 0){
for (int l = 0; l < bucketElementCounts[k]; l++) {
//取出元素放入arr
arr[index++] = bucket[k][l];
}
}
//第一輪處理後 bucketElementCounts[k] = 0
bucketElementCounts[k] = 0;
}
System.out.println(Arrays.toString(arr));
//第一輪 對各位進行處理
for (int j = 0; j < arr.length; j++) {
int digitOfElement = arr[j]/10%10;
//放入對應的桶中
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
bucketElementCounts[digitOfElement]++;
}
//按照桶的順序,依次取出下標
index = 0;
for (int k = 0; k < bucketElementCounts.length; k++) {
//如果桶中有數據 放入一維數組
if (bucketElementCounts[k] != 0){
for (int l = 0; l < bucketElementCounts[k]; l++) {
//取出元素放入arr
arr[index++] = bucket[k][l];
}
}
bucketElementCounts[k] = 0;
}
System.out.println(Arrays.toString(arr));
//第三輪 對各位進行處理
for (int j = 0; j < arr.length; j++) {
int digitOfElement = arr[j]/100%10;
//放入對應的桶中
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
bucketElementCounts[digitOfElement]++;
}
//按照桶的順序,依次取出下標
index = 0;
for (int k = 0; k < bucketElementCounts.length; k++) {
//如果桶中有數據 放入一維數組
if (bucketElementCounts[k] != 0){
for (int l = 0; l < bucketElementCounts[k]; l++) {
//取出元素放入arr
arr[index++] = bucket[k][l];
}
}
//bucketElementCounts[k] = 0;
}
System.out.println(Arrays.toString(arr));
}
}
4.java代碼
package cn.smallmartial.sort;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
/**
* @Author smallmartial
* @Date 2019/6/9
* @Email [email protected]
*/
public class RadixSort {
public static void main(String[] args) {
// int arr[] = {53, 3, 542, 748, 14, 214};
int[] arr = new int[80000];
for (int i = 0; i < arr.length -1 ; i++) {
arr[i] = (int)(Math.random()*80000);
}
Date data = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dataStr = simpleDateFormat.format(data);
System.out.println("排序前的時間"+dataStr);
radixSort(arr);
Date data2 = new Date();
// SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String data2Str = simpleDateFormat.format(data2);
System.out.println("排序前的時間"+data2Str);
}
public static void radixSort(int[] arr){
//最終版
int max = arr[0];
for (int i = 1; i < arr.length ;i++) {
if (arr[i] >max){
max = arr[i];
}
}
//得到最大的幾位數
int maxLength = (max +"").length();
//定一個二維數組,表示10個桶
int[][] bucket = new int[10][arr.length];
//爲了記錄每個桶中存放的數據,定義一個一維數組記錄各個桶中的數據
int[] bucketElementCounts = new int[10];
for (int i = 0 ,n = 1; i < maxLength; i++, n*=10) {
for (int j = 0; j < arr.length; j++) {
int digitOfElement = arr[j]/n%10;
//放入對應的桶中
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
bucketElementCounts[digitOfElement]++;
}
//按照桶的順序,依次取出下標
int index = 0;
for (int k = 0; k < bucketElementCounts.length; k++) {
//如果桶中有數據 放入一維數組
if (bucketElementCounts[k] != 0){
for (int l = 0; l < bucketElementCounts[k]; l++) {
//取出元素放入arr
arr[index++] = bucket[k][l];
}
}
//第一輪處理後 bucketElementCounts[k] = 0
bucketElementCounts[k] = 0;
}
// System.out.println("第"+(i+1)+"輪"+Arrays.toString(arr));
}
}
}
運行結果:
5.常用排序算法對比
穩定:如果a原本在b前面,而a=b,排序之後a仍然在b的前面;
不穩定:如果a原本在b的前面,而a=b,排序之後a可能會出現在b的後面;
內排序:所有排序操作都在內存中完成;
外排序:由於數據太大,因此把數據放在磁盤中,而排序通過磁盤和內存的數據傳輸才能進行;
時間複雜度: 一個算法執行所耗費的時間。
空間複雜度:運行完一個程序所需內存的大小。
n: 數據規模
k: “桶”的個數
In-place: 不佔用額外內存
Out-place: 佔用額外內存