计数排序算法

计数排序(Counting Sort)是一种非比较型整数排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。

计数排序的使用条件和范围

使用条件

  • 输入的数据必须是整数。
  • 输入数据的范围已知(即存在最大值和最小值)。

使用范围

  • 适用于一定范围内的整数排序。

  • 当输入的数据范围k不是很大时,计数排序非常高效。

  • 如果k远大于n(n是数据个数),则计数排序不是最佳选择,因为会浪费很多空间。

    java 复制代码
        /*
        * 计数排序
        * */
        public static int[] sortNumber(int[] array){
            int max = Integer.MIN_VALUE;
            for (int num : array){
                max = Math.max(max, num);
            }
            int[] store = new int[max + 1];
    
            for (int i = 0; i < array.length; i++) {
                store[array[i]]++;
            }
    
            //写法1
            int index = 0;
            for (int i = 0; i < store.length; i++) {
                for (int j = 0; j < store[i]; j++) {
                    array[index] = i;
                    index++;
                }
            }
    
            //写法2
            int sortedIndex = 0;
            for (int j = 0; j < bucketLen; j++) {
                while (store[j] > 0) {
                    arr[sortedIndex++] = j;
                    store[j]--;
                }
            }
    
            return array;
        }
    }

计数排序的Java示例

以下是一个Java示例,展示了如何使用计数排序对一个整数数组进行排序。假设我们要排序的整数都在0到100之间(即k=101):

java 复制代码
public class CountingSort {  
  
    public static void countingSort(int[] arr) {  
        if (arr == null || arr.length == 0) return;  
  
        // 找出数组中的最大值和最小值  
        int max = arr[0], min = arr[0];  
        for (int i = 1; i < arr.length; i++) {  
            if (arr[i] > max) max = arr[i];  
            if (arr[i] < min) min = arr[i];  
        }  
  
        // 计数数组的长度设为最大值+1  
        int range = max - min + 1;  
        int[] count = new int[range];  
  
        // 填充计数数组  
        for (int i = 0; i < arr.length; i++) {  
            count[arr[i] - min]++;  
        }  
  
        // 累加计数数组,使其变为前缀和  
        for (int i = 1; i < count.length; i++) {  
            count[i] += count[i - 1];  
        }  
  
        // 从后向前遍历原数组,根据计数数组填充结果数组  
        int[] sortedArr = new int[arr.length];  
        for (int i = arr.length - 1; i >= 0; i--) {  
            sortedArr[count[arr[i] - min] - 1] = arr[i];  
            count[arr[i] - min]--;  
        }  
  
        // 将结果数组复制到原数组  
        System.arraycopy(sortedArr, 0, arr, 0, arr.length);  
    }  
  
    public static void main(String[] args) {  
        int[] arr = {4, 2, 2, 8, 3, 3, 1};  
        countingSort(arr);  
        for (int num : arr) {  
            System.out.print(num + " ");  
        }  
    }  
}

注意:

  • 在这个例子中,我们首先找到了数组中的最大值和最小值,以确定计数数组的大小。
  • 计数数组count的索引对应于原数组中的元素值减去最小值min,这是因为我们假设所有元素都是非负整数,并希望从0开始计数。
  • 累加计数数组使其成为前缀和,这样我们可以知道每个元素在排序后数组中的位置。
  • 从后向前遍历原数组,并使用计数数组来确定每个元素在排序后数组中的位置。这样做是为了稳定排序(即相等元素的相对顺序不变)。
  • 最后,我们将排序后的数组复制回原数组。
相关推荐
玖玥拾11 分钟前
LeetCode 202 快乐数
算法·leetcode
LuminousCPP14 分钟前
数据结构-二叉树(六):BFS层序遍历与完全二叉树判断|复用链式队列 + (N_0=N_2+1) 性质证明
c语言·数据结构·笔记·算法·二叉树·宽度优先
ZhouDevin1 小时前
算法论文/数据集3——CLD(TMLR2025)压缩训练集,仅保留对验证集有益的样本
人工智能·深度学习·算法·计算机视觉
Tim_102 小时前
【LeetCode】29、两数相除
算法·leetcode·职场和发展
纪念 2292 小时前
数据结构排序(三)
数据结构
船厂电气自动化ai大模型2 小时前
AI大模型与数学/第63课:矩阵定义、矩阵加法、标量乘法(逐级精讲)
数据结构·人工智能·深度学习·线性代数·算法
余额瞒着我当琳3 小时前
算法修炼 chapter 2 双指针进阶、盛最多水的容器、有效三角形的个数、两数之和、三数之和、四数之和
算法
你压到我腿毛了6663 小时前
C语言冒泡算法(Bubble sort)
c语言·数据结构·算法
靠沿3 小时前
贪心算法专题(三)
算法·贪心算法
super大力张4 小时前
MOE基于结构的药物设计(七):Ligand R-Vectors——如何判断配体可以从哪里继续生长?
数据库·算法·cadd·moe·svl·基于结构的药物设计