计数排序算法

基本思想

先确定待排序数组的最大值(Max)和最小值(Min),随后创建Max - Min + 1个长度的数组称为计数数组,计数数组的索引对应着待排序数组中元素的值,数组的值表示该元素的出现次数。通过从前往后或者从后往前遍历数组,用数组下标+Min得到已排序好数组的值。并且累加每个位置的计数,得到每个元素的最终位置。最后依次将元素放回到结果数组中,得到排序后的数组。

示例

假设我们有以下数组需要排序:4, 2, 2, 8, 3, 3, 1

1、确定范围 :最大值是 8,最小值是 1。
2、创建计数数组 :根据最大值和最小值,创建计数数组 C,其长度为 最大值 - 最小值 + 1,即 C[0] 对应数字 1,C[7] 对应数字 8。

bash 复制代码
C[0] = 0  (表示数字 1 出现次数)
C[1] = 0  (表示数字 2 出现次数)
C[2] = 0  (表示数字 3 出现次数)
C[3] = 0  (表示数字 4 出现次数)
C[4] = 0  (表示数字 5 出现次数)
C[5] = 0  (表示数字 6 出现次数)
C[6] = 0  (表示数字 7 出现次数)
C[7] = 0  (表示数字 8 出现次数)

3、统计每个数字的出现次数

bash 复制代码
C[0] = 1 (数字 1 出现 1 次)
C[1] = 2 (数字 2 出现 2 次)
C[2] = 2 (数字 3 出现 2 次)
C[3] = 1 (数字 4 出现 1 次)
​​​​​​​C[7] = 1 (数字 8 出现 1 次)

4、累加计数数组 :为了确定每个元素的位置,累加每个元素的计数值。

5、将元素放入结果数组 :根据累加后的计数数组,将原数组的元素放到排序后的结果数组中。

排序后的结果:1, 2, 2, 3, 3, 4, 8

复杂度

时间复杂度 :O(n + k),其中 n 是待排序数组的元素个数,k 是待排序数组中的最大值和最小值之间的范围(即最大值Max与最小值Min之差)。

如果数组中的元素范围(k)不大,那么计数排序的时间复杂度可以接近 O(n),适合用于范围较小的整数排序。

如果元素范围 k 很大,计数排序的空间和时间复杂度就会受到影响。

空间复杂度:O(n + k),需要额外的空间来存储计数数组和排序后的数组。

稳定性:计数排序是稳定的。

代码实现

java 复制代码
public static void countingSort(int[] arr) {
        // 1. 找到最大值和最小值
        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        for (int num : arr) {
            if (num > max) max = num;
            if (num < min) min = num;
        }

        // 2. 创建计数数组
        int range = max - min + 1;
        int[] count = new int[range];

        // 3. 统计每个元素的出现次数
        for (int num : arr) {
            count[num - min]++;
        }

        // 4. 累加计数数组
        for (int i = 1; i < count.length; i++) {
            count[i] += count[i - 1];
        }

        // 5. 构造排序后的数组
        int[] sortedArr2 = new int[arr.length];
        for (int i = arr.length - 1; i >= 0; i--) {
            sortedArr2[count[arr[i] - min] - 1] = arr[i];
            count[arr[i] - min]--;
        }

        // 6. 将排序后的数组复制回原数组
        System.arraycopy(sortedArr, 0, arr, 0, arr.length);
    }
java 复制代码
   这段代码是简化版的累加计数过程,可以代替上段代码的4-5步,适用于重复元素出现过多的情况
        int[] sortedArr = new int[arr.length];
        int j = 0;
        for (int i = 0; i <= arr.length - 1; i++) {
            while(count[j] == 0){
                j++;
            }
            sortedArr[i] = j + min;
            count[j]--;
        }
相关推荐
ZhouDevin39 分钟前
算法论文/数据集3——CLD(TMLR2025)压缩训练集,仅保留对验证集有益的样本
人工智能·深度学习·算法·计算机视觉
Tim_101 小时前
【LeetCode】29、两数相除
算法·leetcode·职场和发展
纪念 2291 小时前
数据结构排序(三)
数据结构
船厂电气自动化ai大模型2 小时前
AI大模型与数学/第63课:矩阵定义、矩阵加法、标量乘法(逐级精讲)
数据结构·人工智能·深度学习·线性代数·算法
余额瞒着我当琳2 小时前
算法修炼 chapter 2 双指针进阶、盛最多水的容器、有效三角形的个数、两数之和、三数之和、四数之和
算法
你压到我腿毛了6662 小时前
C语言冒泡算法(Bubble sort)
c语言·数据结构·算法
靠沿3 小时前
贪心算法专题(三)
算法·贪心算法
super大力张3 小时前
MOE基于结构的药物设计(七):Ligand R-Vectors——如何判断配体可以从哪里继续生长?
数据库·算法·cadd·moe·svl·基于结构的药物设计
Tongsr4 小时前
别只混淆代码:用 Kaleido 加固整个 Android Release AAB
前端·算法·github
高亦真4 小时前
今天是学习嵌入式的第34天
linux·学习·算法