详解排序算法(四)之计数排序

2019 CCF CSP-J第一轮 2019CCF非专业级别软件能力认证第一轮(初赛) A卷 (B卷=A卷,顺序不同) 听说这次CSP可能是最后一次,因为以后是NOIP了……好好纪念一下 第一部分 一、单项选择题(共15题,每题2分,共计30分;每题有且仅有一个正确选项) 1.中国的国家顶级域名是() A. .cnB. .ch C. .chn D. .china 答案:A 解析:常识,中国国家顶级域名即是.cn(弱智题)【说话还是要文雅一点。】 2. 二进制数 11 1011 1001 0111 和... 阅读详情

计数排序

计数排序不是一个比较排序算法,该算法于1954年由 Harold H. Seward提出。

01 算法步骤

  1. 找到数列的最大值,计为 max

  2. 新建一个长度为 max + 1 的数组,计为 bucket

  3. 遍历数列,在 bucket 中找到值对应的下标,若对应下标里已有值,值加 1,若无值,将值设置为 1,例如

    值为5,则找到 bucket 中下标为 5 的位置,即 bucket [5],若 bucket [5] 不存在,则设置 bucket [5] 为1,即 bucket [5] = 1 ,若 bucket [5] 存在,则值加 1,即 bucket [5]++

  4. 遍历 bucket,对于存在值的元素,设其值为 count,下标为 index,往结果数组中插入 count 个元素,元素的值为 index例如

    bucket [5] = 3,则 count = 3,index = 5,往结果数组中插入 3 个 5。

02 示例

