基数排序

#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;
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值