基数排序
算法描述
基数排序是一种非比较的排序算法,它将待排序的元素按照各个位上的数字进行排序。基数排序的主要思想是从最低位开始,依次对每个位上的数字进行排序,直到最高位排序完成,就得到了有序的结果。
具体步骤如下:
-
确定排序的轮数:首先确定待排序元素中最大值的位数,这决定了需要进行多少轮排序。例如,如果最大值是三位数,则需要进行三轮排序。
-
按照最低位进行排序:从最低位开始,对待排序的元素按照当前位上的数字进行排序。可以使用任何一种稳定的排序算法,如计数排序或桶排序等。排序后,元素按照当前位上的数字被分配到不同的桶中。
-
按照下一位继续排序:对上一轮排序后的桶中的元素,再次按照下一位上的数字进行排序。重复这个过程,直到所有的位都被排序完成。
-
合并桶中的元素:按照桶的顺序,依次将每个桶中的元素取出,得到最终的有序结果。
基数排序的关键在于按照每个位上的数字进行排序。通过多轮的排序过程,每个位上的数字都 会被考虑到,从而实现了整体的排序。需要注意的是,基数排序适用于待排序元素是非负整数的情况,对于负数和小数,需要进行适当的转换或处理。
基数排序的时间复杂度取决于待排序元素的位数和每个位上的排序算法的时间复杂度。当待排序元素的位数较小且每个位上的排序算法是线性时间复杂度时,基数排序可以达到较高的排序效率。但是,对于位数较大的情况,基数排序的时间复杂度可能较高。
基数排序的时间复杂度取决于待排序元素的位数和每个位上的排序算法的时间复杂度。假设待排序元素的位数为 ,每个位上的排序算法的时间复杂度为 ,其中 是待排序元素的数量。
在每一轮排序中,基数排序需要对所有的元素进行一次遍历,并将它们按照当前位上的数字分配到对应的桶中。这个过程的时间复杂度是 。由于需要进行 轮排序,因此基数排序的总时间复杂度为 。
空间复杂度方面,基数排序需要使用额外的存储空间来存储桶和排序结果。通常情况下,桶的数量与待排序元素的范围有关,即 ,其中 是待排序元素的范围。因此,基数排序的空间复杂度为 。
编程实现
#include <stdio.h>
// 获取数组中的最大值
int getMax(int arr[], int n) {
int max = arr[0];
for (int i = 1; i < n; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
// 使用计数排序对数组按照指定位数进行排序
void countingSort(int arr[], int n, int exp) {
int output[n];
int count[10] = {0};
// 统计当前位上的数字出现的次数
for (int i = 0; i < n; i++) {
count[(arr[i] / exp) % 10]++;
}
// 计算累计次数
for (int i = 1; i < 10; i++) {
count[i] += count[i - 1];
}
// 根据当前位上的数字,将元素放入输出数组中
for (int i = n - 1; i >= 0; i--) {
output[count[(arr[i] / exp) % 10] - 1] = arr[i];
count[(arr[i] / exp) % 10]--;
}
// 将输出数组的内容复制回原数组
for (int i = 0; i < n; i++) {
arr[i] = output[i];
}
}
// 基数排序函数
void radixSort(int arr[], int n) {
// 获取数组中的最大值,确定位数
int max = getMax(arr, n);
// 对每个位数进行排序
for (int exp = 1; max / exp > 0; exp *= 10) {
countingSort(arr, n, exp);
}
}
// 打印数组
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() {
int arr[] = {170, 45, 75, 90, 802, 24, 2, 66};
int n = sizeof(arr) / sizeof(arr[0]);
printf("原始数组:");
printArray(arr, n);
radixSort(arr, n);
printf("排序后的数组:");
printArray(arr, n);
return 0;
}