JAVA数据结构 08.排序算法
2. 八大排序算法 实现 解析 和优化
2.7 基数排序(桶排序)
算法介绍:基数排序是桶排序的扩展,是使用空间换时间的经典算法。桶排序顾名思义,它是通过键值的各个位的值,将要排序的元素分配到某些“桶”中,达到排序的目的。基数排序是效率高的稳定性排序法,它是将整数按位数切割成不同的数字,然后按每个位数分别比较。
算法思想:
- 创建10个桶bucket,标号分别为0~9,对应个位数值为0~9;
- 获取数组arr中最大值的位数maxLength,算法的循环次数就是位数的值maxLength;
- 每一轮循环中,遍历数组arr,取出arr特定位数的值(第一次循环取个位数,第二次取十位数,依次累加),放入到相应的桶中,在按顺序遍历10个桶,依次取出数据重新放入数组arr中;
- 当执行maxLength循环后,数组中所有数字的每一位都进行了拆分入桶,顺序出桶,此时数组有序。
算法图解:
代码实现:
import java.util.Arrays;
public class RadixSort {
public static void main(String args[]){
int[] arr = {53,3,542,748,14,214};
radixSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void radixSort(int[] arr){
//1.空间用量初始化
// 定义一个二维数组来表示10个桶bucket
int[][] bucket = new int[10][arr.length];
// 定义一个一维数组记录每个桶中的数字个数
int[] bucketElementCounts = new int[10];
//2.找到数组中最大的数的位数
int max = arr[0];
for (int i = 0; i <arr.length ; i++) {
if(arr[i]>max) max = arr[i];
}
int maxLength = max+"".length();
//3.循环进行maxLength次的顺序放入桶和顺序拿出桶
for(int i = 0;i < maxLength;i++){
//3.1 放入桶中
for (int j = 0; j < arr.length ; j++) {
//3.1.1 取出当前循环位的值:第一次循环取个位数,第二次取十位数,依次累加
int digitOfElement =(int)(arr[j] / Math.pow(10,i) % 10);
//3.1.2 将数组中的数放入到下标为相应digitOfElement的桶中,记录桶中的数字数量bucketElementCounts[j]
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
bucketElementCounts[digitOfElement]++;
}
//3.2 按桶的顺序依次取出数字,放入原数组arr
int index = 0;
for (int j = 0; j < bucketElementCounts.length ; j++) {
if(bucketElementCounts[j] != 0){
for (int k = 0; k <bucketElementCounts[j] ; k++) {
arr[index++] = bucket[j][k];
}
// 取出后将记录个数值清空
bucketElementCounts[j] = 0;
}
}
}
}
}
说明:
- 基数排序是对传统桶排序的扩展,速度很快;
- 基数排序是经典的空间换时间的方式,占用内存很大,当对海量数据排序时,容易造成OutOfMemoryError;
- 基数排序是稳定的;
- 有负数的数组,不建议用基数排序,需要进行额外的绝对值以及反转操作。