W. :计数排序.8-2,P98

来源:互联网 发布:sabayon linux 编辑:程序博客网 时间:2024/05/16 08:53

//author: W.
//计数排序.8-2,P98
//当k=O(n)时,时间复杂度为O(n),稳定排序

//输入:n个输入的元素中每一个都是介于0~k之间的整数,此处k为某个整数.即0 <= A[0]~A[i] <= k.
//该方法的总体思路是:用一个中间数组C来记录每个A[i]应该在已排序的数组中的位置,A[i]在已排序中的位置即计算出A[0]~A[n]中小于等于A[i]的个数。
//通过2次循环,第一次循环后C[A[i]]记录A[0]~A[n]中值为A[i]的元素的个数,第二次循环后C[i]记录A[0]~A[n]中值小于等于A[i]的个数
//最后再通过一次循环把A[i]插入到已排序的位置中即可.
//当k=O(n)时,每次循环的时间复杂度分别为O(n)和O(k),则总的时间复杂度为O(n),即可以在线程的时间内完成排序.
//该方法要注意C中下标及元素所表示的意义.

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

//参数:(in)A:待排序的数组
//(in)length:数组A元素个数
//(in)k:n个输入的元素中每一个都是介于0~k之间的整数,此处k为某个整数.即0 <= A[0]~A[i] <= k.
//(out)B:输出的已排序的数组
void COUNTING_SORT(const int A[], const int length, const int k, int B[])
{
    int *C = (int*)malloc((k + 1) * sizeof(int));
    int i;
    int C_index;
    int B_index;
    for(i = 0; i <= k; ++i) //对C中的元素进行初始化,C[i]值都初始化为0
    {
        C[i] = 0;
    }
    for(i = 0; i < length; ++i) //A[i]的取值范围为0~k,即C中的下标对应着A中的元素的值的情况,即每个A[i]对应一个C_index,C[C_index]就标识了有多少个A[i]对应到这个C_index中。
    {
        C_index = A[i];
        C[C_index] = C[C_index] + 1;
        //上式等价于:
        //++C[A[i]];
    }
    for(i = 1; i <= k; ++i) //此时C[i]表示A[0]~A[length-1]中小于等于i的元素的个数。
    {
        C[i] = C[i] + C[i-1];
    }
    for(i = length - 1; i >= 0; --i) //A[i]为A中的元素值,C[A[i]]表示A[0]~A[i]中小于等于A[i]的元素的个数,C[A[i]]-1(由于索引从0开始)则表示该A[i]在排序的数组中所处的位置,每次插入一个A[i]后,要使得C[A[i]]的值减1.
    {
        B_index = C[A[i]] - 1;
        B[B_index] = A[i];
        //上式等价于
        //B[C[A[i]]-1] = A[i];
        --C[A[i]];
    }
    free(C);
}

void test_CountingSort()
{
    int a[] = { 2, 5, 3, 0, 2, 3, 0, 3, 2, 3, 4, 5, 3, 4, 1, 0, 0, 0};
    int b[sizeof(a)/sizeof(int)];
    int i;
    for(i = 0; i < sizeof(a)/sizeof(int); ++i)
    {
        printf("%d ", a[i]);
    }
    printf("/n");
   
    COUNTING_SORT(a, sizeof(a)/sizeof(int), 5, b);
   
    for(i = 0; i < sizeof(b)/sizeof(int); ++i)
    {
        printf("%d ", b[i]);
    }
    printf("/n");
   
}

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

//输出:
//2 5 3 0 2 3 0 3 2 3 4 5 3 4 1 0 0 0
//0 0 0 0 0 1 2 2 2 3 3 3 3 3 4 4 5 5