基数排序(radix sort)又称桶排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。以下是基数排序的详细知识点:
一、定义与原理
- 基数排序又称桶排序(bucket sort),是一种分配式排序算法。它通过将所有数字分配到应在的位置,最后再覆盖到原数组完成排序的过程。
- 将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。
- 基数排序分为最高位优先法(MSD)和最低位优先法(LSD)两种。MSD从最高位开始比较,而LSD从最低位开始比较。
二、基本步骤
- 初始化桶:根据待排序元素的最大位数,确定需要进行的趟数。每趟排序时,创建与基数(如10进制下的10个桶)数量相等的桶。
- 分配元素:从最低有效位开始,遍历待排序序列,将每个元素按当前位数的值放入对应的桶中。
- 收集元素:按照桶的顺序,依次从每个桶中取出元素,形成新的一组序列。这一步完成了该位数上的排序。
- 重复以上过程:对更高位数进行相同的操作,直到处理完最高有效位。每趟排序后,待排序序列都会变得更有序。
- 合并结果:经过多趟排序后,待排序序列已按每一位有序,最终合并得到全局有序序列。
三、特点
- 基数排序是稳定的排序算法,即相等元素的相对顺序在排序后保持不变。
- 基数排序的时间复杂度为O(nlog(r)m),其中n为待排序元素个数,r为所采取的基数(如十进制下r=10),m为堆数(即桶的个数)。
- 基数排序的空间复杂度为O(n+k),其中k为待排序元素的最大位数。
四、适用场景
- 基数排序适用于待排序数据可以分割出独立“位”来比较的情况,如整数。
- 对于位数较少的正整数,基数排序通常具有较高的效率。但对于位数较多的数据,可能需要较多的内存空间来存储桶和辅助数组。
五、代码实现
基数排序的代码实现通常包括初始化桶、分配元素、收集元素和合并结果等步骤。具体的实现方式可能因编程语言和具体需求而有所不同。例如,在Java中,可以使用二维数组来表示桶,并使用循环和条件语句来实现元素的分配和收集。在Python中,可以使用列表和字典等数据结构来实现类似的功能。
以下是一个使用Java编写的基数排序(LSD,最低位优先)的示例代码。这个示例中,我们假设输入是一个非负整数数组
public class RadixSort {
// 获取一个数的最大位数
private static int getMaxDigit(int[] arr) {
int max = arr[0];
for (int num : arr) {
if (num > max) {
max = num;
}
}
int digit = 0;
while (max > 0) {
max /= 10;
digit++;
}
return digit;
}
// 基数排序
public static void radixSort(int[] arr) {
int maxDigit = getMaxDigit(arr);
// 为每一位数创建一个桶
int[][] bucket = new int[10][arr.length];
int[] count = new int[10]; // 每个桶中的元素数量
// 从最低位开始排序
for (int i = 1; i <= maxDigit; i++) {
// 将元素分配到桶中
for (int j = 0; j < arr.length; j++) {
int digit = (arr[j] / ((int) Math.pow(10, i - 1))) % 10;
bucket[digit][count[digit]] = arr[j];
count[digit]++;
}
// 将桶中的元素收集回数组
int index = 0;
for (int k = 0; k < 10; k++) {
if (count[k] == 0) continue;
for (int l = 0; l < count[k]; l++) {
arr[index++] = bucket[k][l];
}
count[k] = 0; // 重置桶中元素数量
}
}
}
// 测试基数排序
public static void main(String[] args) {
int[] arr = {170, 45, 75, 90, 802, 24, 2, 66};
radixSort(arr);
for (int num : arr) {
System.out.print(num + " ");
}
}
}
在这个示例中,我们首先定义了一个getMaxDigit
方法来获取数组中最大数的位数,以便知道我们需要进行多少轮排序。然后,我们定义了基数排序的主体方法radixSort
,它使用了一个二维数组bucket
来模拟桶,并使用count
数组来跟踪每个桶中的元素数量。
在排序过程中,我们从最低位开始,依次处理每一位数,将元素分配到对应的桶中,然后再从桶中收集回原数组。这个过程重复进行,直到最高位被处理完。
最后,我们在main
方法中测试了基数排序,并打印了排序后的结果。