计数排序:原理、步骤、复杂度及应用全解析

一、基本原理

  • 计数排序的基本思想是对于给定的输入序列中的每一个元素x,确定小于x的元素个数。通过统计每个元素出现的次数,然后根据统计结果将元素放到有序序列中的正确位置。

  • 假设输入的数组是A,长度为n,数组中的元素范围是0到k。它需要额外创建两个辅助数组:计数数组C(长度为k + 1)用于统计每个元素出现的次数,和输出数组B(长度为n)用于存放排序后的结果。

二、算法步骤

  1. 统计元素出现次数
    • 遍历输入数组A,对于数组A中的每个元素A[i],将计数数组C[A[i]]的值加1。例如,若A = [2, 5, 3, 0, 2],当遍历到第一个元素2时,C[2]的值就加1。这个步骤可以用以下代码实现:
    C = [0] * (k + 1)
    for i in range(len(A)):
        C[A[i]] += 1
    
  2. 计算元素的累积计数
    • 计算计数数组C的累积和。累积和的意义是确定每个元素在排序后的输出数组B中的位置范围。具体来说,C[i]现在表示小于或等于i的元素的个数。代码如下:
    for i in range(1, len(C)):
        C[i] += C[i - 1]
    
  3. 构建输出数组B
    • 从输入数组A的末尾开始遍历(这样可以保证排序的稳定性),对于每个元素A[i],将其放到输出数组B中。B中的位置由C[A[i]] - 1确定(因为数组索引从0开始),然后将C[A[i]]的值减1。这个步骤可以用以下代码实现:
    B = [0] * len(A)
    for i in range(len(A) - 1, -1, -1):
        B[C[A[i]] - 1] = A[i]
        C[A[i]] -= 1
    
  4. 返回排序后的数组
    • 最后,输出数组B就是排序后的结果。

三、时间复杂度和空间复杂度

  • 时间复杂度
    • 计数排序的时间复杂度为\(O(n + k)\),其中n是输入数组的长度,k是输入数组中元素的范围。在最好、最坏和平均情况下,时间复杂度都是\(O(n + k)\)。因为它主要包含三个步骤,统计元素出现次数、计算累积计数和构建输出数组,每个步骤的时间复杂度都与n或k有关。
  • 空间复杂度
    • 空间复杂度为\(O(n + k)\)。因为需要创建计数数组C(长度为k + 1)和输出数组B(长度为n)来存储数据。不过,如果输入数组中的元素范围k较小,相对于基于比较的排序算法(如快速排序的平均空间复杂度\(O(log n)\)),计数排序在空间上可能会有优势。

四、稳定性和适用场景

  • 稳定性
    • 计数排序是一种稳定的排序算法。稳定排序是指在排序过程中,相等元素的相对顺序不会改变。在计数排序的第三步构建输出数组B时,从输入数组A的末尾开始遍历,保证了相等元素的相对顺序不变。
  • 适用场景
    • 计数排序适用于输入数据范围比较小的整数排序。例如,对学生成绩(分数范围通常是0 - 100)进行排序,或者对年龄(范围可能是0 - 120左右)等有限范围的数据进行排序。如果数据范围k很大(比如和n同数量级或者更大),那么计数排序可能会因为需要创建很大的计数数组C而占用过多的空间,效率可能不如其他排序算法。
posted @ 2024-12-25 16:06  软件职业规划  阅读(22)  评论(0编辑  收藏  举报