基数排序
原理:
基数排序(Radix Sort)是桶排序的扩展,它的基本思想是:将整数按位数切割成不同的数字,然后按每个位数分别比较。
具体做法是:将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。
思路:
- 遍历序列找出最大的数(为的是确定最大的数是几位数);
- 开辟一个与数组大小相同的临时数组tmp;
- 用一个count数组统计原数组中某一位(从低位向高位统计)相同的数据出现的次数;
- 通过count[i] += count[i - 1];记录tmp[i]数组每个数的位置
- 将临时数组tmp的值储存回array数组中
- 重复(3)(4)(5)直到所有位都被统计并计算过。
图解基数排序
算法解析:
- 假设在基数排序中,r为基数(桶的范围),d为位数,n为个数。则基数排序的时间复杂度为O(d(n+r))。对于任何位数上的基数进行“装桶”操作时,都需要n+rd个临时空间。是稳定排序算法。
- 基数排序是一种高效的排序算法,多用于处理字符串(不支持负数,实数排序效率不高)
- LSD——从低位向高位排
MSD——从高位向低位排
从排序效果上看,高位优先比較直观,但却涉及到递归的过程,故最经常使用的还是低位优先法。
C代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//得到最大数为几位数
int get_max_digit(int array[], int n)
{
int digit = 0, max = array[0];
int i;
for (i = 1; i < n; i++)
{
if (array[i] > max)
max = array[i];
}
while (max)
{
digit++;
max /= 10;
}
return digit;
}
//基数排序
void RadixSort(int array[], int n)
{
//创建临时数组
int *tmp = (int *)malloc(sizeof(int)*n);
//位数(决定了排序趟数)
int digit = get_max_digit(array, n);
//计数桶
int count[10];
//排序
int r, i, d;
for (r = 1; r <= digit; r++)
{
//重置计数桶
memset(count, 0, 10 * sizeof(int));
//把数据存储到临时数组
memcpy(tmp, array, n*sizeof(int));
d = i = 1;
while (i < r)
{
i++;
d *= 10;
}
//统计每个桶中的记录数
for (i = 0; i < n; i++)
count[(array[i] / d) % 10]++;
//将tmp中的位置依次分配给每个桶
for (i = 1; i < 10; i++)
count[i] += count[i - 1];
//将临时数组的内容复制到array中
for (i = n - 1; i >= 0; i--)
array[--count[(tmp[i] / d) % 10]] = tmp[i];
}
}
//打印数组
void print(int arr[], int n)
{
int i;
for (i = 0; i < n; i++){
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = { 53, 542, 3, 63, 14, 214, 154, 748, 616 };
int n = sizeof(arr) / sizeof(arr[0]);
printf("原序列为:");
print(arr, n);
printf("基数排序为:");
RadixSort(arr, n);
print(arr, n);
system("pause");
return 0;
}
代码生成图
如有不同见解,欢迎留言讨论!