排序算法——计数排序

news2024/12/31 1:18:16

计数排序

以升序排序为例

文章目录

  • 计数排序
    • 什么是计数排序
    • 实现思路
    • 具体步骤
    • 实现代码
    • 时间复杂度和局限性
      • 时间复杂度
      • 局限性

什么是计数排序

  • 计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出
  • 基本思想:是对于给定的输入序列中的每一个元素x,确定该序列中值小于x的元素的个数(此处并非比较各元素的大小,而是通过对元素值的计数和计数值的累加来确定)。一旦有了这个信息,就可以将x直接存放到最终的输出序列的正确位置上。例如,如果输入序列中只有17个元素的值小于x的值,则x可以直接存放在输出序列的第18个位置上。当然,如果有多个元素具有相同的值时,我们不能将这些元素放在输出序列的同一个位置上,因此,上述方案还要作适当的修改。——百度百科

实现思路

  • 根据待排序列的最大值和最小值,向系统申请一块空间

  • 空间内每个位置就代表着待排序列最小值到最大值每个数据的映射

  • 遍历待排序序列,统计每个数据出现的次数,并记录于申请的空间内

  • 最后根据空间中记录的每个数据出现的次数,实现对待排序列的排序

具体步骤

  • 我们以数组{101,105,102,107,105,106}为例
  • 首先,我们遍历整个乱序序列,找到最大值max,最小值min,从而求出待排序列的数据范围range
for (int i = 0; i < numsSize; i++)
{
    if (nums[i] > max)
        max = nums[i];
    if (nums[i] < min)
        min = nums[i];
}

int range = max - min + 1;
  • 向内存中申请range * sizeof(数据类型)大小的空间,并将其初始化为0(这块空间记录的是range范围内每个数据出现的次数,因此初始值为0)
int* count = (int*)malloc(sizeof(int) * range);		//申请内存
memset(count, 0, range * sizeof(int));		//初始化为0

在这里插入图片描述

  • 遍历乱序序列,记录每个数据出现的次数,并记录到申请的空间中
  • 那么问题来了,我们怎么得到每个数据在申请的空间中的位置呢?由上面的分析可以得到吗,空间的第一个位置即下标0处代表着最小值min(例子中的101),102就是101后面的一个数,下标就是102-101 = 1,103就是101后面的第二个数,下标就是103-101 = 2…………,因此数据nums[i]在count中的位置就是nums[i] - min
for (int i = 0; i < numsSize; i++)
		count[nums[i] - min]++;

在这里插入图片描述

  • 由于申请的空间是range范围内从小到大的映射,这已经是一个升序序列,因此最后我们只需要根据空间中记录的每个数据出现的次数,将这些数据重新按顺序放到原序列中就可以实现升序排序了
int cur = 0;
for (int i = 0; i < range; i++)
{
    while (count[i]--)
        nums[cur++] = i + min;
}

在这里插入图片描述

实现代码

void CountSort(int* nums, int numsSize)
{
	int max = nums[0];
	int min = nums[0];

	for (int i = 0; i < numsSize; i++)
	{
		if (nums[i] > max)
			max = nums[i];
		if (nums[i] < min)
			min = nums[i];
	}

	int range = max - min + 1;
	int* count = (int*)malloc(sizeof(int) * range);
	memset(count, 0, range * sizeof(int));

	for (int i = 0; i < numsSize; i++)
		count[nums[i] - min]++;

	int cur = 0;
	for (int i = 0; i < range; i++)
	{
		while (count[i]--)
			nums[cur++] = i + min;
	}
    
    free(count);
}

时间复杂度和局限性

时间复杂度

  • 计数排序的时间复杂度为:O(N + K),其中N为待排序列元素个数,K为待排序列数据范围(即range)
  • 是线性的时间复杂度,快于任何比较排序算法

局限性

  • 计数排序只能对整数排序
  • 如果数据范围range过大,那么不适合用计数排序来排
    • 例如,要对5个数排序,但这20个数的数据范围是一千万,这样像内存申请的空间就会很大,从而造成空间浪费
  • range > NlogN时,计数排序的效率反而不如基于比较的排序算法,因为堆排序、希尔排序、快速排序、归并排序等排序时间复杂度的理论下限为O(NlogN)

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

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

