返回
计数排序及基数排序算法的Java实现
后端
2023-12-10 09:46:59
上期我们谈了快速排序和希尔排序。本期我们将一起学习计数排序和基数排序算法。
1. 计数排序
计数排序是一种简单有效的排序算法,适用于数据范围较小的情况。其原理是将数据按照其值的大小划分为多个桶,然后将每个桶中的数据依次取出,形成一个有序序列。
1.1 时间复杂度
计数排序的时间复杂度为O(n + k),其中n为数据个数,k为数据范围。
1.2 空间复杂度
计数排序的空间复杂度为O(n + k),其中n为数据个数,k为数据范围。
1.3 代码实现
public static void countingSort(int[] arr) {
// 找到最大值
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
// 创建计数数组
int[] count = new int[max + 1];
// 统计每个元素出现的次数
for (int i = 0; i < arr.length; i++) {
count[arr[i]]++;
}
// 将计数数组中的元素累加
for (int i = 1; i <= max; i++) {
count[i] += count[i - 1];
}
// 根据计数数组中的值重新排列元素
int[] sortedArr = new int[arr.length];
for (int i = arr.length - 1; i >= 0; i--) {
int index = count[arr[i]] - 1;
sortedArr[index] = arr[i];
count[arr[i]]--;
}
// 将排序后的数组复制回原数组
for (int i = 0; i < arr.length; i++) {
arr[i] = sortedArr[i];
}
}
2. 基数排序
基数排序是一种非比较型排序算法,适用于数据范围较大的情况。其原理是将数据按照其值的大小划分为多个桶,然后将每个桶中的数据依次取出,形成一个有序序列。
2.1 时间复杂度
基数排序的时间复杂度为O(nk),其中n为数据个数,k为数据范围的位数。
2.2 空间复杂度
基数排序的空间复杂度为O(n + k),其中n为数据个数,k为数据范围的位数。
2.3 代码实现
public static void radixSort(int[] arr) {
// 找到最大值
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
// 计算数据范围的位数
int exp = 1;
while (max / exp > 0) {
countingSort(arr, exp);
exp *= 10;
}
}
public static void countingSort(int[] arr, int exp) {
// 创建计数数组
int[] count = new int[10];
// 统计每个元素出现的次数
for (int i = 0; i < arr.length; i++) {
int index = arr[i] / exp % 10;
count[index]++;
}
// 将计数数组中的元素累加
for (int i = 1; i < count.length; i++) {
count[i] += count[i - 1];
}
// 根据计数数组中的值重新排列元素
int[] sortedArr = new int[arr.length];
for (int i = arr.length - 1; i >= 0; i--) {
int index = count[arr[i] / exp % 10] - 1;
sortedArr[index] = arr[i];
count[arr[i] / exp % 10]--;
}
// 将排序后的数组复制回原数组
for (int i = 0; i < arr.length; i++) {
arr[i] = sortedArr[i];
}
}
3. 总结
计数排序和基数排序都是简单高效的排序算法,适用于不同的数据情况。计数排序适用于数据范围较小的情况,时间复杂度为O(n + k),其中n为数据个数,k为数据范围。基数排序适用于数据范围较大的情况,时间复杂度为O(nk),其中n为数据个数,k为数据范围的位数。