漫画:什么是计数排序

转载自   漫画:什么是计数排序

 

 

 

 

 

 

 

 

 

假定20个随机整数的值如下:

9,3,5,4,9,1,2,7,8,1,3,6,5,3,4,0,10,9 ,7,9

如何给这些无序的随机整数排序呢?

非常简单,让我们遍历这个无序的随机数列,每一个整数按照其值对号入座,对应数组下标的元素进行加1操作。

比如第一个整数是9,那么数组下标为9的元素加1:

 

第二个整数是3,那么数组下标为3的元素加1:

 

继续遍历数列并修改数组......

最终,数列遍历完毕时,数组的状态如下:

 

数组每一个下标位置的值,代表了数列中对应整数出现的次数。

有了这个“统计结果”,排序就很简单了。直接遍历数组,输出数组元素的下标值,元素的值是几,就输出几次:

0,1,1,2,3,3,3,4,4,5,5,6,7,7,8,9,9,9,9,10

显然,这个输出的数列已经是有序的了。

 

 

 

public static int[] countSort(int[] array) {//1.得到数列的最大值int max = array[0];for(int i=1; i<array.length; i++){if(array[i] > max){max = array[i];}}//2.根据数列最大值确定统计数组的长度int[] countArray = new int[max+1];//3.遍历数列,填充统计数组for(int i=0; i<array.length; i++){countArray[array[i]]++;}//4.遍历统计数组,输出结果int index = 0;int[] sortedArray = new int[array.length];for(int i=0; i<countArray.length; i++){for(int j=0; j<countArray[i]; j++){sortedArray[index++] = i;}}return sortedArray;}public static void main(String[] args) {int[] array = new int[] {4,4,6,5,3,2,8,1,7,5,6,0,10};int[] sortedArray = countSort(array);System.out.println(Arrays.toString(sortedArray));}

这段代码在一开头补充了一个步骤,就是求得数列的最大整数值max。后面创建的统计数组countArray,长度就是max+1,以此保证数组的最后一个下标是max。

 

 

 

95,94,91,98,99,90,99,93,91,92

 

怎么解决这个问题呢?

很简单,我们不再以(输入数列的最大值+1)作为统计数组的长度,而是以(数列最大值和最小值的差+1)作为统计数组的长度。

同时,数列的最小值作为一个偏移量,用于统计数组的对号入座。

以刚才的数列为例,统计数组的长度为  99-90+1 = 10 ,偏移量等于数列的最小值 90 。

对于第一个整数95,对应的统计数组下标是 95-90 = 5,如图所示:

 

 

 

什么意思呢?让我们看看下面的例子:

 

给定一个学生的成绩表,要求按成绩从低到高排序,如果成绩相同,则遵循原表固有顺序。

那么,当我们填充统计数组以后,我们只知道有两个成绩并列95分的小伙伴,却不知道哪一个是小红,哪一个是小绿:

 

 

下面的讲解会有一些烧脑,请大家扶稳坐好。我们仍然以刚才的学生成绩表为例,把之前的统计数组变形成下面的样子:

 

这是如何变形的呢?统计数组从第二个元素开始,每一个元素都加上前面所有元素之和。

为什么要相加呢?初次看到的小伙伴可能会觉得莫名其妙。

这样相加的目的,是让统计数组存储的元素值,等于相应整数的最终排序位置。比如下标是9的元素值为5,代表原始数列的整数9,最终的排序是在第5位。

接下来,我们创建输出数组sortedArray,长度和输入数列一致。然后从后向前遍历输入数列:

第一步,我们遍历成绩表最后一行的小绿:

小绿是95分,我们找到countArray下标是5的元素,值是4,代表小绿的成绩排名位置在第4位。

同时,我们给countArray下标是5的元素值减1,从4变成3,,代表着下次再遇到95分的成绩时,最终排名是第3。

 

第二步,我们遍历成绩表倒数第二行的小白:

小白是94分,我们找到countArray下标是4的元素,值是2,代表小白的成绩排名位置在第2位。

同时,我们给countArray下标是4的元素值减1,从2变成1,,代表着下次再遇到94分的成绩时(实际上已经遇不到了),最终排名是第1。

 

第三步,我们遍历成绩表倒数第三行的小红:

小红是95分,我们找到countArray下标是5的元素,值是3(最初是4,减1变成了3),代表小红的成绩排名位置在第3位。

同时,我们给countArray下标是5的元素值减1,从3变成2,,代表着下次再遇到95分的成绩时(实际上已经遇不到了),最终排名是第2。

 

这样一来,同样是95分的小红和小绿就能够清楚地排出顺序了,也正因此,优化版本的计数排序属于稳定排序

后面的遍历过程以此类推,这里就不再详细描述了。

 

public static int[] countSort(int[] array) {//1.得到数列的最大值和最小值,并算出差值dint max = array[0];int min = array[0];for(int i=1; i<array.length; i++) {if(array[i] > max) {max = array[i];}if(array[i] < min) {min = array[i];}}int d = max - min;//2.创建统计数组并统计对应元素个数int[] countArray = new int[d+1];for(int i=0; i<array.length; i++) {countArray[array[i]-min]++;}//3.统计数组做变形,后面的元素等于前面的元素之和int sum = 0;for(int i=0;i<countArray.length;i++) {sum += countArray[i];countArray[i] = sum;}//4.倒序遍历原始数列,从统计数组找到正确位置,输出到结果数组int[] sortedArray = new int[array.length];for(int i=array.length-1;i>=0;i--) {sortedArray[countArray[array[i]-min]-1]=array[i];countArray[array[i]-min]--;}return sortedArray;}public static void main(String[] args) {int[] array = new int[] {95,94,91,98,99,90,99,93,91,92};int[] sortedArray = countSort(array);System.out.println(Arrays.toString(sortedArray));}

 

 

 

 

 

 

 

1.当数列最大最小值差距过大时,并不适用计数排序。

比如给定20个随机整数,范围在0到1亿之间,这时候如果使用计数排序,需要创建长度1亿的数组。不但严重浪费空间,而且时间复杂度也随之升高。

2.当数列元素不是整数,并不适用计数排序。

如果数列中的元素都是小数,比如25.213,或是0.00000001这样子,则无法创建对应的统计数组。这样显然无法进行计数排序。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/324603.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Office365开发系列——开发一个全功能的Word Add-In

2016年10月我参加了在北京举行的DevDays Asia 2016 - Office 365应用开发”48小时黑客马拉松“&#xff0c;我开发的一个Word Add-In Demo——WordTemplateHelper获得了二等奖。在会场有幸结识了陈希章老师&#xff0c;在与陈老师的交流中受益良多&#xff0c;得知陈老师在准备…

秒懂python的深浅copy

dict , list ,set , s {name:alex....} s2 s , 此时s2和s是共享 同一份数据 的&#xff0c;copy一份新数据 , 浅copy, 只copy第一层 s2 s.copy() 深copy s4 copy.deepcopy(s)浅拷贝 深拷贝

SpringBoot整合Shiro实现登录认证和授权CHCache

文章目录一、 springboot实现普通登录1 添加依赖2 编写配置文件3 新建实体类和mapper4 编写业务层代码5 编写控制器6 编写启动类7 编写登录页面和主页面二、 springboot整合shiro实现登录认证和凭证匹配1 添加依赖2 自定义Realm3 编写配置4 userService新增单元方法&#xff1a…

java中如何对对象排序?

大家好&#xff0c;我是雄雄。前言&#xff1a;我们知道&#xff0c;在平时做项目的过程中&#xff0c;我们总会用到各种各样的排序&#xff0c;或是升序&#xff0c;或是降序。在java中&#xff0c;要实现排序有好多中方式&#xff0c;比如我们耳熟能详的冒泡排序、选择排序等…

Java程序员必看的 13 本 Java 书籍

转载自 Java程序员必看的 13 本 Java 书籍 关乎于程序员&#xff0c;除了做项目来提高自身的技术&#xff0c;还有一种提升自己的专业技能就是&#xff1a;多&#xff01;看&#xff01;书&#xff01; 毕竟&#xff0c;书是学习的海洋呢&#xff01;So&#xff0c;Java程序…

祝你生日快乐!

祝生日快乐今天&#xff0c;于我来说是个特别的日子。本来&#xff0c;我是比较低调的&#xff0c;尤其是对于生日来说&#xff0c;可以说是这些年都没有好好的过过&#xff0c;要么忘记了&#xff0c;要么就是在异国他乡的&#xff0c;谁都不识&#xff0c;这一天和往常的一天…

.NET Exceptionless 日志收集框架本地环境搭建

一、简介 Exceptionless 是一个开源的实时的日志收集框架&#xff0c;它可以应用在基于 ASP.NET&#xff0c;ASP.NET Core&#xff0c;Web Api&#xff0c;Web Forms&#xff0c;WPF&#xff0c;Console&#xff0c;MVC 等技术栈的应用程序中&#xff0c;并且提供了Rest接口可以…

java中如何对汉字进行排序?

前言&#xff1a;上一篇文章我们讲解了java中实现Comparator进行排序 和实现Comparable进行排序&#xff0c;我们分别举例根据学号和姓名降序排序&#xff0c;原文在这里&#xff1a;java中如何对对象排序&#xff1f; &#xff0c;不过在文章的最后&#xff0c;我故意留了个问…

Blazor将.NET带回到浏览器

由Steve Sanderson开发的Blazor尝试使用WebAssembly和DotNetAnywhere将.NET带回到浏览器。它不是要成为一个像Flash或Silverlight那样的完整生产框架&#xff0c;而是要探索一下有什么可能性。 WebAssembly将自己描述成一个“内存安全的沙箱执行环境”标准&#xff0c;它“甚至…

过滤器和监听器

文章目录01 过滤器的简介02 使用过滤器进行乱码解决03 使用过滤器进行登陆的控制04 过滤器更多内容05 监听器实现日志记录06 监听器实现在线人数的统计07 其他监听器使用01 过滤器的简介 为什么使用过滤器&#xff1f; 我们目前书写项目中遇到的问题&#xff1f; A、目前使用的…

高启航:秋运会!

本文原创&#xff1a;高启航&#xff08;本文所有收益均归高启航所有&#xff09;在十月份的二十一号&#xff0c;我们济南信息工程学校迎来了一年一度的秋季运动会。这次秋运会&#xff0c;每一个班级所准备的开幕式、训练已久的千人武术大展演、以及在运动会上表现优越的运动…

用python画出吉祥物

大前提 你需要一个"npy" 效果图 源码 # 库的导入 import turtleturtle.title(PythonBingDwenDwen&#xff08;axing&#xff09;) #这里的字我们可以自己进行修改turtle.speed(10) # 速度&#xff0c;如果觉得20快了&#xff0c;你们可以设置10# 左手 turtle.p…

RabbitMQ知多少

1.引言 RabbitMQ——Rabbit Message Queue的简写&#xff0c;但不能仅仅理解其为消息队列&#xff0c;消息代理更合适。RabbitMQ 是一个由 Erlang 语言开发的AMQP&#xff08;高级消息队列协议&#xff09;的开源实现&#xff0c;其内部结构如下&#xff1a; RabbitMQ作为一个…

王宝兴:秋运会

本文原创&#xff1a;王宝兴本文所有收益归王宝兴所有一年一度的运动会如期而至。可谓是“沙场秋点兵”的壮阔&#xff0c;给了我们难以言喻的激情。为了入场式&#xff0c;为了我们每个人&#xff0c;为了我们整个班集体&#xff0c;所有人付出的不止一点&#xff0c;在这短短…

.NET Core快速入门教程 1、开篇:说说.NET Core的那些事儿

一、.NET Core的诞生 聊 .NET Core&#xff0c;就不得不说他的爸爸 .NET。当年Java刚刚兴起&#xff0c;如火如荼&#xff0c;微软也非常推崇Java&#xff0c;当时Windows平台的Java虚拟机就是微软按照JVM标准实现的&#xff0c;据说也是当时性能最好的Java虚拟机。但是微软也…

机器学习和深度学习概念入门

转载自 机器学习和深度学习概念入门 作者&#xff1a;谭东 遵循&#xff1a;BY-SA&#xff08;署名-相同方式共享4.0协议&#xff09; 对于很多初入学习人工智能的学习者来说&#xff0c;对人工智能、机器学习、深度学习的概念和区别还不是很了解&#xff0c;有可能你每天…

lldb 调试 linux下 .net Core 总结及开源扩展 yinuo

相信很多朋友在跟随微软.net core 从windows平台迁移至linux平台的过程中遇到很多别扭的地方&#xff0c;这里我只聊聊 运行时 调试的那些事儿。 首先从工具上来讲Windows上的windbg肯定是运行时的首选调试工具(因为有对应版本的SOS.dll)&#xff0c;在linux平台运行时调试需要…

班级日常分享:一天一瞬间!

好久没有记录班级日常了&#xff0c;自运动会结束之后&#xff0c;事情比较多&#xff0c;也很忙&#xff0c;所以没有及时记录。19级3班最近在上bootstrap&#xff0c;属于前端的范畴&#xff0c;内容较简单&#xff0c;同学们都能跟的上老师的步伐&#xff0c;一行一行大代码…

Java 程序员必须掌握的 8 道数据结构面试题,你会几道

转载自 Java 程序员必须掌握的 8 道数据结构面试题&#xff0c;你会几道 瑞士计算机科学家Niklaus Wirth在1976年写了一本书&#xff0c;名为《算法数据结构编程》。 40多年后&#xff0c;这个等式仍被奉为真理。这就是为什么在面试过程中&#xff0c;需要考察软件工程师对数…