iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > node.js >如何实现计数排序
  • 369
分享到

如何实现计数排序

2024-04-02 19:04:59 369人浏览 薄情痞子
摘要

这篇文章主要介绍“如何实现计数排序”,在日常操作中,相信很多人在如何实现计数排序问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何实现计数排序”的疑惑有所帮助!接下来,请跟着

这篇文章主要介绍“如何实现计数排序”,在日常操作中,相信很多人在如何实现计数排序问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何实现计数排序”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

因为今年编程网的效益不错,所以老板就想给员工发些小福利,让小二根据员工工龄进行排序,但是公司共有 100000 名员工,公司开业 10 年,员工工龄从  0 - 10 不等。

看来这真是一个艰巨的任务啊。

当然我们可以借助之前说过的 归并排序 和 快速排序 解决,但是我们有没有其他更好的方法呢?

了解排序算法的老哥可能已经猜到今天写什么啦。是滴,我们今天来写写用空间换时间的线性排序。

说之前我们先来回顾一下之前的排序算法,最好的时间复杂度为 O(nlogn) ,且都基于元素之间的比较来进行排序。

我们来说一下非基于元素比较的排序算法,且时间复杂度为 O(n),时间复杂度是线性的,所以我们称其为线性排序算法。

其优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k),此时的 k  则代表整数的范围。快于任何一种比较类排序算法,不过也是需要牺牲一些空间来换取时间。

下面我们先来看看什么是计数排序,这个计数的含义是什么?

我们假设某一分店共有 10 名员工,

工龄分别为 1,2,3,5,0,2,2,4,5,9

那么我们将其存在一个长度为 10 的数组里,,但是我们注意,我们数组此时存的并不是元素值,而是元素的个数。见下图

如何实现计数排序

注:此时我们这里统计次数的数组长度根据最大值来决定,上面的例子中最大值为 9 ,则长度为 9 + 1 = 10。暂且先这样理解,后面会对其优化

我们继续以上图的例子来说明,在该数组中,索引代表的为元素值(也就是上面例子中的工龄),数组的值代表的则是元素个数(也就是不同工龄出现的次数)。

即工龄为 0 的员工有 1 个, 工龄为 1 的员工有 1 个,工龄为 2 的员工有 3 个 。。。

然后我们根据出现次数将其依次取出看看是什么效果。

0,1,2,2,2,3,4,5,5,9

我们发现此时元素则变成了有序的,但是这并不是排序,只是简单的按照统计数组的下标,输出了元素值,并没有真正的给原始数组进行排序。

这样操作之后我们不知道工龄属于哪个员工。

见下图

如何实现计数排序

举例

虽然喵哥和杰哥工龄相同,如果我们按照上面的操作输出之后,我们不能知道工龄为 4 的两个员工,哪个是喵哥哪个是杰哥。

所以我们需要借助其他方法来对元素进行排序。

大家还记不记得我们之前说过的前缀和,下面我们通过上面统计次数的数组求出其前缀和数组。

如何实现计数排序

因为我们是通过统计次数的数组得到了前缀和数组,那么我们来分析一下 presum 数组里面值的含义。

例如我们的 presum[2] = 5 ,代表的则是原数组小于等于 2 的值共有 5 个。presum[4] = 7 代表小于等于 4 的元素共有 7  个。

是不是感觉计数排序的含义要慢慢显现出来啦。

其实到这里我们已经可以理解的差不多了,还差最后一步,

此时我们要从后往前遍历原始数组,然后将遍历到的元素放到临时数组的合适位置,并修改 presum 数组的值,遍历结束后则达到了排序的目的。

这时有人要问了,为什么我们要从后往前遍历呢?

这个问题的答案,我们等下说,继续往下看吧。

如何实现计数排序

计数排序

我们从后往前遍历,nums[9] = 9,则我们拿该值去 presum 数组中查找,发现 presum[nums[9]] = presum[9] = 10  ,

大家还记得我们 presum 数组里面每个值的含义吗,我们此时 presum[9] = 10,则代表在数组中,小于等于的数共有 10  个,则我们要将他排在临时数组的第 10 个位置,也就是 temp[9] = 9。

我们还需要干什么呢?我们想一下,我们已经把 9 放入到 temp 数组里了,已经对其排好序了,那么我们的 presum  数组则不应该再统计他了,则将相应的位置减 1 即可,也就是 presum[9] = 10 - 1 = 9;

如何实现计数排序

下面我们继续遍历 5 ,然后同样执行上诉步骤

如何实现计数排序

我们继续查询 presum 数组,发现 presum[5] = 9,则说明小于等于 5 的数共有 9 个,我们将其放入到 temp 数组的第 9  个位置,也就是

temp[8] = 5。然后再将 presum[5] 减 1 。

