数据结构之基数排序
基数排序(RadixSort)
1.基数排序属于分配式排序,又称桶子法,它是通过键值的各个位的值,将要排序的元素分配至某些桶中,达到排序的作用。
2.基数排序是属于稳定性的排序,基数排序法的是效率高的稳定性排序法。
3.基数排序是桶排序的扩展
稳定性:比如要对1,5,1,2,3排序。结果为1,1,2,3,5
第一个1是前面的1,第二个1是后面的1
4.将所有待比较的数值统一为同样的数位长度,数位较短的数前面补零。然后从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。
public class RadixSort {
public static void main(String[] args) {
int[] arr = {53, 3, 542, 748, 14, 214};
radixSort(arr);
}
/**
* 基数排序
* 1.第一轮针对每个数的个位数进行大小排序,将得到的数组 拷贝给原数组
* 2.第二轮针对每个数的十位数进行大小排序。将得到的数组 拷贝给原数组
* 3.第三轮。。。。。。百位数、、、、、、、
* 4.进行数组中最大元素的最高位次排序后,所得到的数组就是有序数组
*/
public static int[] radixSort(int[] arr) {
//一、先找到数组中最大的数
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
//得到最大位数的位数
int maxLength = (max + "").length();
//定义二维数组,表示十个桶。每个桶都是一个一维数组。
//为了防止在放入数时栈溢出,则每个桶(一维数组)的大小定义为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) {
//针对每个元素对应的位进行排序处理,第一次是个位,第二次是十位,依次类推。
for (int j = 0; j < arr.length; j++) {
//取出每个元素对应的值
int digitOfElement = arr[j] / n % 10;
//放入到对应的桶中
//bucket[3][0] = 53;
//bucketElementCounts[3]++ ==> 1
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
bucketElementCounts[digitOfElement]++;
}
//按照这个桶的顺序(一维数组的下标依次取出数据,放入原来的数组)
int index = 0;
//遍历每一个桶,将桶中的数据放入到原来的数组
for (int k = 0; k < bucketElementCounts.length; k++) {
//如果桶中有数据,才放入
if (bucketElementCounts[k] != 0) {
//循环该桶即第k个桶(即第k个一维数组)
for (int l = 0; l < bucketElementCounts[k]; l++) {
//取出元素放入到arr
arr[index++] = bucket[k][l];
}
}
//第i+1轮处理后,需要将每个bucketElementCounts[k]置零
bucketElementCounts[k] = 0;
}
System.out.println("第"+(i+1)+"轮排序后的数组");
System.out.println(Arrays.toString(arr));
}
return arr;
}
}
输出结果:
第1轮排序后的数组
[542, 53, 3, 14, 214, 748]
第2轮排序后的数组
[3, 14, 214, 542, 748, 53]
第3轮排序后的数组
[3, 14, 53, 214, 542, 748]
基数排序时间测试,8000000个数据
public class RadixSortTimeTest {
public static void main(String[] args) {
int[] arr = new int[8000000];
for (int i = 0; i < 8000000; i++) {
arr[i] = (int) (Math.random() * 8000000);
}
Date date1 = new Date();
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String s1 = simpleDateFormat1.format(date1);
System.out.println("排序前的时间:" + s1);
RadixSort.radixSort(arr);
Date date2 = new Date();
SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String s2 = simpleDateFormat2.format(date2);
System.out.println("排序前的时间:" + s2);
}
}
输出结果:
排序前的时间:2021-10-06 15:52:29
排序前的时间:2021-10-06 15:52:30