zoukankan      html  css  js  c++  java
  • 《算法导论》第8章 线性时间排序 (1)计数排序


    一种简单的实现是得到数组C,C[i]表示数组A中值为i的元素个数。
    C = { 2, 0, 2, 3, 0, 1 }就表示两个0,两个2,三个3,一个5。
    然后将这些数字依次存到数组B中。

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

    void printArray(int[], int);

    void counting_sort(int A[], int B[], int len, int k)
    {
         int* C = calloc(k + 1, sizeof(int));

         int j;
         for (j = 0; j < len; j++)
              C[A[j]] += 1;

         // 保存C[i]个元素i到数组B[j]中。
         int i;
         for (i = 0, j = 0; i <= k; i++)
              while (C[i]-- > 0)
                   B[j++] = i;
    }

    int main(void)
    {
         int A[8] = { 2, 5, 3, 0, 2, 3, 0, 3 };
         int B[8];
         int k = 5;

         counting_sort(A, B, 8, k);
         printArray(B, 8);

         return 1;     
    }

    void printArray(int array[], int len)
    {
         int i;
         for (i = 0; i < len; i++)
              printf("%d,", array[i]);
         printf("\n");
    }

    这样简单的实现可以处理简单的整型数组的排序,但是对于有卫星数据的对象来说,
    直接遍历数组C输出结果的方法是行不通的。不能直接创建新的元素当做结果,
    而需要挪到输入数组A中的元素。

    《算法导论》中的实现如下:保证结果与输入数组中元素的关联,以及稳定性。

    // A = { 2, 5, 3, 0, 2, 3, 0, 3 }, len = 8, k = 5
    void counting_sort(int A[], int B[], int len, int k)
    {
         // 输入数范围是[0, k],数组C大小是k+1
         int* C = calloc(k + 1, sizeof(int));

         // C[i]表示数组A中值为i的元素个数
         // C = { 2, 0, 2, 3, 0, 1 }
         int j;
         for (j = 0; j < len; j++)
              C[A[j]] += 1;

         // C[i]表示数组A中小于等于值为i的元素个数
         // 即C[A[j]] - 1即为元素应在B中的下标
         // C = { 2, 2, 4, 7, 7, 8 }
         int i;
         for (i = 1; i <= k; i++)
              C[i] += C[i - 1];

         // 从len - 1到0遍历数组A,保证稳定性
         for (j = len - 1; j >= 0; j--) {
              B[C[A[j]] - 1] = A[j];
              C[A[j]] -= 1;
         }
    }

    习题8.2-4,先使用计数排序花费n+k时间得到数组C,
    然后区间[a, b]内的数字个数就是C[b] - C[a-1]。(a=0时,C[0] = 0)

    例如上面例子中A = { 2, 5, 3, 0, 2, 3, 0, 3 },
    C = { 2, 2, 4, 7, 7, 8 },[0, 5] = C[5] - 0 = 8
    [1, 3] = C[3] - C[1-1] = 7 - 2 = 5。


  • 相关阅读:
    第二十九课 循环链表的实现
    第二十八课 再论智能指针(下)
    第二十七课 再论智能指针(上)
    第二十六课 典型问题分析(Bugfix)
    普通new和placement new的重载
    leetcode 581. Shortest Unsorted Continuous Subarray
    leetcode 605. Can Place Flowers
    leetcode 219. Contains Duplicate II
    leetcode 283. Move Zeroes
    leetcode 217. Contains Duplicate
  • 原文地址:https://www.cnblogs.com/xiaomaohai/p/6157863.html
Copyright © 2011-2022 走看看