基础算法【7】:计数排序CountingSort

  1. 计数排序:

    1. 假设:如果要排序的项目是小范围的整数,我们可以计算每个整数(在这个小范围内)的出现频率(O(N)),然后通过循环该小范围来按排序顺序输出项目。

    2. 在示例数组{2, 3, 8, 7, 1, 2, 2, 2, 7, 3, 9, 8, 2, 1, 4, 2, 4, 6, 9, 2}中,对所有整数都在[1..9]内的示例数组尝试Counting Sort,因此我们只需要计算整数1出现的次数,出现整数2,...,出现整数9,然后遍历 如果频率 [y] = x,则 1至9 打印出整数 y 的 x 个副本。

    3. 时间复杂度为O(N)来计算频率,O(N + k)以排序顺序输出结果,其中 k 是输入的整数范围,在本例中为9-1 + 1 = 9。 计数排序(Counting Sort)的时间复杂度为O(N + k),如果 k 很小,那么它就是O(N)。

    4. 由于内存限制,当 k 相对较大时,我们将无法执行计数排序(Counting Sort)的计数部分,因为我们需要存储那些 k 个整数出现的次数。

  2. 代码:

int CountingSort(int *data_arr, int data_num)
{
    int ret = 0;
    int data_index = 0, count_index = 0;
    /*
        1. data_arr = {2, 3, 8, 7, 1, 2, 2, 2, 7, 3, 9, 8, 2, 1, 4, 2, 4, 6, 9, 2}
        2. 计数数组的成员个数,为原始数组中最大的元素值。
    */
    int count_arr[10] = {0};
    int count_num = sizeof(count_arr) / sizeof(count_arr[0]);
    int *pai_arr = NULL;

    pai_arr = malloc(sizeof(int) * data_num);
    if (NULL == pai_arr) {
        return;
    }
    memset(pai_arr, 0, sizeof(int) * data_num);

    /* 
        1. 计数数组每个索引位置存储的是,与该索引值相等的原始数组中元素的个数。 
        2. 操作后,count_arr = {0, 2, 7, 2, 2, 0, 1, 2, 2, 2}
    */
    memset(count_arr, 0, sizeof(count_arr));
    for (data_index = 0; data_index < data_num; data_index++) {
        count_arr[ data_arr[data_index] ] += 1;
    }

    /* 
        1. 计数数组每个索引位置存储的是,大于等于该索引值的原始数组中元素的个数。 
        2. 操作后,count_arr = {0, 2, 9, 11, 13, 13, 14, 16, 18, 20}
    */
    for (count_index = 1; count_index < count_num; count_index++) {
        count_arr[count_index] += count_arr[count_index - 1];
    }

    /* 逆序遍历原始数组,根据元素值(value),
       找到大于等于该元素值(value)的元素个数(pos),
       将元素值存储在新数组中的正确位置上。 */
    for (data_index = data_num - 1; data_index >= 0; data_index--) {
        int value = data_arr[data_index];
        int pos = count_arr[value];
        pai_arr[pos - 1] = value;
        count_arr[value] -= 1;
    }

    for (data_index = 0; data_index < data_num; data_index++) {
        data_arr[data_index] = pai_arr[data_index];
    }

    if (NULL != pai_arr) {
        free(pai_arr);
        pai_arr = NULL;
    }
    return ret;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值