计数排序——CountingSort

计数排序

计数排序是线性排序的一种。能够在线性时间内完成给定序列的排序,但计数排序应用的场景就更加具体了。

基本思想:对每一个输入的元素x,确定小于x的元素个数。这样就可以直接把x放到它在输出数组中的位置了。例如,有17个元素小于x,则x应在第18个输出位置上,但当有几个相同元素时,就要略加修改。

下面是算法导论中给出的伪代码:

COUNTING_SORT(A, B, k)
    let C[0...k] be a new array
    for i = 0 to k
        C[i] = 0
    for j = 1 to A.length
        C[A[j]] = C[A[j]] + 1
    for i = 1 to k
        C[i] = C[i] + C[i - 1]
    for j = A.length downto 1
        B[C[A[j]]] = A[j]
        C[A[j]] = C[A[j]] - 1

有了伪代码,就很容易转换成代码

void Counting_Sort(int A[], int size)
{
    int *B = NULL;
    B = (int *) malloc(sizeof(int) * size);

    for(int i = 0; i < size; i++)//临时数组的初始化
        B[i] = 0;
    for(int i = 0; i < size; i++)//记录元素的个数
        B[A[i]]++;
    for(int i = 0; i < size; i++)确定小于B[i]的元素个数
        B[i] += B[i - 1];

    int *C = NULL;    //C数组用来临时存放有序序列
    C = (int *)malloc(sizeof(int) * size);

    for(int i = 0; i < size; i++)
    {
        C[B[A[i]]] = A[i];
        B[A[i]]--;
    }
    for(int j = 0; j < size; j++)//将有序序列赋值给数组A
        A[i] = C[j];

    free(B);   /*最后释放B和C的空间*/
    free(C);
}

其实,还可以使代码更简洁,省去临时数组A,像下面这样:

void Counting_Sort(int A[], int size)
{
    int *B = NULL;
    B = (int *) malloc(sizeof(int) * size);

    for(int i = 0; i < size; i++)//临时数组的初始化
        B[i] = 0;
    for(int i = 0; i < size; i++)//记录元素的个数
        B[A[i]]++;

    int index = 0;
    for(int i = 0; i < size; i++)//B中的下表就是原数中的元素
    {                           //而B[i]的值代表元素的个数  
        while(B[i]-- > 0)
        {
            A[index++] = i;
        }
    }
    free(B); 
}

猜你喜欢

转载自blog.csdn.net/sinat_31508159/article/details/50631376