如何实现计数排序

是不是到这里就理解了计数排序的大致思路啦。

那么我们为什么需要从后往前遍历呢?我们思考一下,如果我们从前往后遍历,相同元素的话,前面的元素则会先归位再减一,这样则会使计数排序变成不稳定的排序算法。

这个排序的过程像不像查字典呢?通过查询 presum 数组,得出自己应该排在临时数组的第几位。然后再修改下字典,直到遍历结束。

那么我们先来用动画模拟一下我们这个 bug 版的计数排序,加深理解。

注:我们得到 presum 数组的过程在动画中省略。直接模拟排序过程。

但是到现在就完了吗?显然没有,我们思考下这个情况。

假如我们的数字为 90,93,94,91,92 如果我们根据上面方法设置 presum 数组的长度,那我们则需要设置数组长度为  95(因为最大值是94),这样显然是不合理的,会浪费掉很多空间。

还有就是当我们需要对负数进行排序时同样会出现问题,因为我们求次数的时候是根据 nums[index] 的值来填充 presum 数组的,所以当  nums[index] 为负数时,填充 presum 数组时则会报错。

此时通过最大值来定义数组长度也不合理。

所以我们需要采取别的方法来定义数组长度。

下面我们来说一下偏移量的概念。

例如 90,93,94,91,92,我们 可以通过 max ,min 的值来设置数组长度即 94 - 90 + 1 = 5 。偏移量则为 min  值,也就是 90。那么我们的 90 则对应索引 0 。

见下图。

如何实现计数排序

这样我们填充 presum 数组时就不会出现浪费空间的情况了,负数?出现负数的情况当然也可以。继续看

例如:-1,-3,0,2,1

如何实现计数排序

一样可以,哦了,到这里我们就搞定了计数排序,下面我们来看一哈代码吧。

class Solution {     public int[] sortArray(int[] nums) {          int len = nums.length;         if (nums.length < 1) {              return nums;         }         //求出最大最小值         int max = nums[0];         int min = nums[0];         for (int x : nums) {             if (max < x)  max = x;                    if (min > x)  min = x;                  }         //设置 presum 数组长度,然后求出我们的前缀和数组,         //这里我们可以把求次数数组和前缀和数组用一个数组处理         int[] presum = new int[max-min+1];         for (int x : nums) {             presum[x-min]++;         }         for (int i = 1; i < presum.length; ++i) {             presum[i] = presum[i-1]+presum[i];          }         //临时数组         int[] temp = new int[len];         //遍历数组,开始排序,注意偏移量         for (int i = len-1; i >= 0; --i) {             //查找 presum 字典,然后将其放到临时数组,注意偏移度             int index = presum[nums[i]-min]-1;             temp[index] = nums[i];             //相应位置减一             presum[nums[i]-min]--;                    }         //copy回原数组         System.arraycopy(temp,0,nums,0,len);         return nums;     } }

好啦,这个排序算法我们已经搞定了,下面我们来扒一扒它。

计数排序时间复杂度分析

我们的总体运算量为 n+n+k+n ,总体运算是 3n + k 所以时间复杂度为 O(N+K);

计数排序空间复杂度分析

我们用到了辅助数组,空间复杂度为 O(n)

计数排序稳定性分析

稳定性在我们最后存入临时数组时有体现,我们当时让其放入临时数组的合适位置,并减一,所以某元素前面的相同元素,在临时数组,仍然在其前面。所以计数排序是稳定的排序算法。

虽然计数排序效率不错但是用到的并不多。

  • 这是因为其当数组元素的范围太大时,并不适合计数排序,不仅浪费时间,效率还会大大降低。

