• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
思想人生从关注生活开始
博客园    首页    新随笔    联系   管理    订阅  订阅

常用的排序算法之计数排序(Counting Sort)

计数排序(Counting Sort)

原理

计数排序(Counting Sort)的起源并不明确指向某一个特定的发明者或时间点,但它作为一种简单直观的排序算法,在计算机科学中得到了广泛的应用。计数排序的基本思想是通过统计数组中每个元素出现的次数,来确定其在排序后数组中的位置。

定义

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

引伸义

计数排序的主要思想是通过“计数”来排序,即统计每个元素出现的次数,然后根据这个次数来确定元素在排序后数组中的位置。这种方法避免了传统比较排序算法中的重复比较,从而实现了线性的时间复杂度。

优缺点

优点:

  1. 时间复杂度低,为O(n+k)(n为待排序数组长度,k为待排序数组中元素的取值范围)。
  2. 稳定性好,相等的元素在排序后保持原有的相对顺序。
  3. 空间复杂度为O(k),其中k为待排序数组中元素的取值范围。

缺点:

  1. 当k很大时,需要消耗大量空间。
  2. 只适用于整数排序,且要求待排序数组中的元素非负。

使用场景

计数排序适用于待排序数组元素取值范围较小且非负的场景,如考试成绩排序(假设分数范围为0-100)等。

使用数据一步步举例

假设有一个待排序数组arr = [4, 2, 2, 8, 3, 3, 1],其元素取值范围为1-9。

  1. 初始化一个长度为10(取值范围+1)的计数数组count,并将所有元素初始化为0。

    count = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  2. 遍历待排序数组arr,统计每个元素出现的次数,并将计数数组对应位置的值加1。

    arr: [4, 2, 2, 8, 3, 3, 1]  
    count 变为: [1, 1, 2, 2, 1, 0, 0, 0, 1, 0]
  3. 修改计数数组,使得每个位置的值变为小于等于该值的元素个数。

    count 变为: [0, 1, 2, 4, 5, 5, 5, 5, 6, 6]
  4. 从后往前遍历待排序数组arr,将每个元素放到排序后数组sortedArr的count[arr[i]]-1位置,并更新count[arr[i]]的值。

    sortedArr = []  
    for i from len(arr) - 1 to 0:  
        sortedArr.insert(count[arr[i]] - 1, arr[i])  
        count[arr[i]] -= 1

    排序后的数组sortedArr为[1, 2, 2, 3, 3, 4, 8]。

Java示例代码

public class CountingSort {  
  
    // 查找数组中的最大值  
    private static int findMaxValue(int[] arr) {  
        int maxValue = arr[0];  
        for (int i = 1; i < arr.length; i++) {  
            if (arr[i] > maxValue) {  
                maxValue = arr[i];  
            }  
        }  
        return maxValue;  
    }  
  
    // 计数排序方法  
    public static void countingSort(int[] arr) {  
        if (arr == null || arr.length == 0) return;  
  
        int maxValue = findMaxValue(arr);  
        int[] count = new int[maxValue + 1];  
  
        // 统计每个元素出现的次数  
        for (int i = 0; i < arr.length; i++) {  
            count[arr[i]]++;  
        }  
  
        // 修改count数组,使得每个位置的值变为小于等于该值的元素个数  
        for (int i = 1; i <= maxValue; i++) {  
            count[i] += count[i - 1];  
        }  
  
        // 从后往前遍历arr,将元素放到正确的位置  
        int[] sortedArr = new int[arr.length];  
        for (int i = arr.length - 1; i >= 0; i--) {  
            sortedArr[count[arr[i]] - 1] = arr[i];  
            count[arr[i]]--;  
        }  
  
        // 将排序后的数组复制回原数组  
        System.arraycopy(sortedArr, 0, arr, 0, arr.length);  
    }  
  
    // 主方法,用于测试计数排序  
    public static void main(String[] args) {  
        int[] arr = {4, 2, 2, 8, 3, 3, 1};  
        System.out.println("Original array: " + Arrays.toString(arr));  
  
        countingSort(arr);  
  
        System.out.println("Sorted array: " + Arrays.toString(arr));  
    }  
}  
  

  在这段代码中,我添加了一个findMaxValue方法来查找数组中的最大值,以便正确地初始化计数数组count的大小。然后,我添加了一个main方法来测试countingSort方法。main方法创建了一个示例数组,打印出原始数组,调用countingSort方法进行排序,并打印出排序后的数组。

其他相关排序算法详解文章汇总

常用的排序算法之基数排序(Radix Sort)

常用的排序算法之桶排序(Bucket Sort) 

常用的排序算法之计数排序(Counting Sort) 

常用的排序算法之堆排序(Heap Sort) 

常用的排序算法之快速排序(Quick Sort)

常用的排序算法之归并排序(Merge Sort)

常用的排序算法之希尔排序(Shell Sort)

常用的排序算法之插入排序(Insertion Sort)

常用的排序算法之选择排序(Selection Sort)

常用的排序算法之冒泡排序(Bubble Sort)

posted @ 2024-05-27 16:30  JackYang  阅读(347)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3