动画:一篇文章快速学会计数排序

内容介绍

计数排序简介

我们知道目前排序速度最快的是时间复杂度为O(nlogn)的排序算法,如快速排序、归并排序和堆排序。其中O(logn)是利用了分治思想进行数据二分远距离比较和交换元素的位置。之前的算法都是基于元素比较的,有没有一种算法,它的时间复杂度小于O(nlogn)呢?这样的算法是存在的。计数排序就是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward提出。它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。 当然这是一种牺牲空间换取时间的做法。

计数排序适用于数据量很大,但是数据的范围比较小的情况。比如对一个公司20万人的年龄进行排序,要排序的数据量很大,但是年龄分布在0 ~ 134岁之间(最大年龄数据来源吉尼斯世界记录)。

计数排序的思想

使用一个辅助数组,遍历待排序的数据,待排序数据的值就是辅助数组的索引,辅助数组索引对应的位置保存这个待排序数据出现的次数。最后从辅助数组中取出待排序的数据,放到排序后的数组中。

计数排序动画演示

一般没有特殊要求排序算法都是升序排序,小的在前,大的在后。数组由{6, 8, 9, 5, 3, 2, 1, 7, 8, 5} 这10个无序元素组成。

计数排序分析

通过上面的动画演示,我们可以将计数排序分为两个过程:

  1. 统计过程
  2. 排序过程。

假设我们要排序的数据是10个0到9的随机数字,例如{6, 8, 9, 5, 3, 2, 1, 7, 8, 5} 这10个数据,如下图所示:

  1. 统计过程
    取出元素6,放到辅助数组索引6的地方,辅助数组记录数据6出现1次,效果如下图:

取出元素8,放到辅助数组索引8的地方,辅助数组记录数据8出现1次,效果如下图:

取出元素9,放到辅助数组索引9的地方,辅助数组记录数据9出现1次,效果如下图:

依次类推。中间省略一部分。

再次取出元素8,放到辅助数组索引8的地方,辅助数组记录数据8出现2次,效果如下图:

最终辅助数组效果如下:

这个辅助数组统计了每个数据出现的次数,最后遍历这个辅助数组,辅助数组中的索引就是元素的值,辅助数组中索引对应的值就是这个数据出现的次数,放到排序后的数组中。

  1. 排序过程
    辅助数组索引1的对应的数据1放到排序后数组中,效果如下:

辅助数组索引2的对应的数据2放到排序后数组中,效果如下:

依次类推,取出统计数组中的数据放到排序后的数组中,中间省略部分。

辅助数组索引5的对应的数据5放到排序后数组中,效果如下:

再次将辅助数组索引5的对应的数据5放到排序后数组中,效果如下:

依次类推,中间省略部分。

最终排序后的效果如下:

计数排序代码编写

public class CountSortTest {
   
    public static void main(String[] args) {
   
        int[] arr = new int[] {
   6, 8, 9, 5, 3, 2, 1, 7, 8, 5};

        countSort(arr);
        System.out.println("排序后:" + Arrays.toString(arr));
    }

    // 假设我们要排序的数据是10个0到9的随机数字
    public static void countSort(int[] arr) {
   
        // 1.得到待排序数据的最大值
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
   
            int num = arr[i];
            if (num 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值