数据结构——lesson13排序之计数排序

💞💞 前言

hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹
在这里插入图片描述

💥个人主页:大耳朵土土垚的博客
💥 所属专栏:数据结构学习笔记 、排序算法合集
💥对于数据结构顺序表、链表、堆以及排序有疑问的都可以在上面数据结构专栏和排序合集专栏进行学习哦~ 有问题可以写在评论区或者私信我哦~

前面我们学习过七种排序——直接插入排序、希尔排序、直接选择排序、堆排序、冒泡排序、快速排序和归并排序,它们都是通过两数之间进行比较来排序的,今天我们就来学习非比较排序中的计数排序🥳🥳🥳

1.计数排序

基本思想

  1. 统计相同元素出现次数
  2. 根据统计的结果将序列回收到原来的序列中

我们这里利用malloc开辟一个数组来统计相同元素出现的次数,用该数字下标表示相同元素,下标对应的值来统计次数
图示如下:
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
void CountSort(int* a, int n)
{//开辟数组int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");return;}//将tmp数组的值初始化为0for (int i = 0; i < n; i++){tmp[i] = 0;}//遍历afor (int i = 0; i < n; i++){//tmp下标对应值要++tmp[a[i]]++;}//拷贝回元素组aint j = 0;//记录a下标for (int i = 0; i < n; i++){while (tmp[i]--){a[j++] = i;}}free(tmp);
}
int main()
{int a[] = { 1,3,3,9,7,5,8,7,6 };printf("排序前:");for (int i = 0; i < 9; i++){printf("%d ", a[i]);}printf("\n");CountSort(a, 9);printf("排序后:");for (int i = 0; i < 9; i++){printf("%d ", a[i]);}printf("\n");return 0;
}

结果如下:
在这里插入图片描述

🥲我们仔细观察发现我们开辟tmp数组的大小是n:
int* tmp = (int*)malloc(sizeof(int) * n);
而数组a里面有九个数,也就是tmp大小为9,下标最大也就是8,那么当a中出现比8大的数9时应该怎么计数呢?就不可以计数了,所以出错了;
✨✨那么我们应该开辟多大的数组呢?应该根据什么来开辟才可以呢?
根据a数组最大最小值之差来开辟好像可以,a数组之间的范围就可以作为判断标准;但是这次我们得考虑得全面一点,如果a数组是这样得:a[] = {45,43,36,50,49,44,47}这些呢?那我们岂不是要开辟50个int大小的数组才可以有这么大的下标,如果是考虑范围就是最大50-最小36 = 14,更不可以了;
✨✨解决办法
利用相对值,还是开辟最大-最小的范围大小数组,然后最后拷贝数据的时候让下标+最小的数即可:
代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
void CountSort(int* a, int n)
{//求a数组最大最小差的范围int small = a[0];int big = a[0];for (int i = 1; i < n; i++){//求最大值if (a[i] > big){big = a[i];}//求最小值if (a[i] < small){small = a[i];}}//范围int gap = big - small;//比如0~4,差就是4,但是对应开辟的大小得是5,0~4有五个数//开辟数组int* tmp = (int*)malloc(sizeof(int) * (gap+1));if (tmp == NULL){perror("malloc fail");return;}//将tmp数组的值初始化为0for (int i = 0; i < gap+1; i++){tmp[i] = 0;}//遍历afor (int i = 0; i < n; i++){//tmp下标(a数组对应值-small)对应值要++tmp[a[i]-small]++;}//拷贝回元素组a,记得+samllint j = 0;//记录a下标for (int i = 0; i < gap+1; i++){while (tmp[i]--){a[j++] = i + small;}}free(tmp);
}
int main()
{int a[] = { 1,3,3,9,7,5,8,7,6 };printf("排序前:");for (int i = 0; i < 9; i++){printf("%d ", a[i]);}printf("\n");CountSort(a, 9);printf("排序后:");for (int i = 0; i < 9; i++){printf("%d ", a[i]);}printf("\n");return 0;
}

结果如下:
在这里插入图片描述
当int a[] = {45,43,36,50,49,44,47}时结果如下:
在这里插入图片描述
可以发现,计数排序成功啦~🥳🥳🥳

2.计数排序复杂度分析

2.1空间复杂度

我们根据上述代码实现可以知道计数排序开辟了大小为gap的数组,而gap对应的是最大与最小值的差也就是范围,所以其空间复杂度应该为O(gap);

2.2时间复杂度

