基数排序(radix sort)属于分配式排序。基数排序的实现方法分为两种:MSD和LSD。
MSD:最高位优先法(Most Significant Digit First),先比较最高位,最高位分到一个桶中的,再按照第二位进行分桶…,知道分到最后一位,然后再从最小的桶中逐层向上,把元素都拿出来,即完成排序。
LSD:最低位优先法(Least Significant Digit First),先比较最低位,也就是个位,进行分桶,分桶过程中分到一个桶中的数据直接追加到桶中即可,无需排序。然后将所有同种的元素按桶的顺序拿出,重新组成序列,然后比较十位,进行分桶…直到比较到最高位,重新组成序列即可完成排序。
举例了解如下:
比较优秀的文章集合:
1、图解+实现 https://blog.csdn.net/lemon_tree12138/article/details/51695211.
2、图解:https://blog.csdn.net/weixin_44537194/article/details/87302788.
3、桶排序的说明https://blog.csdn.net/developer1024/article/details/79770240.
4、基数排序的优化https://blog.csdn.net/yutianzuijin/article/details/22876017.
自己在学习过程中参考编写的如下:留作笔记
编写代码,按照步骤来即可:
注:读取按照下面方式 从上到下,从左到右 进行读取。
【53,3,542,748,14,214】
个位数:将所有数据按照个位数分配到每个桶中。然后依次读取
2: 542
3: 53 3
4: 14 214
8: 748
1 [542, 53, 3, 14, 214, 748]
十位数:将所有数据按照十位数分配到每个桶中。然后依次读取
0: 3
1: 14 214
4: 542 748
5: 53
2 [3, 14, 214, 542, 748, 53]
百位数:将所有数据按照百位数分配到每个桶中。然后依次读取
0: 3 14 53
2: 214
5: 542
7: 748
3 [3, 14, 53, 214, 542, 748]
//打印桶中数据
for(int j = 0 ;j<bucketElementCounts.length;j++) {
System.out.println(j+":"+Arrays.toString(bucket[j]));
}
测试程序
public static void main(String[] args) {
int arr[] = {53,3,542,748,14,214};
radixsort(arr);
int arr1[] = {53,3,542,748,14,214};
radixsortBystep(arr1);
int[] arr2 = new int[8000000];
for(int i =0;i<8000000;i++){
arr2[i] =(int)( Math.random()*80000000); //[0-8000000]
}
SimpleDateFormat simdate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
System.out.println(simdate.format(new Date()));
radixsort(arr2);
System.out.println(simdate.format(new Date()));
}
输出结果:
748
个位[542, 53, 3, 14, 214, 748]
十位[3, 14, 214, 542, 748, 53]
百位[3, 14, 53, 214, 542, 748]
2020-11-16 20:51:40 127
79999993
2020-11-16 20:51:41 033
基数排序的算法实现
public static void radixsort(int[] arr) {
//得到元素中最大数的位数
int max = arr[0];
for(int i = 1;i<arr.length;i++) {
if(max < arr[i]) {
max = arr[i];
}
}
System.out.println(max);
//得到最大数的位数
int maxLength = (max + "").length();
//1、二维数组包含10个一维
//2、为了防止放置数据的时候溢出,则每一个数组(桶)定义为arr.length
int[][] bucket = new int[10][arr.length];
//记录每个桶中有多少有效数据
int[] bucketElementCounts = new int[10];
for(int i = 0,n=1;i<maxLength;i++ , n*=10) {
//1、放在桶中
for(int j=0 ; j<arr.length ;j++) {
int digitOfElement = arr[j]/n%10;
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j]; //放到对应桶
bucketElementCounts[digitOfElement]++; //有效位数+1
}
//2、从桶中取出
int index = 0; //按照顺序取出
for(int k=0;k<bucketElementCounts.length;k++) { //遍历每一个桶
if(bucketElementCounts[k]!=0) { //判断桶中是否有数据
//如果有数据,循环该桶,并将其放入到arr中
//System.out.print(k+ ": ");
for(int l =0 ; l<bucketElementCounts[k];l++) {
arr[index] = bucket[k][l]; //取出元素放到arr中
//System.out.print(bucket[k][l]+ " ");
index++;
}
//System.out.print("\n\r");
}
//每一轮都要清空
bucketElementCounts[k] = 0;
}
//System.out.println((i+1) + " "+Arrays.toString(arr));
}
}
基数排序算法的分步实现 :
public static void radixsortBystep(int[] arr) {
//1、二维数组包含10个一维
//2、为了防止放置数据的时候溢出,则每一个数组(桶)定义为arr.length
int[][] bucket = new int[10][arr.length];
//记录每个桶中有多少有效数据
int[] bucketElementCounts = new int[10];
//========第一次,取个位数进行排序========//
//1、放在桶中
for(int j=0 ; j<arr.length ;j++) {
int digitOfElement = arr[j]%10; //取出个位数
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j]; //放到对应桶
bucketElementCounts[digitOfElement]++; //有效位数+1
}
//2、从桶中取出
int index = 0; //按照顺序取出
for(int k=0;k<bucketElementCounts.length;k++) { //遍历每一个桶
if(bucketElementCounts[k]!=0) { //判断桶中是否有数据
//如果有数据,循环该桶,并将其放入到arr中
for(int l =0 ; l<bucketElementCounts[k];l++) {
arr[index] = bucket[k][l]; //取出元素放到arr中
index++;
}
}
//每一轮都要清空
bucketElementCounts[k] = 0;
}
System.out.println("个位"+Arrays.toString(arr));
//========第二次,取十位数进行排序========//
//1、放在桶中
for(int j=0 ; j<arr.length ;j++) {
int digitOfElement = arr[j]/10%10; //取出十位数
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j]; //放到对应桶
bucketElementCounts[digitOfElement]++; //有效位数+1
}
//2、从桶中取出
index = 0; //按照顺序取出
for(int k=0;k<bucketElementCounts.length;k++) { //遍历每一个桶
if(bucketElementCounts[k]!=0) { //判断桶中是否有数据
//如果有数据,循环该桶,并将其放入到arr中
for(int l =0 ; l<bucketElementCounts[k];l++) {
arr[index] = bucket[k][l]; //取出元素放到arr中
index++;
}
}
//每一轮都要清空
bucketElementCounts[k] = 0;
}
System.out.println("十位"+Arrays.toString(arr));
//========第三次,取百位数进行排序========//
//1、放在桶中
for(int j=0 ; j<arr.length ;j++) {
int digitOfElement = arr[j]/100%10; //取出百位数
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j]; //放到对应桶
bucketElementCounts[digitOfElement]++; //有效位数+1
}
//2、从桶中取出
index = 0; //按照顺序取出
for(int k=0;k<bucketElementCounts.length;k++) { //遍历每一个桶
if(bucketElementCounts[k]!=0) { //判断桶中是否有数据
//如果有数据,循环该桶,并将其放入到arr中
for(int l =0 ; l<bucketElementCounts[k];l++) {
arr[index] = bucket[k][l]; //取出元素放到arr中
index++;
}
}
//每一轮都要清空
bucketElementCounts[k] = 0;
}
System.out.println("百位"+Arrays.toString(arr));
}
完。