相关文章

运算放大器(一):电压跟随器

一、电压跟随器 电压跟随器&#xff08;单位增益放大器、缓冲放大器或隔离放大器&#xff09;是一种电压放大倍数为 1 的运算放大器&#xff0c;能够将输入信号的电压放大到同样的幅度并输出&#xff0c;同时保持输入输出电阻不变&#xff08;电压跟随器的输入电阻很大&#x…

Python网络编程:socket包的用法

持续补充 1 网络编程 网络编程&#xff0c;主要用于两台或多台计算机之间的通信&#xff0c;也可以是同一台计算机内不同进程之间的通信。Socket套接字可以用来实现网络通信。关于Socket套接字&#xff0c;需要注意以下几点&#xff1a; Socket是网络通信中应用层和传输层之间…

安装numpy

pip install numpy1.21.6 -i https://mirrors.aliyun.com/pypi/simple/ 最外面的python.exe 是默认版本 下载包----第二种方式

调用有道API实现图片翻译

调用有道API实现图片翻译 1&#xff0e;作者介绍2&#xff0e;关于理论方面的知识介绍3&#xff0e;调用有道API实现图片翻译实验3.1官方代码与结果3.2解码3.3换行输出3.4 示例展示 1&#xff0e;作者介绍 周慧龙&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff…

心电图机原理及电路超详细讲解

心电图机原理及电路超详细讲解 心电图主要器件导联单极导联和双极导联威尔逊中心端加压导联胸导联 心电图机的结构电路框图介绍输入部分过压保护电路高频滤波电路低压保护及缓冲放大器屏蔽驱动电路导联选择起搏脉冲抑制与定标电路肌电滤波、时间常数电路、封闭电路与电极异常检…

【OC底层_消息发送与转发机制原理】

文章目录 前言动态类型动态绑定为何为动态语言&#xff1f; 什么是消息传递选择子SELIMPIMP和SEL的关系 消息发送1. 快速查找objc_msgSend()的执行流程objc_msgSend()深基核心逻辑及其参数解析源码解析消息发送的快速查找总结&#xff1a;objc_msgSend(receiver, sel, …)对于b…

接口测试Post请求提交数据的四种类型

常见的post提交数据类型有四种&#xff1a; 第一种&#xff1a;application/json 这是最常见的json格式&#xff0c;也是非常友好的深受小伙伴喜欢的一种&#xff0c;如下 {“input1”:“xxx”,“input2”:“ooo”,“remember”:false} 第二种&#xff1a;application/x-www…

【MySQL实战】笔记

1、MySQL的基本架构组成 MySQL的基本架构组成包括以下几个部分&#xff1a; 连接器&#xff08;Connection Manager&#xff09;&#xff1a;负责与客户端建立连接&#xff0c;并处理客户端发送的请求。连接器会验证客户端的身份、分配线程和缓存等资源&#xff0c;并将请求转…

pdf转excel怎么样格式不乱?这两个方法轻松转换!

PDF和Excel是广泛应用的文件格式&#xff0c;然而&#xff0c;将PDF转换为Excel时&#xff0c;常常面临格式混乱的问题。幸运的是&#xff0c;我们有记灵在线工具和Adobe Acrobat Pro软件这两个简单而有效的方法&#xff0c;可以帮助我们将PDF转换为Excel并保持格式整齐。本文将…

复旦微7045环境安装

Linux Petalinux 0.下载 更换下载源&#xff1a;https://blog.csdn.net/u012308586/article/details/102737950 更换中文&#xff1a;https://cloud.tencent.com/developer/article/2159346 1.配置 配置/bin/sh 由于 petalinux 用到的/bin/sh 命令都是 bash 的&#xff0c…

好用又强大的开源建站工具,配合上不同的模板与插件,可以很好地帮助你构建你心中的理想站点

