//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