码迷,mamicode.com
首页 > 编程语言 > 详细

基数排序

时间:2015-06-29 17:50:24      阅读:146      评论:0      收藏:0      [点我收藏+]

标签:基数排序   排序算法   算法   c语言   排序   

基数排序

①简介

    基数排序是一种用在卡片排序机上的算法,一张卡片有80列,在每一列上机器可以选择在12个位置中的任意一处穿孔。通过机器的操作,能够“编程”来检查每个卡片中的给定列,然后根据穿孔的位置将他们分别放在12个容器中。操作员就可以挨个容器来收集卡片,其中第一个位置穿孔的卡片在最上面,以此类推。

②原理

    直观上来看,可能会认为应该先按照最高有效位进行排序并分装到不同的容器中,再对每个容器进行递归的排序,但是对一个容器排序的同时,其他容器全部是空闲状态,必须放在一边还要存起来,会花费很大的空间。

    基数排序的思想恰好和人们的直观感受相反,是先按最低有效位进行排序来解决问题的。按最低有效位排序并分配好容器,再将容器中的卡片按照容器编号合成一叠,0号容器在1号容器上面,依次类推。合成一堆后再依据次最低有效位循环上面的流程。
技术分享

③C语言实现

#define NUM 10
int digit_assist[] = { 1, 10, 100, 1000, 10000 };

//清空辅助数组
void clear_array(int* a, int count)
{
    for (int i = 0; i < count; i++)
    {
        a[i] = 0;
    }
}

//得到第d位数上的数字
int get_digit(int num, int d)
{
    return (num / digit_assist[d - 1]) % 10;
}

//得到输入数组中最大的位数
int get_max_digit(int *a, int count)
{
    int max_digit = 1,max = a[0];
    for (int i = 1; i < count; i++)
    {
        if (a[i] > max)
            max = a[i];
    }
    while (0 != max / 10)
    {
        max = max / 10;
        max_digit++;
    }
    return max_digit;
}

//基数排序
void radix_sort(int* a, int count)
{
    int max_digit, *bucket, *bucket_index;
    bucket = (int*)malloc(count * sizeof(int));
    bucket_index = (int*)malloc(NUM * sizeof(int));

    max_digit = get_max_digit(a, count);
    for (int i = 0; i < max_digit; i++)
    {
        //清空辅助容器
        clear_array(bucket, count);
        clear_array(bucket_index, NUM);

        /* 利用了计数排序的小知识,避免过大的容器开销
         * 先统计每个桶里面有多少个数字
         */
        for (int j = 0; j < count; j++)
            bucket_index[get_digit(a[j], i + 1)]++;
        for (int j = 1; j < NUM; j++)
            bucket_index[j] += bucket_index[j - 1];

        /* 开始进行排序
         * 这里倒序开始,此处重点,原因在后面分析
         */
        for (int j = count - 1; j >= 0; j--)
        {
            int k = get_digit(a[j], i + 1);
            bucket[bucket_index[k] - 1] = a[j];
            bucket_index[k]--;
        }

        //再从容器中收集排列的数据
        for (int j = 0; j < count; j++)
        {
            a[j] = bucket[j];
        }
    }
}

void main()
{
    int count, *p;
    printf("请输入需要排序的数的个数 :");
    scanf_s("%d", &count);
    p = (int*)malloc(count * sizeof(int));
    printf("\n请输入需要排序的%d个数字:",count);
    for (int i = 0; i < count; i++)
    {
        scanf_s("%d", p+i);
    }
    printf("\n快速排序后的数组:");

    radix_sort(p,count);

    for (int i = 0; i < count; i++)
    {
        printf("%d ", p[i]);
    }
    printf("\n");
    system("pause");
}

    在这里说明一下,代码里面开始排序的时候为什么从后面提取数据而不是从前面。这里用一个例子来说明情况:假设我们需要排列的数组有三个数,分别是333,22,1。这三个数需要三次大的基数排序循环才能排好序,在循环的前两次,按照流程走下来都没什么大的问题,第二次大循环下来后,原始数组变成了1,22,333

    现在进行第三次的排序,轮到比较百位上的数字了,分别是百位上数字为0,0,3。统计出来的bucket_index数组中结果为2,2,2,3,3,3,3,3,3,3。统计完成后开始排序,如果这时候从前往后开始重新放置数字进入新的数组(类似计数排序那样bucket_index[k]–;),具有相同的百位数字中,十位数字较小的数字可能被放到十位数字较大的数字后面,会造成之前十位数字大循环拍好序列的紊乱。因此需要从后面向前面取数。

版权声明:本文为博主原创文章,未经博主允许不得转载。

基数排序

标签:基数排序   排序算法   算法   c语言   排序   

原文地址:http://blog.csdn.net/jing_unique_da/article/details/46681225

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!