5-2 其他排序:计数排序

计数排序

计数排序是一种非比较排序算法。当输入值的范围相对于待排序元素的数量较小时,它尤其高效。

  • 计数排序的基本思想是统计输入数组中每个不同元素出现的频率,并利用该信息将元素放置在正确的排序位置上。
  • 当输入元素的范围较小且与数组大小相当时,这种方法效果很好。例如,对于输入 [1, 4, 0, 2, 1, 1],数组大小为 6,元素范围为 0 到 4。
  • 如果输入数组的范围大于 n Log n,其中 n 是数组的大小,那么我们可以使用标准的基于比较的排序算法(如归并排序)对数组进行排序。

计数排序算法

  • 声明一个大小为max(arr[])+1的计数数组cntArr[],并将其初始化为0。
  • 遍历输入数组arr[] ,并将arr[]的每个元素映射为cntArr[]数组的索引,即,对0 <= i < N执行cntArr[arr[i]]++。
  • 计算cntArr[]中每个索引处的前缀和。
  • 创建一个大小为N的数组ans[]。
  • 从数组arr[] 的末尾开始遍历,并更新ans[cntArr[arr[i]] - 1] = arr[i]。此外,更新 cntArr [arr[i]] = cntArr[arr[i]]--。

为什么要计算前缀和?
我们可以简单地统计所有元素出现的次数,然后逐个将它们放入输出数组中,但为了保证算法的稳定性,我们计算了前缀和。需要注意的是,在构建前缀和 cntArr[] 之后,我们从数组的右端开始遍历,以确保最后一个出现的元素移动到排序数组中最后一个正确的位置。


代码实现

#include <iostream>
#include <vector>

std::vector<int> countsort(std::vector<int>& arr)
{
    int n = arr.size();

    // find the maximum element
    int maxval = 0;
    for (int i = 0; i < n; i++)
    {
        maxval = std::max(maxval, arr[i]);
    }

    // create and initialize cntArr array
    std::vector<int> cntArr(maxval + 1, 0);

    // count frequency of each element
    for (int i = 0; i < n; i++)
    {
        cntArr[arr[i]]++;
    }

    // compute prefix sum
    for (int i = 1; i <= maxval; i++)
    {
        cntArr[i] += cntArr[i - 1];
    }

    // build output array
    std::vector<int> ans(n);
    for (int i = n - 1; i >= 0; i--)
    {
        ans[cntArr[arr[i]] - 1] = arr[i];
        cntArr[arr[i]]--;
    }

    return ans;
}

int main()
{
    std::vector<int> arr = {2, 5, 3, 0, 2, 3, 0, 3};
    std::vector<int> ans = countsort(arr);

    for (int x : ans)
    {
        std::cout << x << " ";
    }

    return 0;
}

输出:

image


计数排序的复杂度分析、优缺点、以及应用:

计数排序的复杂度分析
时间复杂度:在所有情况下均为 O(N+M),其中N和M分别是inputArray[]和countArray[]的大小。
辅助空间: O(N+M),其中N和M分别是outputArray[]和countArray[]占用的空间。


计数排序的优势

  • 如果输入范围与输入数量处于同一数量级,则计数排序通常比所有基于比较的排序算法(如归并排序和快速排序)运行速度更快。
  • 稳定算法

计数排序的缺点

  • 不适用于小数。
  • 如果待排序的值范围非常大,则效率低下。
  • 它不是原地排序算法,它需要额外的空间来对数组元素进行排序。

计数排序的应用
对于数据范围有限的情况,这是一种常用的算法。例如,按成绩对学生进行排序,按时间、日期、月份、年份等对事件进行排序。
它被用作基数排序算法中的一个子程序。
桶排序利用计数排序的思想,将元素分成不同的桶。

posted @ 2026-03-30 18:18  游翔  阅读(0)  评论(0)    收藏  举报