基数排序算法是一种非比较排序算法,其原理是根据每个元素的位值来进行排序,又称桶排序。基数排序算法可以按照位数来排序,最终得到一个有序的序列。这种排序方法的效率较高,可以处理大量数据。
基数排序的具体实现步骤如下:
-
将待排序的数列按照个位数先进行排序,将排序后的数列存入一个桶中。
-
将桶中的数列按照十位数进行排序,将排序后的数列存入一个桶中。
-
将桶中的数列按照百位数进行排序,将排序后的数列存入一个桶中。
-
重复以上步骤,直到排完最高位数后,得到一个有序的数列。
基数排序算法的时间复杂度为O(d*(n+k)),其中d为位数,n为元素数量,k为桶的数量。因为桶的数量k通常是固定的,所以基数排序的时间复杂度为O(d*n)。
基数排序算法的空间复杂度较高,需要额外的桶来存储数据。同时,基数排序算法只适用于非负整数的排序,对于其他类型的数据需要进行转换才能使用。
一、C 实现 基数排序算法 及代码详解
基数排序(radix sort)是一种非比较型的排序算法,根据关键词对待排序数据进行多次排序,以达到排序的目的。
下面是 C 语言实现基数排序的代码。以下代码将数组中的元素看做是整数,不包括小数。
#include <stdio.h>
void radix_sort(int arr[], int n) {
int i, j, k;
int cnt[10]; // 计数器,用于计算每个桶中的元素个数
int bucket[10][n]; // 用于存放每个桶中的元素
int max_num = arr[0]; // 计算出数组中最大的数
int digit = 1; // 数位
// 计算数组中最大的数
for (i = 1; i < n; i++) {
if (arr[i] > max_num) {
max_num = arr[i];
}
}
// 从低位到高位,对每一位进行排序
while (max_num / digit > 0) {
// 将数据出现的次数存储在 cnt 数组中
for (i = 0; i < 10; i++) {
cnt[i] = 0;
}
for (i = 0; i < n; i++) {
k = (arr[i] / digit) % 10;
bucket[k][cnt[k]] = arr[i];
cnt[k]++;
}
// 重置计数器
for (i = 0; i < 10; i++) {
cnt[i] = 0;
}
// 将桶中的数据,依次放回原数组
for (i = 0; i < 10; i++) {
for (j = 0; j < cnt[i]; j++) {
arr[cnt[i] * i + j] = bucket[i][j];
}
}
// 位数增加
digit *= 10;
}
}
int main() {
int arr[] = {32, 56, 12, 91, 18, 74, 8, 47, 3, 65};
int n = sizeof(arr) / sizeof(arr[0]);
int i;
printf("Original array: ");
for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
radix_sort(arr, n);
printf("\nSorted array: ");
for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
return 0;
}
在上述代码中,首先计算数组中最大的数,然后循环进行排序,从低位到高位。对于每一位,首先统计每个桶中的元素个数,然后将每个元素放到对应的桶中,最后从每个桶中取出元素,依次放回原数组中。需要注意的是,位数增加时需要将 digit 乘以 10。
基数排序的时间复杂度为 O(kn),其中 k 表示数字的位数,n 表示数组的大小。当 k 不大于 log10n 时,基数排序的效率较高。
值得注意的是,基数排序使用的是计数排序的思想,因此也可以使用计数排序的方式来实现。这种方式比较简单,不需要使用桶这个数据结构。
二、C++ 实现 基数排序算法 及代码详解
基数排序(Radix Sort)是一种非比较排序算法,它将所有待比较数值统一为同样的数位长度,然后从低位开始,依次进行排序。基数排序的实现可以使用桶排序或计数排序。
以下是 C++ 实现基数排序算法的代码:
#include <iostream>
#include <vector>
using namespace std;
// 获取 num 的第 d 位数字(从低位开始)
int getDigit(int num, int d) {
for (int i = 1; i < d; i++) {
num /= 10;
}
return num % 10;
}
// 基数排序
void radixSort(vector<int>& nums) {
if (nums.empty()) {
return;
}
int n = nums.size();
int maxNum = *max_element(nums.begin(), nums.end()); // 获取最大数
int maxDigit = to_string(maxNum).length(); // 获取最大数的位数
vector<vector<int>> buckets(10); // 一维是桶的编号,二维是桶里的元素
for (int d = 1; d <= maxDigit; d++) {
// 将 nums 中的数放入对应的桶中
for (int i = 0; i < n; i++) {
int digit = getDigit(nums[i], d);
buckets[digit].push_back(nums[i]);
}
// 将桶中的数依次放入 nums 中
int idx = 0;
for (int i = 0; i < 10; i++) {
for (int j = 0; j < buckets[i].size(); j++) {
nums[idx++] = buckets[i][j];
}
buckets[i].clear(); // 清空桶
}
}
}
// 测试
int main() {
vector<int> nums = {45, 2, 78, 23, 56, 89, 12, 67};
radixSort(nums);
for (int num : nums) {
cout << num << " ";
}
cout << endl;
return 0;
}
代码中,getDigit
函数用于获取一个数的第 d 位数字,从低位开始。radixSort
函数是基数排序的核心代码,其中:
- 首先获取最大数和最大数的位数。
- 创建 10 个桶,一维是桶的编号,二维是桶里的元素。依次对每一位进行排序:
- 将 nums 中的数放入对应的桶中;
- 将桶中的数依次放入 nums 中。
- 返回排好序的 nums 数组。
最后,在 main
函数中测试基数排序的实现效果。
三、Java 实现 基数排序算法 及代码详解
基数排序算法是一种非比较排序算法,它将待排序的元素按照位数切割成不同的数字,然后按照每个数字分别进行排序。这个过程中,需要使用到桶排序来对每个位上的数字进行排序。基数排序算法的时间复杂度为O(d*(n+m)),其中d表示位数,n表示元素个数,m表示每个位上数字的取值范围。
以下是基数排序算法的Java实现和详细注释:
public class RadixSort {
public static void radixSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
// 找到数组中最大的数
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
// 用于存放每个位上的数字
int[] count = new int[10];
// 用于存放排序后的结果
int[] temp = new int[arr.length];
// 计算各个位上数字的出现次数
for (int i = 1; max / i > 0; i *= 10) {
Arrays.fill(count, 0);
for (int j = 0; j < arr.length; j++) {
int num = arr[j] / i % 10;
count[num]++;
}
// 计算各个数字在temp数组中的位置
for (int j = 1; j < count.length; j++) {
count[j] += count[j - 1];
}
// 将arr数组中的元素按照对应的位上的数字排好序放入temp数组中
for (int j = arr.length - 1; j >= 0; j--) {
int num = arr[j] / i % 10;
temp[--count[num]] = arr[j];
}
// 将排序后的结果复制回原数组
System.arraycopy(temp, 0, arr, 0, arr.length);
}
}
public static void main(String[] args) {
int[] arr = {3, 8, 1, 5, 9, 4, 6, 7, 2, 0};
radixSort(arr);
System.out.println(Arrays.toString(arr)); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}
}
上述代码中,首先用一个循环找到数组中最大的数max,然后再对每个位上的数字进行排序,排序的过程中用到了桶排序的思想,具体步骤如下:
- 定义一个长度为10的数组count,用于存放每个位上数字的出现次数;
- 定义一个长度和原数组大小相同的数组temp,用于存放排序后的结果;
- 对于每个数字的每个位,计算出该位上数字的出现次数,记录在count数组中;
- 计算各个数字在temp数组中的位置;
- 将arr数组中的元素按照对应的位上的数字排好序放入temp数组中;
- 将排序后的结果复制回原数组。
重复上面的步骤d次,其中d表示最大数的位数,每一次排序都会使数组更加有序。