我们取 2, 3, 8, 7, 1, 2, 2, 2, 7, 3, 9, 8, 2, 1, 4, 2, 4, 6, 9, 2 来示范

  1. 找到最大值为 9

  2. 新建一个长度为 10 的数组,[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

  3. 找到下标 2,将其值置为 1,得 [0, 0, 1, 0, 0, 0, 0, 0, 0, 0]

    找到下标 3,将其值置为 1,得 [0, 0, 1, 1, 0, 0, 0, 0, 0, 0]

    找到下标 8,将其值置为 1,得 [0, 0, 1, 1, 0, 0, 0, 0, 1, 0]

    找到下标 7,将其值置为 1,得 [0, 0, 1, 1, 0, 0, 0, 1, 1, 0]

    找到下标 1,将其值置为 1,得 [0, 1, 1, 1, 0, 0, 0, 1, 1, 0]

    找到下标 2,将其内值加 1,得 [0, 1, 2, 1, 0, 0, 0, 1, 1, 0]

    找到下标 2,将其内值加 1,得 [0, 1, 3, 1, 0, 0, 0, 1, 1, 0]

    找到下标 2,将其内值加 1,得 [0, 1, 4, 1, 0, 0, 0, 1, 1, 0]

    找到下标 7,将其内值加 1,得 [0, 1, 4, 1, 0, 0, 0, 2, 1, 0]

    找到下标 3,将其内值为 1,得 [0, 1, 4, 2, 0, 0, 0, 2, 1, 0]

    找到下标 9,将其值置为 1,得 [0, 1, 4, 2, 0, 0, 0, 2, 1, 1]

    找到下标 8,将其内值加 1,得 [0, 1, 4, 2, 0, 0, 0, 2, 2, 1]

    找到下标 2,将其内值加 1,得 [0, 1, 5, 2, 0, 0, 0, 2, 2, 1]

    找到下标 1,将其内值加 1,得 [0, 2, 5, 2, 0, 0, 0, 2, 2, 1]

    找到下标 4,将其值置为 1,得 [0, 2, 5, 2, 1, 0, 0, 2, 2, 1]

    找到下标 2,将其内值加 1,得 [0, 2, 6, 2, 1, 0, 0, 2, 2, 1]

    找到下标 4,将其内值加 1,得 [0, 2, 6, 2, 2, 0, 0, 2, 2, 1]

    找到下标 6,将其值置为 1,得 [0, 2, 6, 2, 2, 0, 1, 2, 2, 1]

    找到下标 9,将其内值加 1,得 [0, 2, 6, 2, 2, 0, 1, 2, 2, 2]

    找到下标 2,将其内值加 1,得 [0, 2, 7, 2, 2, 0, 1, 2, 2, 2]

  4. 遍历 [0, 2, 7, 2, 2, 0, 1, 2, 2, 2]

    插入 2 个 1,得 [1, 1]

    插入 7 个 2,得 [1, 1, 2, 2, 2, 2, 2, 2, 2]

    插入 2 个 3,得 [1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3]

    插入 2 个 4,得 [1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4]

    插入 1 个 6,得 [1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 6]

    插入 2 个 7,得 [1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 6, 7, 7]

    插入 2 个 8,得 [1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 6, 7, 7, 8, 8]

    插入 2 个 9,得 [1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 6, 7, 7, 8, 8, 9, 9]

    排序完成。

03 动态图

img

04 javascript代码

function countSort(arr) {
    const max = getMax(arr), // 数组中最大值
          bucketLen = max + 1
          bucket = new Array(bucketLen)
    let sortedIndex = 0

    for (let i = 0; i < arr.length; i++) {
        if (!bucket[arr[i]]) {
            bucket[arr[i]] = 0
        }
        bucket[arr[i]]++
    }

    for (let j = 0; j < bucketLen; j++) {
        while(bucket[j] > 0) {
            arr[sortedIndex++] = j
            bucket[j]--
        }
    }

    return arr
}

// 获取数组最大值
function getMax (arr) {
    let max = arr[0]

    arr.forEach(e => {
        max = e > max ? e : max
    })

    return max
}

优化版 —— 基于最小值的计数排序

经过上面的学习,我们已经掌握了计数排序的过程。但上面的算法有问题吗?当然有!!!

我们不妨举以下两个例子

  • 取数列 101, 99, 99, 100 ,按照上面的算法,所需数组长度为 102,但实际上,我们只用到了 3 个位置,空间大大浪费。
  • 假设数列中存在负数,如 -1, 10, 11,按照以上算法,数组长度为 12,可适配的值的范围为 0 - 11,但 -1 显然不在这个范围内

基于以上问题,优化版 —— 基于最小值的计数排序 便应运而生。

01 算法步骤

  1. 找到数列的最小值、最大值,分别计为 min、max

  2. 新建一个长度为 max + 1 的数组,计为 bucket

  3. 遍历数列,在 bucket 中找到 值 - min 对应的下标,若对应下标里已有值,值加 1,若无值,将值设置为 1,例如

    值为5,min = 2,则找到 bucket 中下标为 3 的位置,即 bucket [3],若 bucket [3] 不存在,则设置 bucket [3] 为 1,即 bucket [3] = 1 ,若 bucket [3] 存在,则值加 1,即 bucket [3]++

  4. 遍历 bucket,对于存在值的元素,设其值为 count,下标为 index,往结果数组中插入 count 个元素,元素的值为 min + index例如

    bucket [3] = 3,min = 2,则 count = 3,index = 3,min + index = 5,往结果数组中插入 3 个 5。

02 示例

我们取 101, 99, 99, 100 来示范

  1. 找到最小值为 99,最大值 101,101 - 99 = 2

  2. 新建一个长度为 3 的数组,[0, 0, 0]

  3. 找到下标 101 - 99 = 2,将其值置为 1,得 [0, 0, 1]

    找到下标 99 - 99 = 0,将其值置为 1,得 [1, 0, 1]

    找到下标 99 - 99 = 0,将其内值加 1,得 [2, 0, 1]

    找到下标 100 - 99 = 1,将其值置为 1,得 [2, 1, 1]

    可以看到,优化后的算法用到的数组长度为 3,而优化前的数组长度为 102

  4. 遍历 [2, 1, 1]

    插入 2 个 99 + 0 = 99,得 [99, 99]

    插入 1 个 99 + 1 = 100,得 [99, 99, 100]

    插入 1 个 99 + 2 = 101,得 [99, 99, 100, 101]

javascript代码

function countSort(arr) {
    const max = getMax(arr), // 数组中最大值
          min = getMin(arr), // 数组中最小值,以其作为基数
          bucketLen = max - min + 1
          bucket = new Array(bucketLen)
    let sortedIndex = 0

    for (let i = 0; i < arr.length; i++) {
        const index = arr[i] - min // 插入位置的下标
        if (!bucket[index]) {
            bucket[index] = 0
        }
        bucket[index]++
    }

    for (let j = 0; j < bucketLen; j++) {
        while(bucket[j] > 0) {
            arr[sortedIndex++] = min + j
            bucket[j]--
        }
    }

    return arr
}

// 获取数组最大值
function getMax (arr) {
    let max = arr[0]

    arr.forEach(e => {
        max = e > max ? e : max
    })

    return max
}

// 获取数组最小值
function getMin (arr) {
    let min = arr[0]

    arr.forEach(e => {
        min = e < min ? e : min
    })

    return min
}

总结

01 复杂度及稳定性

排序算法时间复杂度(平均)时间复杂度(最坏)时间复杂度(最好)空间复杂度稳定性
计数排序O(n + k)O(n + k)O(n + k)O(k)稳定

其中 k 为数列不重复元素的个数

02 使用场景

  • 适用场景:元素为整数且排列密集
  • 不适用场景:元素存在小数或排列不密集
csp之模拟试题——2019 CSP——J 一棵二叉树如下图所示,若采用顺序存储结构,即用一维数组元素存储该二叉树中的结点(根结点的下标为1,若某结点的下标为i,则其左孩子位于下标2i处、右孩子位于下标2i+1处),则该数组的最大下标至少为( )。若输入的字符串长度为( ),那么输入的字符串跟输出的字符串相比,至多有36个字符不同。当n=100时,最坏情况下,与第12行的比较运算执行的次数最接近的是:( )。 阅读详情

相关推荐

chenchen题解:CSP-J2019第二次错题整理

下面是关于CSP-J2019的第二次错题整理: 解释:挨个试,对于每一个数x从二开始试,直到根号x #include<cstdio> using namespace std; int n, m; int a[100], b[100]; int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) a[i] = b[i] = 0; for (int i =

weixin_43403405的博客 1166

计数排序-C语言实现

非常详细的计数排序说明,C语言完全实现,加详细注释

serena_0916的博客 6513

十大经典排序算法-计数排序算法详解

一、什么是计数排序 1.概念 计数排序(Counting sort)是一种非基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中以达到排序的效果 2.算法原理 给定一组取值范围为0到9的无序序列:1、7、4、9、0、5、2、4、7、3、4,建立一个长度为10的计数数组,值初始化为0 遍历无序序列,将每个序列元素值对应的计数数组下标的元素加1 如:第一个序列元素为1,则计数数组中下标为1的元素加1 第二个序列元素为7,计数数组中下标为7的元素加1 继续遍历序列,当序列遍历完毕,

qq_35344198的博客 9602

每日一题&&学习笔记

典型的二分查找,在数组中找到目标值的条件是target==nums[pos],而如果找不到,返回它将会被按顺序插入的位置,条件为nums[pos-1]<target<=num[pos],最终将返回pos。综合我们的目标就是找出在一个有序数组中找第一个大于等于 target 的下标,就直接用二分查找即可,考虑一下边界问题,这个数在数组中最大和最小的情况都是返回left的值,因此最后可直接返回left的值。也可以定义变量ans赋值为数组长度,也可以考虑到边界的情况,直接返回ans即可。请必须使用时间复杂度为。

m0_73096516的博客 339

【算法】计数排序 + 各个排序算法的稳定性

之前介绍的排序算法: 【算法】插入排序——希尔排序+直接插入排序_Rinne’s blog-优快云博客 【算法】选择排序——堆排序+直接选择排序_Rinne’s blog-优快云博客 【算法】交换排序——快速排序+冒泡排序(更新了非递归冒泡以及优化)_Rinne’s blog-优快云博客 【算法】归并排序_Rinne’s blog-优快云博客 计数排序 计数排序是一个非基于比较的排序算法,该算法于1954年由Harold H. Seward提出 它的优势在于在对一定范围内的整数排序时,它的复杂

Rinne's blog 2779

C++排序算法之计数排序

计数排序 像快排、堆排、归并等排序算法都是基于比较的排序算法,时间复杂度最好情况也只能降到O(nlogn)。 计数排序是一种线性排序算法,不需要进行比较,时间复杂度为O(n)。(注意是计数排序不是基数排序,两者不同) 基本思想是:对于每个元素x,找出比x小的数的个数,从而确定x在排好序的数组中的位置。此算法需要辅助数组,是以空间换时间。 举例说明: 原始数组:arr

YF_Li123的博客 8763

计数排序算法

一文速学计数排序

chenchenchencl的博客 1801

经典排序—计数排序算法

一、前言 我们知道归并排序是一种高效的排序算法,在任何情况下时间复杂度都为O(nlogn)。但是,它需要用额外的内存空间来暂时储存归并过程中的元素,因此我们可以认为归并排序是以牺牲一部分内存空间为代价来获得时间的高效性。 相反,如果内存空间有限,我们就必须以牺牲时间为代价来保证空间不被过度使用。像上面所说的那样,在设计一个算法的过程中同时考虑时间复杂度和空间复杂度,并且在这两者中找到一个平衡点的过程我们把它称作时空权衡(time and space trade-off)。 在通常情况下,我

m0_58683072的博客 1413

【排序算法】—— 计数排序

排序(Sorting) 是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个关键字有序的序列。所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 排序算法,就是如何使得记录按照要求排列的方法。排序算法在很多领域得到相当地重视,尤其是在大量数据的处理方面。一个优秀的算法可以节省大量的资源。

2302_80243065的博客 1695

STM32 ST-LINK Utility 无法烧录程序的解决方法

当你打开STM32 ST-LINK Utility,硬件连接好st-link V2,打开了要烧写的文件,点那个Program verify烧录时, 如果出错了: Programming error @ 0x08000000! 我的方法是: 点你想要烧录那个HEX文件的小格,复制 然后去到你前面的文件的格子里,点粘贴: 成功! ...

wocute的博客 9523

Ansys Lumerical 2023 R1.2新功能实战:薄膜铌酸锂调制器仿真全流程解析

本文详细解析了Ansys Lumerical 2023 R1.2在薄膜铌酸锂电光相位调制器仿真中的最新功能与应用。通过实战演示,展示了从电极配置、电场计算到模式分析的全流程,重点介绍了各向异性介电常数支持和多物理场耦合优化等关键技术,助力开发者高效设计高性能光通信器件。

weixin_28454475的博客 1213

十大排序算法——计数排序

计数排序一. 计数排序介绍二. 计数排序基础版三. 计数排序改进版四. 优化最终版本_空间节省 一. 计数排序介绍 计数排序(Counting sort)是一种稳定的排序算法。计数排序使用一个额外的数组C,其中第i个元素是待排序数组A中值等于i的元素的个数。然后根据数组C来将A中的元素排到正确的位置。它只能对整数进行排序。 算法分析 当输入的元素是n 个0到k之间的整数时,它的运行时间是 O(n + k)。计数排序不是比较排序,排序的速度快于任何比较排序算法。 由于用来计数的数组C的长度取

8435

ArcGIS 10.2.2自带Python 2.7.5环境配置全攻略:从pip安装到gdal、arcpy调用

本文详细指导如何在ArcGIS 10.2.2自带的Python 2.7.5环境中进行高效配置。核心内容包括安装pip包管理器、部署gdal等关键地理数据处理库,并确保arcpy模块的无缝调用。通过解决路径配置与PyCharm集成问题,帮助用户在此经典环境中构建稳定、兼容的地理信息自动化工作流,有效连接ArcGIS桌面功能与Python脚本编程。

moon9的博客 768

排序算法 -计数排序

计数排序

shiyue 1466

ollama环境变量配置:修改ollama的数据路径(安装路径)

ollama安装模型,如果很大,会占用C盘空间,影响系统运行速度,通过设置环境变量,来改变ollama放目录的地址。

正经教主是个热衷于正经学习分享的教主。 1万+

每天一个优秀提示词学习收藏 - 文本去AI化(四)

宝子们,今天不藏私啦!我把这段时间四处搜罗、潜心钻研出来的文本去AI化Prompt 提示词大礼包双手奉上,这可都是能让你的 AI 创作水平原地起飞的干货!走过路过不要错过,赶紧码住,开启你的 AI 创作进阶之旅吧!

2450

排序算法之计数排序

计数排序(Counting sort)是一种稳定的线性时间排序算法。该算法于1954年由[哈罗德·H·西华德]提出。计数排序使用一个额外的数组𝐶,其中第i个元素是待排序数组𝐴中值等于𝑖的元素的个数。然后根据数组𝐶来将𝐴中的元素排到正确的位置。

rd_w_csdn的博客 1653

Python之美——Python2与Python3多版本共存

Python多版本共存的方法Python2、Python3共存的方法python2下载及环境变量配置第一步、打开Python官网,下载Python2第二步、python2环境变量配置测试结果 Python2、Python3共存的方法 方法如下: 1.先确保不同版本解释器的python.exe所在的路径在环境变量中 2.拷贝各自的python.exe并重命名即可 步骤(理解不了下面有图示): 1、首先你需要将不同的python版本安装,且都已经将跟版本的环境变量配置好了,python3和2的下载方式

chenchen5152的博客 3946

【十大排序算法】计数排序

数字在轻舞纷飞中,依次排列,如星辰般闪耀。

DC1020的博客 1152

从Chimera到ChimeraX:科研绘图升级指南,让你的论文配图更专业

本文详细介绍了从UCSF Chimera升级到ChimeraX的科研绘图指南,帮助研究者提升论文配图质量。ChimeraX在渲染引擎、大分子处理能力和动画功能上具有显著优势,特别适合生命科学和结构生物学领域。文章涵盖材质设置、专业配色、工作流程和期刊适配等核心技巧,助力产出出版级分子可视化图像。

weixin_33670786的博客 939

【ArcGIS遇上Python】批量提取多波段影像至单个波段

本案例基于ArcGIS python,将landsat影像的7个波段影像数据,批量提取至单个波段。

智慧空间实验室 2074

必学排序算法——计数排序

计数排序算法是必须掌握的一种基础算法,在一些比较出名的竞赛acm、蓝桥杯,并且在一些公司面试题中都可能会出现,而且作为简单题我们必须要拿下,所以我们要引起重视,下面让我们来深入了解计数排序算法。计数排序(Counting Sort)是一种非比较型整数排序算法,适用于一定范围内的整数排序。其基本思想是通过计数来确定每个值在数组中出现的次数,然后根据这些计数来确定每个元素在排序后数组中的位置。计数排序的时间复杂度为 O(n + k),其中 n 是待排序数组的长度,k 是待排序数组中的最大值与最小值之差,

ycs66的博客 1349

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

排序算法——计数排序详解

在排序的最终结果中,各元素的次序依赖于它们之间的比较。这类排序算法被称为比较排序。对于包含 nnn 个元素的输入序列来说,任何比较排序算法在最坏情况下都要经过至少 O(n log n)O(n\ log\ n)O(n log n) 次比较。 而一些排序算法是用运算而不是比较来确定排序顺序的,如计数排序、基数排序以及桶排序。因此,比较次数的下界 O(n log n)O(n\ log\ n)O(n log n) 对它们是不适用的。 下

W24的博客 2187

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Java实现计数排序算法详解及优化

计数排序(Counting Sort)是一种线性时间复杂度的排序算法,特别适用于数据范围有限的情况。它通过统计每个元素出现的次数,然后按照次数排序,从而实现排序。本文将详细讲解如何使用Java实现计数排序算法,并结合图解和实例代码,帮助您全面理解这一高级排序算法。同时,我们还将探讨计数排序的优化方法,以进一步提高其性能。计数排序通过统计每个元素出现的次数,然后利用这些计数值将元素放置在正确的位置,从而实现排序。为了更清晰地展示计数排序的过程,以下使用一个简单示例并分步骤图解:初始数组: 4, 2, 2, 8

捕风捉你 · 星桥API接入与大模型实战 933

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

计数排序算法详解

计数排序是一种非比较型整数排序算法,通过统计元素出现次数实现排序。算法步骤包括:确定数据范围、创建统计数组、统计元素频次、重构排序数组。时间复杂度为O(N+range),空间复杂度为O(range)。该算法在数据范围较小、重复元素多时效率高,但不适用于浮点数且空间消耗较大。当前实现为不稳定排序,若需稳定可改进为使用前缀和技巧。计数排序以空间换时间,在特定条件下能达到线性时间复杂度。

fantasy5_5的博客 1217
上一篇: 详解排序算法(三)之2种选择排序(简单选择排序、堆排序)
下一篇: Git——手贱删除stash如何恢复
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值