news 2026/5/26 8:59:03

【初阶数据结构与算法】八大排序之非比较排序(计数排序),一次性讲清!

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【初阶数据结构与算法】八大排序之非比较排序(计数排序),一次性讲清!

(一)计数排序 Countsort

(升序为例)开辟一个额外数组count用于存储待排数组中的元素个数,譬如待排数组为{2,2,3,3,5,5,5,6,3,1},这样1的个数有1个,存在count数组的第一位中,2有2个,存在count数组的第二位中,3有3个,存在count数组的第三位中,4有0个,存在count数组的第四位中,5有3个,存在count数组的第五位中,6有1个,存在count数组的第六位中。

arr中的数据是啥,就将它的个数存储到count对应下标的位置处

然后再根据count数组中存储的数据个数,依次将值拷贝回原数组中,1有1个,放回原数组中,占一个位置,2有2个,放回原数组中,挨着1占两个位置,3有3个,放回原数组中,挨着2占三个位置,4放回原数组中,挨着3占零个位置,5有3个,放回原数组中,挨着4占三个位置,6有一个,放回原数组中,挨着5占一个位置。

排好序后,原数组变成了{1,2,2,3,3,3,5,5,5,6},排升序完成。

(1)代码实现

void Countsort(int* arr,int n) { int* tmp = (int*)calloc(n,sizeof(int)); if(tmp == NULL) { return; } int* count = tmp; //找最大最小值 int max = arr[0]; int min = arr[0]; for(int i=1;i<n;i++) { if(arr[i]>max) max = arr[i]; if(arr[i]<min) min = arr[i]; } int range = max-min+1; //定义数组的长度 for(int i = 0;i<n;i++) { //让count数组相应下标处存储处理后的arr数组的数据的出现次数 count[arr[i]-min]++; } //让count数组中存储的个数显化为arr数组的排序 int j = 0; for(int i = 0;i<range;i++) { while(count[i]--) arr[j++] = i+min; } }

(2)细节理解

数组里存的数据不同,count数组的大小就不同,所以我们采用动态申请内存的方式创建数组。

要确定count数组的大小,就要知道arr中的数据范围是多少,因为count数组存储的是arr数组中各个数据的出现次数,找到arr数组数据的取值范围,就知道count数组需要记录多少个数据的出现次数,这个"多少个数据"就是count数组的大小。

所以我们找到arr数组中的max和min,通过max-min+1的方式来确定count数组的大小range。

接下来,遍历arr数组,前面我们说arr中的数据是啥,就将它的个数存储到count对应下标的位置处,但这句话是有问题的,假设数组arr为{103,102,109,105},我们能确定count数组的大小为109-102+1=8,那count数组的下标范围就为0-7,何来103/102/109/105呢?

所以,arr中数据要先处理一下,再看这个处理后的数据,处理后的数据是啥,就将它的个数存储到count数组对应下标的位置

处理的方式就是将arr数组中的数据先减去min。

arr为{103,102,109,105},处理后就变成了{1,0,7,3},这样count数组0-7的下标就能满足存储要求了,由于0-7范围内,arr只出现了1,0,7,3,还有一些数没有出现,但是count数组中已经为这些没有出现的数据创建了空间,所以这些空间里填的值应当为0,这也对应了为什么我们用calloc动态申请内存,calloc申请空间,并将空间全部初始化为0。

等到将count数组中存储的数据个数显化成arr中的数据时,遍历count数组,内嵌循环赋值,注意,由于count数组存储的数据个数,是处理后的数据的个数,那么再赋值回arr数组时,就需要将count的下标加上min。

(二)基数排序 Radixsort

基数排序(Radix Sort)是一种非比较型的排序算法,它通过逐位比较元素的每一位(从最低位到最高位)来实现排序。基数排序的核心思想是将整数按位数切割成不同的数字,然后按每个位数分别进行排序。

基数排序算法适用于对多个整数或者多个字符串进行升序或降序排序。

(三)桶排序 Bucketsort

桶排序(Bucket Sort)是一种分布式排序算法,它将待排序的元素分配到若干个桶(Bucket)中,然后对每个桶中的元素进行排序,最后将所有桶中的元素按顺序合并。

桶排序的核心思想是将数据分到有限数量的桶中,每个桶再分别排序(可以使用其他排序算法或递归地使用桶排序)。

后两者出现频率不高,此处不过多解释了。

——end——

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/26 8:58:18

基于java的角色扮演游戏剧本管理系统的设计与实现

基于java的角色扮演游戏剧本管理系统的设计与实现 一、项目概述本项目是一个基于SSM(SpringSpringMVCMyBatis)框架的角色扮演游戏剧本管理系统&#xff0c;旨在为游戏爱好者提供一个便捷的剧本管理和角色扮演活动组织平台。系统支持剧本信息管理、角色扮演活动组织、道具商城、…

作者头像 李华
网站建设 2026/5/26 8:57:01

STM32 CAN扩展帧过滤器配置踩坑记:为什么我的0x04FB2028报文收不到?

STM32 CAN扩展帧过滤器配置深度解析&#xff1a;从原理到实战避坑指南当你在调试STM32的CAN扩展帧通信时&#xff0c;是否遇到过这样的困惑&#xff1a;明明总线上有报文在传输&#xff0c;但你的MCU却像戴了耳塞一样充耳不闻&#xff1f;特别是当你需要过滤特定格式的扩展帧ID…

作者头像 李华
网站建设 2026/5/26 8:57:00

告别脚本搬家:一个LabVIEW项目里优雅管理MATLAB .m文件的完整方案

告别脚本搬家&#xff1a;LabVIEW与MATLAB混合开发的工程化实践在工业自动化与测试测量领域&#xff0c;LabVIEW和MATLAB的组合堪称黄金搭档。前者以图形化编程见长&#xff0c;擅长硬件交互和系统集成&#xff1b;后者则是算法开发的利器&#xff0c;拥有丰富的数学函数库和数…

作者头像 李华
网站建设 2026/5/26 8:52:13

鸿蒙原生开发深度解析:分布式能力为核心

在当今万物互联的时代,操作系统正从单设备向多设备协同演进,华为鸿蒙(HarmonyOS)应运而生,成为新一代分布式操作系统的代表。鸿蒙原生开发强调设备间的无缝协作,其中分布式能力是其核心支柱。本文将聚焦于鸿蒙原生开发的单一重点领域——分布式能力,深入剖析其原理、架构…

作者头像 李华
网站建设 2026/5/26 8:48:39

MCP 2026漏洞修复七步法:工控网关JWT令牌溢出RCE实战指南

1. 这不是普通补丁——MCP 2026漏洞的本质与为什么必须7步闭环MCP 2026不是CVE编号&#xff0c;也不是某个开源库的版本号&#xff0c;它是工业控制领域一个广泛部署的**多协议网关中间件平台&#xff08;Multi-Protocol Convergence Platform&#xff09;**在2026年3月发布的紧…

作者头像 李华
网站建设 2026/5/26 8:46:12

终极指南:如何一键修复Kindle电子书封面损坏问题

终极指南&#xff1a;如何一键修复Kindle电子书封面损坏问题 【免费下载链接】Fix-Kindle-Ebook-Cover A tool to fix damaged cover of Kindle ebook. 项目地址: https://gitcode.com/gh_mirrors/fi/Fix-Kindle-Ebook-Cover 你是否曾经打开Kindle&#xff0c;却发现精心…

作者头像 李华