时间复杂度:
①求数组a最大最小值时遍历了一遍数组a,次数为n;
②初始化tmp数组为0时遍历了数组tmp,次数为gap;
③统计下标出现次数时遍历数组a,次数为n;
④拷贝回原数组时,遍历了数组tmp,次数为gap;
所以其时间复杂度应该是n+gap+n+gap,简化为O(n+gap);

3.计数排序缺陷分析

前面我们学习的七大排序,时间复杂度最好也要O(n*logn);
而计数排序时间复杂度却可以达到O(n);
俗话说金无足赤,人无完人;计数排序达到这么好的时间复杂度其对应的缺陷也是非常明显的:
💥 缺陷1:依赖数据范围,适用于范围集中的数组
💥 缺陷2:只能用于整形(因为使用数组下标来统计)
所以计数排序使用的条件是非常苛刻的

4.结语

计数排序的关键在于理解并运用它的思想, 以上就是计数排序的介绍与实现啦~,完结撒花 ~🥳🥳🎉🎉🎉

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

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

相关文章

基于单片机锂电池电量检测数码管显示系统设计

**单片机设计介绍&#xff0c;基于单片机锂电池电量检测数码管显示系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机锂电池电量检测数码管显示系统设计的主要目标是实时、准确地检测锂电池的电量&#xff0c;并…

【python】常用函数汇总(持续更新……)

文章目录 【numpy.exp()】返回e的幂次方&#xff0c;e是一个常数为2.71828【np.dot()】矩阵相乘【np.linalg.inv()】矩阵求逆 【numpy.exp()】返回e的幂次方&#xff0c;e是一个常数为2.71828 举例&#xff1a;numpy.exp() 【np.dot()】矩阵相乘 【要点】 1、前者的列数后者…

浅谈Spring体系的理解

浅谈Spring知识体系 Spring Framework架构图Spring家族技术生态全景图XMind汇总 本文不涉及细节&#xff0c;主要回答两个问题&#xff1a; Spring家族技术生态全景图有哪些Spring Framework架构下每个模块有哪些东西&#xff0c;以及部分模块之间的关联关系 Spring Framework架…

iOS - Runtime - Class的结构

文章目录 iOS - Runtime - Class的结构前言1. Class的结构1.1 Class的结构1.1.1 objc_class1.1.2 class_rw_t1.1.3 class_ro_t 1.2 class_rw_t和class_ro_t的区别1.3 class_rw_t和class_ro_t的关系1.3.1 分析关系1.3.2 原因 1.4 method_t1.4.1 Type Encoding1.4.2 types说明1.4…

AJAX-项目优化(目录、基地址、token、请求拦截器)

目录管理 基地址存储 在utils/request.js配置axios请求基地址 作用&#xff1a;提取公共前缀地址&#xff0c;配置后axios请求时都会baseURLurl 填写API的公共前缀后&#xff0c;将js文件导入到html文件中 <script src"../../utils/request.js"></script&…

深度学习算法概念介绍

前言 深度学习算法是一类基于人工神经网络的机器学习方法&#xff0c;其核心思想是通过多层次的非线性变换&#xff0c;从数据中学习表示层次特征&#xff0c;从而实现对复杂模式的建模和学习。深度学习算法在图像识别、语音识别、自然语言处理等领域取得了巨大的成功&#xf…

STM32的IAP技术,BootLoader

来源 三种下载方式&#xff1a; 1、ICP&#xff1a;ST-Link, 2、ISP: FlyMcu, 3、IAP IAP简介 IAP技术的核心在于BootLoader程序的设计&#xff0c;这段程序预先烧录在单片机中&#xff0c;正常的APP程序可以使用BootLoader程序中的IAP功能写入&#xff0c;也可以两部分代码一…

docker使用教程

寒假用了docker 2个月没用 结果还重新安装docker 忘了怎么用 为了免得以后忘写下下面内容 # If you dont have a docker installed, youll need to install docker curl -s https://get.docker.com/ | sh # Use pip to install docker-compose pip install docker-compose…

排序第五篇 归并排序

一 简介 归并排序(Merge Sort) 的基本思想是&#xff1a; 首先将待排序文件看成 n n n 个长度为1的有序子文件&#xff0c; 把这些子文件两两归并&#xff0c; 得到 n 2 \frac{n}{2} 2n​ 个长度为 2 的有序子文件&#xff1b; 然后再把这 n 2 \frac{n}{2} 2n​ 个有序的子…

EI期刊和EI会议有哪些不同?别再傻傻分不清

