计数排序-Counting Sort

计数排序是一种不需要进行元素比较的算法,它是通过数组中元素出现的次数来确定其如何排列的。

以待排数组arr[] = {3,1,3,4,3,5,4,2}为例,对其计数排序的思路是这样的:

  1. 它需要创建两个临时空间,我们以tmp和count来表示,其中tmp临时存放已排好的数据。

  2. count这个数组我们需要用两次,第一次存放待排数组arr各元素出现的次数,count[i]中存元素i出现的次数;第二次count[i]中存放小于等于i的元素的个数,其值可以用第一次存放的count[i] + count[i-1]得出。当然了,count里面的值最终是第二次的值。count的大小由待排数组的最大元素的值决定的。
    这里写图片描述

  3. 然后开始从后往前依次取出待排数组arr中的元素,按照其在count中对应的值在临时数组tmp中对号入座 ,入座后该元素在count中的值应该减1,这样能保证arr中相同元素下一次进入tmp中能放在其前一个位置。
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述
    后面依次存放 ,直到遍历完arr中的元素。

  4. 将tmp中的元素拷到arr中。

代码实现如下:

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

//参数分别为待排数组,待排数组的元素个数,和最大元素加1,失败返回0,成功返回1
int ctsort(int* arr,int sz,int k)
{
    int *tmp = NULL;
    int *count = NULL;
    int i;

    if(!(tmp=(int*)malloc(sz*sizeof(int)))) return 0;   
    if(!(count = (int*)malloc(k*sizeof(int)))) return 0;

    for(i=0; i<k; i++)//将count各元素初始化为0
        count[i] = 0;

    for(i=0; i<sz; i++)//统计出各元素出现的次数并将其存放在count中
        count[arr[i]] = count[arr[i]] + 1;

    for(i=1; i<k; i++)//将小于等于各元素的数的个数存放在count中
        count[i] = count[i]+count[i-1];

    for(i=sz-1; i>=0; i--)//从后往前遍历arr,把其中的元素对号入座
    {
        tmp[count[arr[i]] - 1] = arr[i];
        count[arr[i]] = count[arr[i]]-1;
    }

    memcpy(arr,tmp,sz*sizeof(int));//将tmp中的元素拷回arr

    free(tmp);
    free(count);

    return 1;
}

int main()
{
    int i;
    int arr[] = {3,1,3,4,3,5,4,2};
    int sz = sizeof(arr)/sizeof(arr[0]);

    for(i=0; i<sz; i++)
        printf("%d ",arr[i]);

    ctsort(arr,sz,6);

    printf("\n");
    for(i=0; i<sz; i++)
        printf("%d ",arr[i]);
    return 0;
}

结果如下:
这里写图片描述

计数排序的时间复杂度为O(n+k),n为待排数组元素的个数,k为待排数组最大元素值加1。对于空间来说,需要两个n大小的数组,一个k大小的数组。

为了保证计数排序的稳定性,上面是从后往前处理待排数组arr的。

所谓稳定性,就是指如果待排数组arr中,有两个数 a[i] 和 a[j]相等,并且i<j,z在排好序以后,a[i] 仍然在 a[j] 之前。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值