参考文章:
https://www.cnblogs.com/guoyaohua/p/8600214.html 十大经典排序算法最强总结(含JAVA代码实现)(强推)
https://www.cnblogs.com/skywang12345/p/3603669.html 基数排序
温馨提示:
如果代码看不懂,那就拿出纸和笔,照着代码流程走一遍,走一遍,再走一遍,另外看基数排序,最好先把其他的排序都给看了,再看这个会好理解一些。
基数排序分析:
平均时间复杂度 | 最好情况 | 最坏情况 | 空间复杂度 | 排序方式 | 稳定性 |
O(n*k) | O(n*k) | O(n*k) | O(n+k) | Out-place | 稳定 |
基数排序原理:
基数排序也是非比较的排序算法,对每一位进行排序,从最低位开始排序,复杂度为O(kn),n为数组长度,k为数组中的数的最大的位数;
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以是稳定的。
基数排序算法描述:
- 取得数组中的最大数,并取得位数;
- arr为原始数组,从最低位开始取每个位组成radix数组;
- 对radix进行计数排序(利用计数排序适用于小范围数的特点);
基数排序算法原理图解:
图解1:
图解2:
在上图中,首先将所有待比较树脂统一为统一位数长度,接着从最低位开始,依次进行排序。
1. 按照个位数进行排序。
2. 按照十位数进行排序。
3. 按照百位数进行排序。
排序后,数列就变成了一个有序序列。
基数排序 Java 代码实现:
代码一:
package com.sorting.algorithm;
import java.util.ArrayList;
public class RadixSort {
public static int[] radixSort(int[] array){
// 寻找数组中的最大数 max ,并求出最大数的位数maxDigit
int maxDigit = 0,max = array[0];
for (int i = 0; i < array.length; i++) {
if(max < array[i])
max = array[i];
}
while(max != 0){
max /= 10;
maxDigit++;
}
// 设立bucketList 数组,0-10,存储数字0-9,0-9的数组中可以存放多个数组元素,即个位或者十位相同时,就会存放到一起。
ArrayList<ArrayList<Integer>> bucketList = new ArrayList<ArrayList<Integer>>();
// 初始化bucketList
for(int i = 0; i < 10; i++){
bucketList.add(new ArrayList<Integer>());
}
System.out.println("排序过程:");
// mod 取余数用,div 是用来取余之后提取个位、十位、百位的数字
int mod =10, div =1;
for(int i = 0; i < maxDigit; mod *= 10, div *= 10, i++ ){
// 按照0-9 的数字顺序,将数组中的元素放入到bucketList中,0-9每个数字可存放多个数组元素
for (int j = 0; j < array.length; j++) {
int num = (array[j]%mod)/div;
bucketList.get(num).add(array[j]);
}
// 将已经按照个位或十位或百位 排序的元素,重新放入 array数组中,以达到按照个位或十位或百位排序的效果
int index = 0 ;
for (int j = 0; j < bucketList.size(); j++) {
for (int k = 0; k < bucketList.get(j).size(); k++) {
array[index++] = bucketList.get(j).get(k);
}
bucketList.get(j).clear();
}
printArr(array);
}
return array;
}
public static void printArr(int[] array){
for (int i = 0; i < array.length; i++) {
if(i != array.length-1)
System.out.print(array[i]+ ", ");
else
System.out.println(array[i]);
}
System.out.println();
}
public static void main(String[] args) {
int[] array = {53,3,542,748,14,214,154,63,616};
System.out.println("排序之前:");
printArr(array);
int[] sortedArr = radixSort(array);
System.out.println("排序之后:");
printArr(sortedArr);
}
}
代码二:
package com.sorting.algorithm;
public class RadixSort2 {
public static int[] radixSort(int[] array){
// 寻找最大数
int max = array[0];
for (int i = 0; i < array.length; i++) {
if(max < array[i])
max = array[i];
}
System.out.println("排序过程:");
// exp 为应该取模整除的数字,依次类推
// exp =1, 取个位
// exp =10, 取十位
// exp=100, 取百位
int exp = 1;
// 对数组中的元素每一位进行排序,即基数排序
while(max/exp > 0){
radixSort(array,exp);
exp *= 10;
}
return array;
}
private static void radixSort(int[] array, int exp){
// output 为缓存数组,暂存排序后的数组
int [] output = new int[array.length];
int [] buckets = new int[10];
// 计数排序中,统计各元素出现的个数
for(int i = 0; i < array.length; i++)
buckets[(array[i]/exp)%10]++;
// 计数排序汇中,计算数组元素的排序位置
for(int i = 1; i < buckets.length; i++)
buckets[i] = buckets[i] + buckets[i-1];
// 这个要逆序来赋值,因为位置相同的数组元素,越靠前的,他的位置就越靠后
for(int i = array.length-1 ; i >= 0; i--){
buckets[(array[i]/exp)%10]--;
output[buckets[(array[i]/exp)%10]] = array[i];
}
// 将缓存数组总排序好的数组,重新赋值给数组 array
for(int i = 0; i < array.length; i++)
array[i] = output[i];
printArr(output);
}
public static void printArr(int[] array){
for (int i = 0; i < array.length; i++) {
if(i != array.length-1)
System.out.print(array[i]+ ", ");
else
System.out.println(array[i]);
}
System.out.println();
}
public static void main(String[] args) {
int[] array = {53,3,542,748,14,214,154,63,616};
System.out.println("排序之前:");
printArr(array);
int[] sortedArr = radixSort(array);
System.out.println("排序之后:");
printArr(sortedArr);
}
}
基数排序代码测试:
代码一测试:
代码二测试: