1. 基数排序简介
基数排序是一种非比较排序算法,它可以应用于字符串、整数等数据类型的排序。基数排序的核心思想是以位数为基础,从低位到高位对数据进行排序,并利用桶排序的思想对每个位数进行排序。
1.1 基数排序的原理
基数排序的原理非常简单。假设要对一个整数数组进行排序,首先按照个位数的大小对所有数字进行排序,然后按照十位数的大小对所有数字进行排序,以此类推,直到最高位。
1.2 基数排序的步骤
基数排序的步骤如下:
根据待排序数据的最大位数d,确定排序循环的次数。
从个位开始,对待排序数据按照该位的大小进行排序。
将按照该位排序后的数据重新放入桶中。
依次按照十位、百位......进行排序。
重复步骤3、4直到最高位排序完成。
2. 基数排序的C程序实现
下面是基数排序的C程序实现:
#include <stdio.h>
#include <string.h>
/* 获取数组a中最大值 */
int getMax(int a[], int n) {
int max = a[0];
for (int i = 1; i < n; i++) {
if (a[i] > max) {
max = a[i];
}
}
return max;
}
/* 对数组a按照位数进行排序 */
void countingSort(int a[], int n, int exp) {
int output[n]; // 存储排序结果
int i, count[10] = {0};
// 统计每个元素的个数
for (i = 0; i < n; i++) {
count[(a[i] / exp) % 10]++;
}
// 计算每个元素在输出数组中的位置
for (i = 1; i < 10; i++) {
count[i] += count[i - 1];
}
// 将元素放入输出数组中
for (i = n - 1; i >= 0; i--) {
output[count[(a[i] / exp) % 10] - 1] = a[i];
count[(a[i] / exp) % 10]--;
}
// 将排序后的结果放回原数组
for (i = 0; i < n; i++) {
a[i] = output[i];
}
}
/* 基数排序 */
void radixSort(int a[], int n) {
int max = getMax(a, n);
/* 对每个位数进行排序 */
for (int exp = 1; max / exp > 0; exp *= 10) {
countingSort(a, n, exp);
}
}
int main() {
int a[] = { 170, 45, 75, 90, 802, 24, 2, 66 };
int n = sizeof(a) / sizeof(a[0]);
radixSort(a, n);
for (int i = 0; i < n; i++) {
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
上述程序中,函数getMax用于获取数组中的最大值。函数countingSort用于对数组按照某个位数进行排序,函数radixSort用于对每个位数进行排序。
另外需要注意的是,在countingSort函数中,我们使用了一个桶来存储每个元素的个数。由于待排序元素是0到9之间的数字,因此我们可以使用一个长度为10的数组存储每个数字出现的次数。在统计完每个数字的个数后,我们需要根据出现次数计算每个数字在输出数组中的位置。最后,将排序结果存储在输出数组中。
3. 总结
基数排序是一种非常简单、有效的排序算法。它的核心思想是以位数为基础,从低位到高位对数据进行排序,并利用桶排序的思想对每个位数进行排序。基数排序的时间复杂度为O(d*(n+k)),其中d为最高位数,k为进制数。虽然其时间复杂度比快速排序、归并排序等算法要高,但基数排序在处理大量数据时表现相当良好。
此外,在实际应用中,基数排序常常需要与其它排序算法结合起来使用。例如,如果待排序元素的范围比较大,我们可以首先将数据分成若干组,对每组采用快速排序等算法进行排序,然后再使用基数排序将子数组进行合并,这样可以有效降低时间复杂度。