#include<stdio.h>
/*
基数排序更适合用于对时间、字符串等这些整体权值未知的数据进行排序
基数排序已经不再是一种常规的排序方式,它更多地像一种排序方法的应用,
基数排序必须依赖于另外的排序方法。基数排序的总体思路就是将待排序数据
拆分成多个关键字进行排序,也就是说,基数排序的实质是多关键字排序。
如果按照习惯思维,会先比较百位,百位大的数据大,百位相同的再比较十位,
十位大的数据大;最后再比较个位。人得习惯思维是最高位优先方式。
但一旦这样,当开始比较十位时,程序还需要判断它们的百位是否相同--
这就认为地增加了难度,计算机通常会选择最低位优先法。
基数排序方法对任一子关键字排序时必须借助于另一种排序方法,而且这种排序方法必须是稳定的。
对于多关键字拆分出来的子关键字,它们一定位于0-9这个可枚举的范围内,这个范围不大,
因此用桶式排序效率非常好。对于多关键字排序来说,
程序将待排数据拆分成多个子关键字后,对子关键字排序既可以使用桶式排序,
也可以使用任何一种稳定的排序方法。
短的关键字被认为是小的,排在前面,然后相同长度的关键字再按照词典顺序
或者数字大小等进行排序。比如1,2,3,4,5,6,7,8,9,10,11或者”b, c, d, e, f, g, h, i, j, ba”
直接按照字典的顺序进行排序,对于字符串、单词或者是长度固定的
整数排序比较合适。比如:1, 10, 2, 3, 4, 5, 6, 7, 8, 9和 “b, ba, c, d, e, f, g, h, i, j”
*/
const int MAX = 10;
void print(int *a){
int i;
for(i = 0; i < 7;i++){
printf("%d ",a[i]);
}
printf("%d\n",a[i]);
}
void RadixSort(int *a, int arraySize)
{
int i, bucket[MAX], maxVal = 0, digitPosition =1 ;
for(i = 0; i < arraySize; i++) { // 求出最大值
if(a[i] > maxVal) maxVal = a[i];
}
int pass = 1; // 显示趟数
/* maxVal: 通过这个数来决定趟数 三位数则走三趟 */
while(maxVal/digitPosition > 0) {
// 初始化或者重置计数数组
int digitCount[10] = {0};
/* 开始按位计数
digitCount[]存储的是某位的个数
a[i]/digitPosition%10 对应求出的位对应digitCount数组的下标
*/
for(i = 0; i < arraySize; i++)
digitCount[a[i]/digitPosition%10]++;
/* 累加 为了排序 后面每次排一个元素就 -- 一次 */
for(i = 1; i < 10; i++)
digitCount[i] += digitCount[i-1];
/*
排序 这里是最不太好理解的 比如第一次
a[i] == 66
digitCount[a[i]/digitPosition%10] = adigitCount[6] = 8
-- -> digitCount[6] = 7 -->
bucket[7] = a[7] == 66 刚好对应
第二次 a[i] = 802; -> digitCount[2] = 4 -- ->bucket[3] = 4
= a[6] == 802没有对应 交给下一轮
。。。依次类推 主要要理解频次分布 通过这个来实现这个算法
首先统计10个篮子(或口袋)中各有多少个数字,
然后从0~9数字的频次分布(而不是频次密度,有一个累加的过程),
以确定“收集”整数时的位置下标所在。同时为了保证排序算法稳定,
相同的数字保持原来相对位置不变,对原始数据表倒序遍历,逐个构成收集后的数据表。
例如,上图所示,对于数字66,其所对应的频次分布为8,也就是应当排在第8位,在数组中下标应该为7。
而如果对于数字2和802,对应的频次分布为4,那么对于数据表从后往前遍历的话,
对应802的下标为3,而2的下标2,这样实际上就保证了排序算法的稳定性。
*/
for(i = arraySize - 1; i >= 0; i--)
bucket[--digitCount[a[i]/digitPosition%10]] = a[i];
/* 桶内数据重新赋给原数组 */
for(i = 0; i < arraySize; i++)
a[i] = bucket[i];
/* 到此 已经排序第一轮完成 输出 */
printf("pass # %d: ",pass++);
print(a);
/* 1 10 100 */
digitPosition *= 10;
}
}
int main(){
int a[8] = {170, 45, 75, 90, 2, 24, 802, 66};
const size_t sz = sizeof(a)/sizeof(a[0]);
//cout << "pass #0: ";
//print(a);
printf("原序列:");
print(a);
RadixSort(&a[0],sz);
printf("排序后元素如下:");
print(a);
return 0;
}
基数排序
最新推荐文章于 2022-05-10 22:21:31 发布