EI工程索引是综合性检索机构&#xff0c;是三个著名学术检索系统之一&#xff0c;EI工程索引也分为EI期刊和EI会议&#xff0c;那么两者有哪些不同&#xff1f;作者又该如何选&#xff1f;本文系统分享一下相关的知识&#xff0c;仅供学术人员参考&#xff1a; 第一、文章质量不…

2014年认证杯SPSSPRO杯数学建模A题(第二阶段)轮胎的花纹全过程文档及程序

2014年认证杯SPSSPRO杯数学建模 A题 轮胎的花纹 原题再现&#xff1a; 轮胎被广泛使用在多种陆地交通工具上。根据性能的需要&#xff0c;轮胎表面常会加工出不同形状的花纹。在设计轮胎时&#xff0c;往往要针对其使用环境&#xff0c;设计出相应的花纹形状。   第二阶段问…

南京观海微电子---Vitis HLS的工作机制——Vitis HLS教程

1. 前言 Vitis HLS&#xff08;原VivadoHLS&#xff09;是一个高级综合工具。用户可以通过该工具直接将C、 C编写的函数翻译成HDL硬件描述语言&#xff0c;最终再映射成FPGA内部的LUT、DSP资源以及RAM资源等。 用户通过Vitis HLS&#xff0c;使用C/C代码来开发RTL IP核&#x…

前端优化gzip

gzip是GNUzip的缩写&#xff0c;是一种文件的压缩格式&#xff08;也可以说是若干种文件压缩程序&#xff09;&#xff0c;类似的压缩格式还有compress&#xff08;webpack&#xff09;&#xff0c;deflate等 主要用于组件的压缩 压缩的话主要分为两种&#xff0c; 服务器在…

TCP网络协议栈和Posix网络部分API总结

文章目录 Posix网络部分API综述TCP协议栈通信过程TCP三次握手和四次挥手&#xff08;看下图&#xff09;三次握手常见问题&#xff1f;为什么是三次握手而不是两次&#xff1f;三次握手和哪些函数有关&#xff1f;TCP的生命周期是从什么时候开始的&#xff1f; 四次挥手通信状态…

强化基础-Java-泛型基础

什么是泛型&#xff1f; 泛型其实就参数化类型&#xff0c;也就是说这个类型类似一个变量是可变的。 为什么会有泛型&#xff1f; 在没有泛型之前&#xff0c;java中是通过Object来实现泛型的功能。但是这样做有下面两个缺陷&#xff1a; 1 获取值的时候必须进行强转 2 没有…

005 高并发内存池_CentralCache设计

​&#x1f308;个人主页&#xff1a;Fan_558 &#x1f525; 系列专栏&#xff1a;高并发内存池 &#x1f339;关注我&#x1f4aa;&#x1f3fb;带你学更多知识 文章目录 前言本文重点一、构建CentralCache结构二、运用慢开始反馈调节算法三、完成向CentralCache中心缓存申请四…

【linux】AMD GPU和NVIDIA GPU驱动安装

AMD GPUs - Radeon™ PRO W7900的驱动安装过程 要在Linux系统上安装AMD的Radeon™ PRO W7900显卡驱动程序&#xff0c;通常需要执行以下步骤。以下示例基于Ubuntu系统&#xff1b;其他Linux发行版的具体步骤可能有所不同。 1. 更新系统 打开一个终端窗口&#xff0c;并输入…

Thread 之start 和run 的区别

Java Thread 之start 和run 的区别 用start方法来启动线程&#xff0c;真正实现了多线程运行&#xff0c;这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程&#xff0c;这时此线程处于就绪&#xff08;可运行&#x…

自然语言处理3(NLP)—— 机器学习

1. 自然语言处理在机器学习领域的主要任务 自然语言处理&#xff08;NLP&#xff09;在机器学习领域中扮演着至关重要的角色&#xff0c;旨在使计算机能够理解、解释和生成人类语言。以下是NLP在机器学习领域中的主要任务及其分类方法&#xff1a; 1.1 按照功能类型分类 1.1.…

详解JAVA程序调优

目录 1.概述 2.命令 2.1.查看JAVA进程 2.2.查看虚拟机状态 2.3.查看线程的情况 3.工具 3.1.jconsole 3.2.jvisualVM 4.实战场景 1.概述 在实际工作中我们难免会遇见程序执行慢、线程死锁等一系列的问题&#xff0c;这时候就需要我们定位具体问题然后来解决问题了。所…