【数据结构入门】排序算法(5):计数排序

目录

1. 比较排序和非比较排序

2. 计数排序的原理

2.1 计数排序的弊端

3.代码复现

3.1 代码分析

3.2 排序核心

3.3 时间、空间复杂度


1. 比较排序和非比较排序

        比较排序是根据排序元素的具体数值比较来进行排序;非比较排序则相反,非比较排序例如:基数排序和计数排序,这两种排序方式虽然谐音类似,但是其实是完全不同的两种排序。

        首先基数排序是根据一个数字的某一位进行排序;而计数排序是根据某一个数字出现的次数来进行比较排序。

2. 计数排序的原理

①需要判断出整个原数组中最大的数字,例如是5,那么就需要创建一个0-5的数组(元素为6个)。

新创建的数组的下标表示该数字的值该数组的下标所对应的值就类似于该数字出现了几次

③遍历原始数组,如果遍历到某一个数字,那么新数组的对应位置的值就会+1;

④遍历完毕之后,对统计次数的数组进行排序即可;

排序的过程也非常巧妙,首先0下标的值是2,说明0出现了2次,1下标的值是0,说明没有1,2下标的值是2说明有两个2......我们直接对原数组进行覆盖即可。

2.1 计数排序的弊端

        例如需要将下面几个数进行计数排序,按照上面的原理,我们需要开辟一个0-5000(5001个数组元素)的数组,但是需要排序的数只有仅仅5个,这样一来,大量的数组空间会被浪费。

        从下图得知,最小的数是1000,也就是说0-1000这1000个数就没有必要为其准备空间了,所以只需要准备4000个空间就够了。

        此时数的存储是一个相对位置,例如1000存在数组下标为0的位置上,1005存在数组下标为5的位置上,1100存储在数组下标为100的位置上......5000存在数组下标为4000,计算方式a[i] - min,当前位置-最小值。

        所以说,比较稀疏的数进行排序的话,那么就会浪费大量连续空间。

3.代码复现

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>// 计数排序
void count_sort(int* arr, int size)
{// 选出最大值和最小值int max = arr[0];int min = arr[0];for (int i = 0; i < size; i++){if (arr[i] > max){max = arr[i];}if (arr[i] < min){min = arr[i];}}// 创建一个具体数量的数组int range = max - min + 1;// 0-9一共10个数int* countArr = (int*)malloc(sizeof(int) * range);memset(countArr, 0, range * sizeof(int));// 遍历原数组给countArr赋值,计数for (int i = 0; i < size; i++)// countArr下标是arr的值;其值是次数{int val = arr[i] - min; // 这里是相对位置,若只有0-4000个位置,1005就是5号位置,// 这里要arr[i] - min得到相对位置++countArr[val];}int index = 0;// 原数组的覆盖下标// 遍历countArr将原数组覆盖for (int j = 0; j < range; j++){// 计数数组的值是几就覆盖几次while (countArr[j]--){arr[index++] = j + min; // 将下标进行还原,之前是-min存入countArr的 }}free(countArr);
}int main()
{int a[] = { 3,5,4,1,7,9,8,5,0,5 };int size = sizeof(a) / sizeof(int);count_sort(a, size);for (int i = 0; i < size; i++){printf("%d ", a[i]);}return 0;
}

3.1 代码分析

①首先计算出原数组的最大最小值,最大值-最小值+1就是计数数组的长度。

②遍历原数组,原数组的值对应计数数组的下标,如果遍历到2,那么就是计数数组下标为2的值进行+1;

③遍历计数数组,将对应下标作为原数组的值,计数数组的值就是需要赋值的次数,例如上图的5,在计数数组中存储的方式是index = 5,val = 3,那么就是将5赋值原数组,赋值3次,结果如下图。

3.2 排序核心

        就是利用数组的下标将无序的数字分别放入对应的下标,从而实现有序,这里对于重复数字进行一个累加的过程,反作用于原数组就是赋值的次数,这样的排序类似于下图:

        利用连续的有序数组下标作为“柱子”,如果该数字为这个柱子的编号,那么这个柱子就套一个圈,每一个柱子套圈的个数其实就是该数字出现的次数,由于柱子的编号是连续且有序,其实在套圈的过程中,我们已经将数字排好序了,此时只需要将结果覆盖原数组即可。

        所以这个算法可以运用于,数据非常集中,有大量重复出现的数字的数组中。

