基数排序(radix sort)
1.基本介绍
1)基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,顾名思义,它是通过键值的各个位的值,将要排序的元素分配至某些“桶”中,达到排序的作用。
2)基数排序法是属于稳定性的排序,基数排序法的是效率高的稳定性排序法。
3)基数排序(Radix Sort)是桶排序的扩展。
4)基数排序是1887年赫尔曼·何乐礼发明的。它是这样实现的:将整数按位数切割成不同的数字,然后按每个位数分别比较。
2.基本思想
将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。
3.基数排序图文说明
将数组 {53, 3, 542, 748, 14, 214} 使用基数排序, 进行升序排序
- 基数排序的说明:
(1)基数排序是对传统桶排序的扩展,速度很快.
(2)基数排序是经典的空间换时间的方式,占用内存很大, 当对海量数据排序时,容易造成 OutOfMemoryError 。
(3)基数排序时稳定的。[注:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的]
(4)有负数的数组,我们不用基数排序来进行排序, 如果要支持负数,访问支持负数的基数排序
-代码:
import java.util.Arrays;
public class RadixSort {
public static void main(String[] args) {
/*int arr[] = { 53, 3, 542, 748, 14, 214};
System.out.println("排序之前: " + Arrays.toString(arr));
radixSort(arr);
System.out.println("排序之后: " + Arrays.toString(arr));*/
int arr[] = new int[8000000];
int temp[] = new int[arr.length];
for (int i = 0; i < 8000000; i++) {
arr[i] = (int)(Math.random() * 1000000000); //随机生成一个[0,1000000)之间的数
}
//开始时间
long startTime = System.currentTimeMillis();
radixSort(arr);
long endTime = System.currentTimeMillis();
System.out.println("排序花了: " + (endTime - startTime) + "ms");
}
//基数排序
public static void radixSort(int arr[]){
//1.得到该数组中最大的值
int max = arr[0]; //假设第一个数为最大
for (int i = 0; i < arr.length; i++) {
if(arr[i] > max){
max = arr[i];
}
}
//计算得到的最大的数时几位数(这里实现的基数排序不能给负数排序)
int maxLength = (max + "").length();
//2.定义一个二维数组,表示10个桶,每一个一维数组就是一个桶
//说明:
//(1)二维数组包含10个一维数组
//(2)为了防止在放入数的时候数据溢出,将每个桶(一维数组)大小定义为arr.length
//(3)基数排序是典型的空间换时间的算法
int bucket[][] = new int[10][arr.length];
//为了记录每个桶中实际有多少个数据,需要定义一个一维数组来记录每个桶中每次放入的数据的个数
//例如:bucketElementCounts[1]就表示bucket[1]这个桶中实际存放的数据的个数
int[] bucketElementCounts = new int[10];
for (int i = 0, n = 1; i < maxLength; n *= 10, i++) { //数组中最大数是几位,外循环就是多少次
for (int j = 0; j < arr.length; j++) {
//判断每个数的个/十/百...的位数是多少,第一轮计算个位数,第二轮计算十位数...
int digitOfElement = arr[j] / n % 10;
bucket[digitOfElement][bucketElementCounts[digitOfElement]++] = arr[j];
}
//将数按照规则放入桶中之后,在按序从桶中取出数据放入arr数组中
int index = 0;
for (int k = 0; k < bucketElementCounts.length; k++) {
//如果桶中有数据,则将其放入原数组中
if(bucketElementCounts[k] != 0){
for (int l = 0; l < bucketElementCounts[k]; l++) {
arr[index++] = bucket[k][l];
}
}
//每(i+1)轮处理完之后,都需要将bucketElementCounts[k] = 0,重新置位0 !!!!
bucketElementCounts[k] = 0;
}
// System.out.println("第" + (i + 1) + "轮处理后:" + Arrays.toString(arr));
}
}
}