前言:
基数排序从本质上说就是多关键字排序,根据多关键字进行多次排序以得到总体有序的序列。一大串数字可以看成一个个数字的结合,可以看做一堆关键字,因此对大数字进行排序,基数排序的效率很高,但是问题是会用掉比较多的空间。
思路:
基数排序分为MSD和LSD。LSD,最低位优先,是基数排序。
MSD,最高位优先,是分治法实现的排序,就不是基数排序了。
LSD就是一位一位的排序,先对个位进行排序。再将排序后的数组对十位进行排序······一直实现到最高位,就可以将整体有序。由于要实现到最高位,所以这边我们需要先找到数组中最大的元素,以确定外层循环的次数。(最大数字的位数)
int i, max = a[0], base = 1;
//找到数组最大值,以确定循环次数
for (i = 1; i < length; i++)
if (a[i] > max)max = a[i];
while (max / base > 0)
{
}
然后其实就是计数排序,不过不用开辟太大的空间了,只需要开辟10个空间对0-9进行排序就可以了。这里有一个位数不相同的问题,但是如果不同的话,整除位数以后是0,排序完是在前面的,并不影响整体的排序,所以没必要进行处理。
如果计数排序不懂得话,理解起来下面的代码可能会有些难度。建议先去看看计数排序的原理
只需要理解到相对应的数据在计数数组中的下标是:bucket[a[i] / base % 10] - 1 就行。
还有一些细节我放在下头的代码中注释了。
排序核心代码:
void RadixSort(int* a, int length)
{
int i, max = a[0], base = 1;
//找到数组最大值,以确定循环次数
for (i = 1; i < length; i++)
if (a[i] > max)max = a[i];
int* t = (int*)malloc(sizeof(int) * length);
while (max / base > 0)
{
//默认对数字进行排序
int bucket[10] = { 0 };
//计数数组,累加计数数组得到逆序下标
for (i = 0; i < length; i++)
bucket[a[i] / base % 10]++;
for (i = 1; i < 10; i++)
bucket[i] += bucket[i - 1];
for (i = length - 1; i >= 0; i--)
{
//原始序列中最后一个数据,放在新序列下标为 bucket[a[i] / base % 10] - 1 的地方。
t[bucket[a[i] / base % 10] - 1] = a[i];
bucket[a[i] / base % 10]--;
}
//将辅助数组的值复制回原数组,继续下一轮
for (i = 0; i < length; i++)
a[i] = t[i];
//个位->十位->百位->···
base *= 10;
}
}
测试代码:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define N 30
//之前写过了,就不再全写一遍了
void generate_random_number(int*, int, int);
void swap(int*, int*);
void RadixSort(int* a, int length)
{
int i, max = a[0], base = 1;
//找到数组最大值,以确定循环次数
for (i = 1; i < length; i++)
if (a[i] > max)max = a[i];
int* t = (int*)malloc(sizeof(int) * length);
while (max / base > 0)
{
//默认对数字进行排序
int bucket[10] = { 0 };
//计数数组,累加计数数组得到逆序下标
for (i = 0; i < length; i++)
bucket[a[i] / base % 10]++;
for (i = 1; i < 10; i++)
bucket[i] += bucket[i - 1];
for (i = length - 1; i >= 0; i--)
{
//原始序列中最后一个数据,放在新序列下标为 bucket[a[i] / base % 10] - 1 的地方。
t[bucket[a[i] / base % 10] - 1] = a[i];
bucket[a[i] / base % 10]--;
}
//将辅助数组的值复制回原数组,继续下一轮
for (i = 0; i < length; i++)
a[i] = t[i];
//个位->十位->百位->···
base *= 10;
}
}
int main()
{
int arr[N + 10] = { 0 };
generate_random_number(arr, 0, 1024);
RadixSort(arr,N);
printf("排序后数列:\n");
for (int i = 0; i < N; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}
测试结果:
至此,基数排序完成。