简介

今天我们介绍一种不需要作比较就能排序的算法:count排序。

count排序是一种空间换时间的算法,我们借助一个外部的count数组来统计各个元素出现的次数,从而最终完成排序。

count排序的例子

count排序有一定的限制,因为外部的count数组长度是和原数组的元素范围是一致的,所以count排序一般只适合数组中元素范围比较小的情况。

我们举一个0-9的元素的排序的例子:3,4,2,5,6,2,4,9,1,3,5。

先看一个动画,看看是怎么排序的:

count数组里面存放的是从0到9这些元素出现的次数。

我们遍历原始数组,遇到相应的数字就给相应的count+1。

等所有的元素都count之后,再根据count数组中的值还原排序过后的数组。

count排序的java实现

count排序很简单,我们主要掌握下面两个大的步骤:

  1. 遍历原始数组,构建count数组。
  2. 根据count数组中的count值,重新构建排序数组。
public class CountingSort {

    public void doCountingSort(int[] array){
int n = array.length; // 存储排序过后的数组
int output[] = new int[n]; // count数组,用来存储统计各个元素出现的次数
int count[] = new int[10];
for (int i=0; i<10; ++i) {
count[i] = 0;
}
log.info("初始化count值:{}",count); // 将原始数组中数据出现次数存入count数组
for (int i=0; i<n; ++i) {
++count[array[i]];
}
log.info("count之后count值:{}",count); //遍历count,将相应的数据插入output
int j=0;
for(int i=0; i<10; i++){
while(count[i]-- > 0){
output[j++]=i;
}
}
log.info("构建output之后的output值:{}",output); //将排序后的数组写回原数组
for (int i = 0; i<n; ++i)
array[i] = output[i];
} public static void main(String[] args) {
int[] array= {3,4,2,5,6,2,4,9,1,3,5};
CountingSort countingSort=new CountingSort();
log.info("countingSort之前的数组为:{}",array);
countingSort.doCountingSort(array);
}
}

上面的注释应该很清楚了。

运行的结果如下:

count排序的第二种方法

在我们获得count数组中每个元素的个数之后,其实我们还有另外一个生成结果数组的办法:

// 这里是一个小技巧,我们根据count中元素出现的次数计算对应元素第一次应该出现在output中的下标。
//这里的下标是从右往左数的
for (int i=1; i<10; i++) {
count[i] += count[i - 1];
}
log.info("整理count对应的output下标:{}",count);
// 根据count中的下标,构建排序后的数组
//插入一个之后,相应的count下标要减一
for (int i = n-1; i>=0; i--)
{
output[count[array[i]]-1] = array[i];
--count[array[i]];
}
log.info("构建output之后的output值:{}",output);

主要分为两步:

第一步我们根据count中元素出现的次数计算对应元素第一次应该出现在output中的下标。这里的下标是从右往左数的。

第二步根据count中的下标,构建排序后的数组,插入一个之后,相应的count下标要减一。

可能不是很好理解,大家可以结合输出结果反复琢磨一下。

count排序的时间复杂度

从上面的代码我们可以看到,count排序实际上只做了少量次数的遍历。所以它的时间复杂度是O(n)。

本文的代码地址:

learn-algorithm

本文已收录于 http://www.flydean.com/algorithm-count-sort/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