  • 当待排序的元素非整数时,也不适用,大家思考一下这是为什么呢?

到此,关于“如何实现计数排序”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: 如何实现计数排序

本文链接: https://www.lsjlt.com/news/83137.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何实现计数排序
    这篇文章主要介绍“如何实现计数排序”,在日常操作中,相信很多人在如何实现计数排序问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何实现计数排序”的疑惑有所帮助!接下来,请跟着...
    99+
    2022-10-19
  • Java排序算法之计数排序如何实现
    这篇文章主要为大家展示了“Java排序算法之计数排序如何实现”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java排序算法之计数排序如何实现”这篇文章吧。计数排序是非比较的排序算法,用辅助数组对...
    99+
    2023-06-21
  • 计数排序与桶排序python实现
    计数排序 计数排序原理: 找到给定序列的最小值与最大值 创建一个长度为最大值-最小值+1的数组,初始化都为0 然后遍历原序列,并为数组中索引为当前值-最小值的值+1 此时数组中已经记录好每个值的数量,自然也就是有序的了 ...
    99+
    2023-01-31
    python
  • 数据结构:直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序,计数排序(C实现)
    个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》 文章目录 前言一、插入排序1.直接插入排序2.希尔排序 二、选择排序1. 选择排序2.堆排序 三、交换排序1.冒...
    99+
    2023-09-14
    数据结构 c语言 排序算法
  • Python、PHP、Java怎么实现计数排序
    这篇文章主要讲解了“Python、PHP、Java怎么实现计数排序”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python、PHP、Java怎么实现计数排序”吧!计数排序(Counting...
    99+
    2023-06-27
  • 八大排序(三)堆排序,计数排序,归并排序
    一、堆排序 什么是堆排序:堆排序(Heap Sort)就是对直接选择排序的一种改进。此话怎讲呢?直接选择排序在待排序的n个数中进行n-1次比较选出最大或者最小的,但是在选出最大或者最小的数后,并没有对原来的序列进行改变,这使得下一次选数时还...
    99+
    2023-10-21
    算法 数据结构
  • java如何实现数组排序
    这篇文章主要为大家展示了“java如何实现数组排序”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“java如何实现数组排序”这篇文章吧。数组排序(冒泡排序)public class&nb...
    99+
    2023-06-27
  • js如何实现数字排序
    这篇文章主要介绍了js如何实现数字排序,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。数字排序默认地,sort() 函数按照字符串顺序对值进行...
    99+
    2022-10-19
  • PHP如何实现数组排序
    这篇文章主要为大家展示了“PHP如何实现数组排序”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“PHP如何实现数组排序”这篇文章吧。数组排序 a - b 是数字数组写法 遇到字符串的时候就要var...
    99+
    2023-06-03
  • Python实现的计数排序算法示例
    本文实例讲述了Python实现的计数排序算法。分享给大家供大家参考,具体如下: 计数排序是一种非常快捷的稳定性强的排序方法,时间复杂度O(n+k),其中n为要排序的数的个数,k为要排序的数的组大值。计数排序...
    99+
    2022-06-04
    示例 算法 Python
  • PHP中如何实现数组排序
    本篇文章给大家分享的是有关PHP中如何实现数组排序,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。在了解了usort自定义排序后,我们再来看看sort(),这个函数可谓是数组里的...
    99+
    2023-06-17
  • 如何实现统计重复次数并排序的批处理
    这篇文章将为大家详细讲解有关如何实现统计重复次数并排序的批处理,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。代码如下:@echo off :: 目的: :: SearchNet.TXT中每行只有一个数,统...
    99+
    2023-06-08
  • 算法笔记(六):计数排序和基数排序
    (一)说明         这里我是按自己的理解去实现的,时间复杂度和空间复杂度和算法导论上的可能不一样,感兴趣的话参考下就行,感觉最重要的还是算法思想。根据算法性能去实现算法以后再研究。 (二)计数排序     计数排序的基本思想是:对...
    99+
    2023-01-30
    基数 算法 笔记
  • thinkphp如何实现排序
    这篇文章主要介绍“thinkphp如何实现排序”,在日常操作中,相信很多人在thinkphp如何实现排序问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”thinkphp如何实现排序”的疑惑有所帮助!接下来,请跟...
    99+
    2023-07-04
  • mysql如何实现排序
    mysql中实现排序的方法有以下几种通过在数据表使用以下命令实现的排序单列排序SELECT * FROM test1 ORDER BY date_time多列排序 SELECT * FROM test1 ORDER BY `...
    99+
    2022-10-08
  • C++如何实现序列排序
    这篇文章主要讲解了“C++如何实现序列排序”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++如何实现序列排序”吧!Permutation Sequence 序列排序The set ...
    99+
    2023-06-19
  • Java排序算法之堆排序如何实现
    这篇文章主要介绍了Java排序算法之堆排序如何实现,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。二叉堆是完全二叉树或者是近似完全二叉树。二叉堆满足二个特性︰1.父结点的键值总...
    99+
    2023-06-21
  • php如何实现二维数组排序
    在php中,可以使用array_multisort()函数实现二维数组排序。该函数可以对多个数组或多维数组进行排序,语法“array_multisort(二维数组,排列顺序,排序类型)”;当第二个参数省略或设置为“SORT_ASC”则升序排...
    99+
    2022-09-08
  • hadoop详解如何实现数据排序
    目录前言MapReduce排序MapReduce排序分类1、部分排序2、全排序3、辅助排序4、二次排序自定义排序案例1、自定义一个Bean对象,实现WritableComparabl...
    99+
    2022-11-13
  • mybatis如何实现的数据库排序
    目录mybatis数据库排序mybatis order by 排序方式能够很大程度防止sql注入order by 之后要使用$而非#mybatis数据库排序 今天用到了对数据库按照倒...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作