3.3 时间、空间复杂度

        我们注意这里的时间复杂度,看代码我们可以发现遍历了一次原数组,这里时间复杂度是O(n),后面需要遍历计数数组,那么时间复杂度是O(range),那么最后的时间复杂度就是:

O(n + range)

空间复杂度,这里只需要一个range大的数组,所以这里是:

O(range)

(不是橘子哈)

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

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

相关文章

输入3.8V~32V 输出2A 的DCDC降压芯片SCT9320

同志们&#xff0c;今天来个降压芯片SCT9320。输入3.8V~32V&#xff0c;输出最高可以达到2A。0.8V的参考电压。500k的开关频率。一共八个引脚&#xff0c;两个NC&#xff08;为什么不做成六个引脚呢&#xff1f;&#xff09;。EN引脚悬空或者接到VIN都可以直接启动&#xff0c;…

C++类和对象详解(2);初识类的默认成员函数

1.类的默认成员函数默认成员函数就是用户没有显示实现&#xff0c;编译器会自动生成的成员函数称为默认成员函数。一个类我们不写的情况下编译器会默认生成以下的6个默认成员函数。&#xff08;1&#xff09;构造函数&#xff1a;主要完成初始化的工作&#xff08;2&#xff09…

PLC通信 Tpc客户端Socket

