基数排序-C语言实现

基数排序(radix sorting)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)的稳定性排序法。基数排序的方式可以采用最低有效位LSD(Least significant digital)或最高有效位MSD(Most significant digital)。LSD的排序方式将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。 然后 从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。而MSD则相反,由最高位开始,先按最高位排序分组,同一组中记录,最高位相等,再对各组按次高位排序分成子组,之后,对后面的位继续这样的排序分组,直到各子组排序完成。再将各组连接起来,便得到一个有序序列。下面以一组数为例:{90,100,204,20,32,19,56,48,3,91,94,90},采用LSD方式:

0  90 100 20 90                                                                 0   100 3(3在排序前要填充为003)204

1  91                                                                                  1    

2  32                                                                                   2  20                      

3  3   按最低位排序结果{90 100 20 90 91 32 3 204 94 56 48}   3   32   得到第二次排序结果{100 3 204 20 32 48 56 90 90 91 94}

4  204 94            -------------》                                          4   48    -------------------》

5                                                                                          5   56

6  56                                                                                    6    

7                                                                                          7   

8  48                                                                                    8   

9                                                                                          9    90 90 91 94

----------------------------------------------------------------------------------------------------------------------------------------------------------

       0   3  20  32 48 56 90 90 91 94  {用0填充了最高位)

1   100

2   204

3                              第三次排序结束(最高有3位数)

4                     --------------------------------->   {3 20 32 48 56 90 90 91 94 100 204} 有序序列

5

6

7

8

9

LSD的基数排序适用于位数小的数列,如果位数多的话,使用MSD的效率会比较好。MSD的方式与LSD相反,是由高位数为基底开始进行分配,但在分配之后并不马上合并回一个数组中,而是在每个“桶子”中建立“子桶”,将每个桶子中的数值按照下一数位的值分配到“子桶”中。在进行完最低位数的分配后再合并回单一的数组中,下一篇博客会介绍。

C语言实现:(代码来自互联网)

#include
#include
int maxbit(int data[], int n) //辅助函数,求数据的最大位数
{
    int d = 1; //保存最大的位数
    int p = 10;
    for(int i = 0; i < n; ++i) {
        while(data[i] >= p) {
            p *= 10;
            ++d;
        }
    }
    return d;
}
void radixsort(int data[], int n)   //基数排序
{
    int d = maxbit(data, n);   //数组中的元素的最大位数
    int *tmp = (int *)malloc(n * sizeof(int));
    int *count = (int *)malloc(10 * sizeof(int));   //计数器
    int i, j, k;
    int radix = 1;
    for(i = 1; i <= d; i++) {   //进行d次排序
        for(j = 0; j < 10; j++)
            count[j] = 0;    //每次分配前清空计数器
        for(j = 0; j < n; j++) {
            k = (data[j] / radix) % 10;   //计算每次循环某一位的数字
            count[k]++;    //统计每个桶中的记录数
        }
        for(j = 1; j < 10; j++)
            count[j] = count[j - 1] + count[j];   //第j个桶以及之前所有桶中元素的总数
        for(j = n - 1; j >= 0; j--) {    //将所有桶中记录依次收集到tmp中
            k = (data[j] / radix) % 10;
            tmp[count[k] - 1] = data[j];
            count[k]--;
        }
        for(j = 0; j < n; j++)   //将临时数组的内容复制到data中
            data[j] = tmp[j];
        radix = radix * 10;
    }
    free(tmp);
    free(count);
}
int main()
{
    int a[] = {90,100,204,20,32,19,56,48,3,91,94,90};
    int n;
    n = sizeof(a) / sizeof(a[0]);
    radixsort(a, n);
    for(int k = 0; k < n; k++)
        printf("%d ", a[k]);
    printf("\n");
    return 0;
}
时间效率:设待排序列为n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排序的时间复杂度为O(d(n+radix)),其中,一趟分配时间复杂度为O(n),一趟收集时间复杂度为O(radix),共进行d趟分配和收集。 空间效率:需要2*radix个指向队列的辅助空间,以及用于静态链表的n个指针。

你可能感兴趣的:(算法,C语言)