作为一款强大易用的开源建站工具,配合上不同的模板与插件,可以很好地帮助你构建你心中的理想站点。它可以是你公司的官方网站,可以是你的个人博客,也可以是团队共享的知识库,甚至可以是一个论坛、一个商城。 控制台 控制台是一个 Halo 站点的后台管理系统,只有具有权限…

本周大新闻|visionOS SDK开放下载;Meta和三星停止芯片合作

本周XR大新闻&#xff0c;AR方面&#xff0c;visionOS 1.0系统和SDK发布&#xff1b;Meta和三星停止芯片合作&#xff0c;转而投向联发科&#xff1b;Karl Guttag评Vision Pro第二篇发布&#xff1b;Vision Pro眼球追踪细节。 VR方面&#xff0c;Vision Pro游戏空间边界为3米圆…

在CSDN的第1095天(3年),我收获了什么?

机缘 当初接触CSDN的时候是老师带进来的&#xff0c;那时候说人要有一个记录学习的习惯&#xff0c;可以记录很多东西&#xff0c;在后来看着老师的博客粉丝数和阅读数&#xff0c;哈哈哈&#xff0c;我心动了&#xff0c;于是就加了进来&#xff0c;记录点点滴滴。 于是开始…

使用Docker Swarm部署PXC+HAProxy高可用集群(三节点)

使用Docker Swarm部署PXCHAProxy高可用集群&#xff08;三节点&#xff09; 1. 部署规划 当前规划中&#xff0c;只启动一个HAProxy服务&#xff0c;主要用来做MySQL节点的负载均衡和代理&#xff0c;但是HAProxy可能会出现单点故障&#xff0c;后续需要启动多个HAProxy节点&…

【动态规划算法练习】day5

文章目录 一、309. 最佳买卖股票时机含冷冻期1.题目简介2.解题思路3.代码4.运行结果 二、714. 买卖股票的最佳时机含手续费1.题目简介2.解题思路3.代码4.运行结果 三、123. 买卖股票的最佳时机 III1.题目简介2.解题思路3.代码4.运行结果 四、188. 买卖股票的最佳时机 IV1.题目简…

ES6-Map()对象

Map是一个键值对的集合和Object类似&#xff0c;Object 结构提供了“字符串—值”的对应&#xff0c;Map 结构提供了“值—值”的对应&#xff0c;是一种更完善的 Hash 结构实现。Map做为构造函数&#xff0c;可以通过全局对象获取到需要通过new操作创建实例对象。 map与Objec…

移动端适配方案

文章目录 像素设备像素(物理像素)设备独立像素&#xff08;逻辑像素&#xff09;CSS像素像素之间的关系 分辨率设备分辨率逻辑分辨率 移动端开发分类自适应响应式视口布局视口&#xff08;layout viewport&#xff09;视觉视口&#xff08;visual layout&#xff09;理想视口&a…

数据结构-哈希-位图与布隆过滤器

位图与布隆过滤器 一&#xff0c;位图题目分析位图设计位图代码经典题目 二&#xff0c;布隆过滤器布隆过滤器概念布隆过滤器的插入布隆过滤器的结构布隆过滤器总结经典题目 三&#xff0c;哈希切割 一&#xff0c;位图 题目分析 &#x1f680;给40亿个不重复的无符号整数&am…

【UE 从零开始制作坦克】11-坦克炮塔机枪

效果 步骤 1. 复制一份坦克炮弹的蓝图&#xff0c;重命名为“MachineGunBullets”&#xff0c;作为坦克炮塔机枪子弹的蓝图 2. 打开“MachineGunBullets”&#xff0c;由于美M2勃朗宁重机枪的口径是12.7毫米&#xff0c;这里取12毫米&#xff0c;也就是1.2cm&#xff0c;半径是…

Stream流中Map方法的使用

map函数的作用就是针对管道流中的每一个数据元素进行转换操作。 主要有三种用法 一、Stream管道流map的基础用法 将集合中的每个字符串&#xff0c;全部转化成大写&#xff01; 不使用流 List<String> list Arrays.asList("Monkey", "Lion", &…