看动画学算法之:排序-count排序的更多相关文章

  1. 看动画学算法之:二叉搜索树BST

    目录 简介 BST的基本性质 BST的构建 BST的搜索 BST的插入 BST的删除 简介 树是类似于链表的数据结构,和链表的线性结构不同的是,树是具有层次结构的非线性的数据结构. 树是由很多个节点组 ...

  2. 看动画学算法之:linkedList

    目录 简介 linkedList的构建 linkedList的操作 头部插入 尾部插入 中间插入 删除节点 简介 linkedList应该是一种非常非常简单的数据结构了.节点一个一个的连接起来,就成了 ...

  3. 看动画学算法之:栈stack

    目录 简介 栈的构成 栈的实现 使用数组来实现栈 使用动态数组来实现栈 使用链表来实现 简介 栈应该是一种非常简单并且非常有用的数据结构了.栈的特点就是先进后出FILO或者后进先出LIFO. 实际上很 ...

  4. 看动画学算法之:平衡二叉搜索树AVL Tree

    目录 简介 AVL的特性 AVL的构建 AVL的搜索 AVL的插入 AVL的删除 简介 平衡二叉搜索树是一种特殊的二叉搜索树.为什么会有平衡二叉搜索树呢? 考虑一下二叉搜索树的特殊情况,如果一个二叉搜 ...

  5. 看动画学算法之:队列queue

    目录 简介 队列的实现 队列的数组实现 队列的动态数组实现 队列的链表实现 队列的时间复杂度 简介 队列Queue是一个非常常见的数据结构,所谓队列就是先进先出的序列结构. 想象一下我们日常的排队买票 ...

  6. 看动画学算法之:hashtable

    目录 简介 散列表的关键概念 数组和散列表 数组的问题 hash的问题 线性探测 二次探测 双倍散列 分离链接 rehash 简介 java中和hash相关并且常用的有两个类hashTable和has ...

  7. 看动画学算法之:doublyLinkedList

    目录 简介 doublyLinkedList的构建 doublyLinkedList的操作 头部插入 尾部插入 插入给定的位置 删除指定位置的节点 简介 今天我们来学习一下复杂一点的LinkedLis ...

  8. 看动画学算法之:双向队列dequeue

    目录 简介 双向队列的实现 双向队列的数组实现 双向队列的动态数组实现 双向队列的链表实现 双向链表的时间复杂度 简介 dequeue指的是双向队列,可以分别从队列的头部插入和获取数据,也可以从队列的 ...

  9. JavaScript 数据结构与算法之美 - 桶排序、计数排序、基数排序

    1. 前言 算法为王. 想学好前端,先练好内功,只有内功深厚者,前端之路才会走得更远. 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 JavaScript ,旨在入门数据结构与算 ...

随机推荐

  1. python基础 Day3

    python Day3 1.作业回顾 设定一个理想的数字比如88,让用户输入数字,如果比88大,则显示猜测的结果大:如果比66小,则显示猜测的结果小了,给用户三次猜测机会,如果显示猜测正确退出循环,如 ...

  2. Ceph Luminous手动解决pg分布不均衡问题

    原文链接: https://www.jianshu.com/p/afb6277dbfd6 1.设置集群仅支持 Luminous(或者L之后的)客户端 具体命令: ceph osd set-requir ...

  3. 下载 golang.org/x 包出错不用代理的解决办法

    原文链接:https://www.jianshu.com/p/6fe61053c8aa?utm_campaign=maleskine&utm_content=note&utm_medi ...

  4. 团队作业3:需求改进&系统设计(歪瑞古德小队)

    目录 一.需求&原型改进 1.1 用户需求调查 1.2 选题需求改进 1.3 功能分析的四个象限 1.4 完善需求规格说明书 1.5 任务分解WBS调整 1.6 项目进度计划调整 二.后端架构 ...

  5. Flink-1.10中的StreamingFileSink相关特性

    一切新知识的学习,都离不开官网得相关阅读,那么StreamingFileSink的官网介绍呢? https://ci.apache.org/projects/flink/flink-docs-rele ...

  6. 高并发&性能优化(一)------总体介绍

    [开篇词] 本文主要通过一些经典的高并发场景,以及一些基本的运维工具来讲述一些关于高并发以及性能优化相关的内容,主要包括性能瓶颈的定位,性能调优的思路和技巧等. [性能的衡量指标] ?什么是性能 性能 ...

  7. 牛客网数据库SQL实战解析(11-20题)

    牛客网SQL刷题地址: https://www.nowcoder.com/ta/sql?page=0 牛客网数据库SQL实战解析(01-10题): https://blog.csdn.net/u010 ...

  8. 力扣Leetcode 46. 全排列

    全排列 给定一个 没有重复 数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], ...

  9. HttpServletRespnse 对象 相关基本应用

    HttpServletRespnse 对象相关基本应用 向浏览器输出数据 getOutputStream() @Override protected void service(HttpServletR ...

  10. JVM 垃圾收集算法 标记-清楚、标记-复制、标记-整理

    摘要 Java程序在运行过程中会产生大量的对象,但是内存大小是有限的,如果光用而不释放,那内存迟早被耗尽.如C.C++程序,需要程序员手动释放内存,Java则不需要,是由垃圾回收器去自动回收. 垃圾回 ...