基数排序
基数排序(Radix sort)是一种非比较型的排序算法,最早用于解决卡片排序的问题。
它的工作原理是将待排序的元素拆分为k个关键字,其中k为最大值的位数,从低位开始进行稳定排序。(注意:数列中的元素都是非负整数)
基数排序是一种稳定的排序算法。
代码实现:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef unsigned long long ULL;
//数据预处理,保证每个元素的值都大于等于0(如果已知数列全是非负数就不必进行此处理了)
int Pretreatment(int* nums, ULL* tmp, int numsSize){
int bias = 0;
for(int i = 0; i < numsSize; i++){
if(nums[i] < bias){
bias = nums[i];
}
}
for(int i = 0; i < numsSize; i++){
tmp[i] = nums[i] - bias;
}
return bias;
}
//基数排序
//LSD(最低位优先法)适用于位数较小的数列
void LSDRadixSort(int* nums, int numsSize){
ULL* tmp = (ULL*)calloc(numsSize, sizeof(ULL));
int bias = Pretreatment(nums, tmp, numsSize);
ULL buf[numsSize];
ULL exp = 1;
ULL maxval = 0;
//找到最大值作为循环停止的标准
for(int i = 0; i < numsSize; i++){
if(tmp[i] > maxval){
maxval = tmp[i];
}
}
//从低位到高位分配
while(maxval >= exp){
int cnt[10];
memset(cnt, 0, sizeof(cnt));
for(int i = 0; i < numsSize; i++){
int digit = (tmp[i] / exp) % 10;
cnt[digit]++;
}
for(int i = 1; i < 10; i++){
cnt[i] += cnt[i - 1];
}
for(int i = numsSize - 1; i >= 0; i--){
int digit = (tmp[i] / exp) % 10;
buf[--cnt[digit]] = tmp[i];
}
memcpy(tmp, buf, sizeof(ULL) * numsSize);
exp = exp * 10;
}
for(int i = 0; i < numsSize; i++){
nums[i] = tmp[i] + bias;
}
free(tmp);
}
int main(void) {
int numsSize;
scanf("%d", &numsSize);
int* nums = (int*)calloc(numsSize, sizeof(int));
for(int i = 0; i < numsSize; i++){
scanf("%d", &nums[i]);
}
LSDRadixSort(nums, numsSize);
for(int i = 0; i < numsSize; i++){
printf("%d", nums[i]);
if(i != numsSize - 1) printf(" ");
else printf("\n");
}
return 0;
}