1.PLC通信 namespace _2.PLC通信 {public partial class Form1 : Form{public Form1(){InitializeComponent();}//连接//1.型号: 跟PLC沟通 使用哪个型号的PLC//2.IP 同上//3.机台号:同上//4.插槽号:同上Plc plc new Plc(CpuType.S71200, "192.168.25.80", 0, 1);pr…

Android 开发实战:从零到一集成 espeak-ng 实现中文离线 TTS(无需账号开箱即用)

简介 在移动应用开发中,语音合成(TTS)技术是提升用户体验的重要工具。然而,许多开发者在集成 TTS 时面临依赖网络、需注册账号、功能受限等问题。本文将带你从零开始,通过开源项目 espeak-ng,实现无需账号、开箱即用的中文离线语音播报。 文章将覆盖以下核心内容: esp…

直播APP集成美颜SDK详解:智能美妆功能的开发实战

在这个“颜值即正义”的时代&#xff0c;用户对直播APP的第一印象&#xff0c;往往来自主播的画面质量。高清的视频固然重要&#xff0c;但如果缺少自然美颜和智能美妆功能&#xff0c;观众体验就会大打折扣。于是&#xff0c;美颜SDK成了直播行业的“标配”。今天&#xff0c;…

C++内存管理:new与delete的深层解析

1. 引言在C的世界里&#xff0c;动态内存管理是一个核心话题。对于从C语言过渡到C的开发者来说&#xff0c;一个常见的困惑是&#xff1a;既然C语言的malloc和free依然可以在C中使用&#xff0c;为什么C还要引入new和delete这两个操作符&#xff1f;本文将深入探讨这两对内存管…

【AI开发】【前后端全栈】[特殊字符] AI 时代的快速开发思维

&#x1f680; AI 时代的快速开发思维 —— 以 Django Vue3 为例的前后端分离快捷开发流程 一、AI 时代的开发新思路 在 AI 的加持下&#xff0c;软件开发不再是“纯体力活”&#xff0c;而是 思维工具自动化 的协作。 过去&#xff1a;需求 → 设计 → 开发 → 测试 → 上…

Day24_【深度学习(3)—PyTorch使用—张量的创建和类型转换】

一、创建张量1.张量基本创建方式torch.tensor 根据指定数据创建张量 &#xff08;最重要&#xff09;torch.Tensor 根据形状创建张量, 其也可用来创建指定数据的张量torch.IntTensor、torch.FloatTensor、torch.DoubleTensor 创建指定类型的张量1.1 torch.tensor# 方式一&…

3-12〔OSCP ◈ 研记〕❘ WEB应用攻击▸利用XSS提权

郑重声明&#xff1a; 本文所有安全知识与技术&#xff0c;仅用于探讨、研究及学习&#xff0c;严禁用于违反国家法律法规的非法活动。对于因不当使用相关内容造成的任何损失或法律责任&#xff0c;本人不承担任何责任。 如需转载&#xff0c;请注明出处且不得用于商业盈利。 …

AI 大模型赋能智慧矿山:从政策到落地的全栈解决方案

矿山行业作为能源与工业原料的核心供给端&#xff0c;长期面临 “安全生产压力大、人工效率低、技术落地难” 等痛点。随着 AI 大模型与工业互联网技术的深度融合&#xff0c;智慧矿山已从 “政策引导” 迈入 “规模化落地” 阶段。本文基于 AI 大模型智慧矿山行业解决方案&…

Node.js 项目依赖包管理

h5打开以查看 一、核心理念&#xff1a;从“能用就行”到“精细化管理” 一个规范的依赖管理体系的目标是&#xff1a; 可复现&#xff1a;在任何机器、任何时间都能安装完全一致的依赖&#xff0c;保证构建结果一致。 清晰可控&#xff1a;明确知道每个依赖为何存在&#x…

洛谷P1835素数密度 详解

题目如下&#xff1a;这里面有部分代码比较有意思&#xff1a;1&#xff0c;为何开始先遍历&#xff0c;最终值小于50000&#xff1f;因为题目要求的右边与左边差小于 10^6 &#xff0c;所以最多有10^3个素数&#xff0c;所以保存里面的素数数量大于1000&#xff0c;而50000的化…

突破限制:FileCodeBox远程文件分享新体验

文章目录【视频教程】1.Docker部署2.简单使用演示3. 安装cpolar内网穿透4. 配置公网地址5. 配置固定公网地址在隐私日益重要的今天&#xff0c;FileCodeBox与cpolar的协同为文件传输提供了安全高效的解决方案。通过消除公网IP限制和隐私顾虑&#xff0c;让每个人都能掌控自己的…

以太网链路聚合实验

一、实验目的掌握使用手动模式配置链路聚合的方法掌握使用静态 LACP 模式配置链路聚合的方法掌握控制静态 LACP 模式下活动链路的方法掌握静态 LACP 的部分特性的配置二、实验环境安装有eNSP模拟器的PC一台&#xff0c;要求PC能联网。三、实验拓扑LSW1与LSW2均为S3700交换机。L…

autMan安装教程

一、安装命令 如果你系统没安装docker&#xff0c;请看往期教程 以下为通用命令 docker run -d --name autman --restart always -p 8080:8080 -p 8081:8081 -v /root/autman:/autMan --log-opt max-size10m --log-opt max-file3 hdbjlizhe/autman:latest解释一下以上命令&…

【无人机】自检arming参数调整选项

检查项目 (英文名)中文含义检查内容四旋翼建议 (新手 → 老手)理由说明All所有检查启用下面所有的检查项目。✅ 强烈建议勾选这是最安全的设置&#xff0c;确保所有关键系统正常。Barometer气压计检查气压计是否健康、数据是否稳定。✅ 必须勾选用于定高模式&#xff0c;数据异…

数字图像处理(1)OpenCV C++ Opencv Python显示图像和视频

Open CV C显示图像#include <iostream> #include <opencv2/opencv.hpp> using namespace cv;//包含cv命名空间 int main() {//imread(path)&#xff1a;从给定路径读取一张图片&#xff0c;储存为Mat变量对象Mat img imread("images/love.jpg");//named…

【芯片设计-信号完整性 SI 学习 1.2.2 -- 时序裕量(Margin)】

文章目录1. 什么是时序裕量&#xff08;Margin&#xff09;1. 背景&#xff1a;为什么需要数字接口时序分析2. 时钟周期方程3. Setup 裕量 (tMARGIN_SETUP)4. Hold 裕量 (tMARGIN_HOLD)5. 设计注意事项6. 实际应用场景2. 时序裕量的来源3. 测试方法(1) 眼图测试 (Eye Diagram)(…

AOP 切面日志详细

在业务方法上打注解package com.lib.service;Service public class BookService {LogExecution(description "查询图书")public Book query(int id) {return repo.findById(id);}LogExecution(description "借阅图书")public void borrow(int id) {// 模…

使用paddlepaddle-Gpu库时的一个小bug!

起初安装的是 paddlepaddle 2.6.1版本。 用的是Taskflow的快速分词以及ner快速识别&#xff1a;​​​​​​​seg_accurate Taskflow("word_segmentation", mode"fast") ner Taskflow("ner", mode"fast")但是使用不了Gpu。想使用Gp…