W. :基数排序.8.3,P100

//author: W.
//基数排序.8.3,P100

//时间复杂度:O(n),但系数很大
//基数排序的条件:给定n个d位数,每一个数位可以取k种可能的值。这种排序也可以适合于有d的key组合来标识一个数据,比如用年月日来标识一条日程记录,或者数据库中用多个关键字标识一条记录.
//基数排序是对d位数,从后往前进行排序,并且使用的中间对每一位进行的排序算法必须是稳定排序算法。

//该例中定义以下数据结构作为输入数据的条件。该例子模拟对日期的排序,这里没有检测日期的合法性.

#define MAX_DAY 31         
#define MAX_MONTH 12
#define MAX_YEAR 99

typedef int DATE[3];  //其中[0]: DAY, [1]: MONTH, [2]: YEAR

#include <stdio.h>
#include <stdlib.h>

//参数:(in,out)A:待排序的数组,输出按index索引位置的已排序数组,即A[0][index]~A[length-1][index]进行排序
//(in)length:数组A元素个数
//(in)index:对数组A中元素的index索引对应的值进行排序
//(in)k:n个输入的元素中每一个都是介于0~k之间的整数,此处k为某个整数.即0 <= A[0][index]~A[i][index] <= k.
void COUNTING_SORT(DATE A[], const int length, const int index, const int k)
{
    int* B = (int*)malloc(length * sizeof(int));
    int *C = (int*)malloc((k + 1) * sizeof(int));
    int i;
    for(i = 0; i <= k; ++i)
    {
        C[i] = 0;
    }
    for(i = 0; i < length; ++i)
    {
        ++C[A[i][index]];
    }
    for(i = 1; i <= k; ++i)
    {
        C[i] = C[i] + C[i-1];
    }
    for(i = length – 1; i >= 0; –i)
    {
        B[C[A[i][index]]-1] = A[i][index];
        –C[A[i][index]];
    }
    for(i = 0; i < length; ++i) //由于基数排序需要每轮排序的结果都作用到原始数组A中,所以这里把得到的已排序值拷贝到原始数组A对应的位置上,由于计数排序的时间复杂度为O(n)所以该循环不影响总的时间复杂度
    {
        A[i][index] = B[i];
    }
    free(C);
    free(B);
}

void RADIX_SORT(DATE A[], int length, int d, int max_value[])
{
    int i;
    for(i = 0; i < d; ++i) //从低位到高位排序
    {
        COUNTING_SORT(A, length, i, max_value[i]); //基数排序需要的中间排序算法必须是稳定排序,注意COUNTING_SORT中每个元素的值认为是0~max_value[i]的,但这里实际的值是1~max_value[i],但对于计数排序来说,该子范围不影响排序的结果.
    }
}

void test_RadixSort()
{
    DATE a[] = { {22, 12, 3}, {22, 11, 30}, {22, 11, 2}, {11, 1, 2}, {10, 12, 31}, {1, 1, 1}, {22, 11, 30}, {22, 11, 2}};
    int MAX_VALUE[3] = { MAX_DAY, MAX_MONTH, MAX_YEAR};
    int i;
    int j;
    for(i = 0; i < sizeof(a)/sizeof(DATE); ++i)
    {
        for(j = 0; j < 3; ++j)
        {
            printf(“%d”, a[i][j]);
            if(j != 2)
            {
                printf(“-“);
            }
        }
        printf(“/n”);
    }
    printf(“/n”);
    RADIX_SORT(a, sizeof(a)/sizeof(DATE), 3, MAX_VALUE);
    for(i = 0; i < sizeof(a)/sizeof(DATE); ++i)
    {
        for(j = 0; j < 3; ++j)
        {
            printf(“%d”, a[i][j]);
            if(j != 2)
            {
                printf(“-“);
            }
        }
        printf(“/n”);
    }
    printf(“/n”);
}

int main(int argc, char** argv)
{
    test_RadixSort();
    return 0;
}

//输出:
//22-12-3
//22-11-30
//22-11-2
//11-1-2
//10-12-31
//1-1-1
//22-11-30
//22-11-2
//
//1-1-1
//10-1-2
//11-11-2
//22-11-2
//22-11-3
//22-11-30
//22-12-30
//22-12-31

点赞