1. 基数排序算法
1.1 基数排序的介绍
基数排序(Radix Sort)是桶排序的扩展。基数排序属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort
基数排序法是属于稳定性的排序,而且效率特别高,但是特别占用内存空间,数据量大容易造成内存溢出。稳定性是指当两个相同的元素,进行排序后,它们的次序并不会发现变化
基数排序基本思想:将所有待比较整数数值统一为同样的数位长度,数位较短的数前面补零。然后从最低位开始,按最低位将要排序的元素分配至对应的”桶“中,进行一次排序,可以保证数据的低位顺序在后面的高位排序中是有序的。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。注意基数排序不支持负整数,如果要支持则需要进行拓展
1.2 基数排序的程序实现
需求:有一组无序的数据{53, 3, 542, 748, 14, 214},请用基数排序算法实现从小到大排列。因最大的数到百位,所有需要进行3轮排序
步骤如下:
- 第1轮排序(按照个位排序): 事先准备10个数组(10个桶), 0-9号桶分别对应个位数的0-9。将各个数,按照个位数大小放入到对应的各个桶中。然后依次从0-9号桶,按照加入元素的先后顺序取出,再将桶中的数据清空。第1轮排序后顺序为:{542, 53, 3, 14, 214, 748}
- 第2轮排序(按照十位排序):将各个数,按照十位数大小放入到对应的各个桶中 。然后依次从0-9号桶,按照加入元素的先后顺序取出,再将桶中的数据清空。第2轮排序后顺序为:{3, 14, 214, 542, 748, 53}
3. 第3轮排序(按照百位排序):将各个数,按照百位数大小放入到对应的各个桶中。然后依次从0-9号桶,按照加入元素的先后顺序取出,再将桶中的数据清空。第3轮排序后顺序为:{3, 14, 53, 214, 542, 748}。此时排序完成
程序如下:
import java.util.Arrays;
public class RadixSort {
public static void main(String[] args) {
int[] array = {53, 3, 542, 748, 14, 214};
radixSort(array);
System.out.println("基数排序后 " + Arrays.toString(array));
}
// 基数排序方法实现
public static void radixSort(int[] array) {
// 得到数组中的最大数
int max = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
}
// 得到最大数的位数
int maxLength = (max + "").length();
// 定义一个二维数组
// 第一个维度表示桶,0-9号桶分别对应位数0-9
// 第二个维度用于储存每个桶对应的数据,大小为原数组的大小,以防所有数的同一位数都一样
int[][] bucket = new int[10][array.length];
// 定义一个数组,数组的index和桶的号对应,数组index对应的值就是对应桶中保存元素的个数
int[] bucketElementCounts = new int[10];
// 最大数有多少位,就需要进行多少次排序
// n用于计算每个数对应位数的值
for (int i = 1, n = 1; i <= maxLength; i++, n *= 10) {
// 对每个元素进行遍历
for (int arrayIndex = 0; arrayIndex < array.length; arrayIndex++) {
// 求出对应位数的值
int digitOfElement = array[arrayIndex] / n % 10;
// 保存到对应的桶中
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = array[arrayIndex];
bucketElementCounts[digitOfElement]++;
}
// 依次从每个桶,按照加入元素的先后顺序取出,再将桶中的数据清空
// 取数据保存到原数组的index
int copy2ArrayIndex = 0;
// 遍历每一个桶
for (int bucketIndex = 0; bucketIndex < bucketElementCounts.length; bucketIndex++) {
// 桶中有数据,才进行数据取出
if (bucketElementCounts[bucketIndex] != 0) {
// 遍历一个桶,将里面的数据顺序取出
for (int elementIndex = 0; elementIndex < bucketElementCounts[bucketIndex]; elementIndex++) {
// 取出数据放入原数组
array[copy2ArrayIndex++] = bucket[bucketIndex][elementIndex];
}
}
// 将每个桶的元素个数置为0,达到将桶中数据清空的效果
bucketElementCounts[bucketIndex] = 0;
}
}
}
}
运行程序,结果如下:
基数排序后 [3, 14, 53, 214, 542, 748]