数据结构与算法之排序算法-(计数,桶,基数排序)
排序算法是数据结构与算法中最基本的算法之一,其作用就是将一些可以比较大小的数据进行有规律的排序,而想要实现这种排序就拥有很多种方法~
📚 非线性时间比较类:
那么我将通过几篇文章,将排序算法中各种算法细化的,详尽的为大家呈现出来:
📕 插入类排序:数据结构与算法之排序算法-插入排序-CSDN博客
📖 直接插入排序
📖 希尔排序
📕 交换类排序:数据结构与算法之排序算法-快速排序(分治)-CSDN博客
📖 冒泡排序
📖 冒泡排序-优化
📖 快速排序(Hoare,挖坑法,前后指针法)
📖 快速排序-优化
📕 选择类排序:数据结构与算法之排序算法-选择排序-CSDN博客
📖 简单选择排序
📖 堆排序
📕 归并类排序:数据结构与算法之排序算法-归并排序-CSDN博客
📖 归并排序
📚 线性时间非比较类:
📕 非比较类排序:[本篇]
📖 计数排序
📖 桶排序
📖 基数排序
一、计数排序
稳定性:稳定
时间复杂度:O(n + m)
额外空间复杂度:O(n + m)
大家应该也注意到了,这次学习到的排序算法,不仅具有稳定性,时间复杂度竟然还趋近O(n)!这是相当快的一种排序算法了。
那么为什么它能达到这么优秀的时间复杂度呢?主要就是因为它并不需要对元素之间进行比较~那么有人可能就要发出疑问,不进行比较又如何知道元素与元素间的大小关系呢?
① 计数排序
📚 算法思想:
计数排序的基本思想:把原数组元素作为数组的下标,创建一个临时数组 arr,使得 arr 至少能将原数组中所有数据都存入数组中。
然后遍历原数组,将遍历到的元素与 arr 下标进行匹配,并使 arr[index]++,代表该数字出现的次数 +1,而将数组遍历结束后,arr 从 start 下标到 end 下标存储的数据正好由下标默认排序好了,并且数据也准确的存到了正确位置~
了解了计数排序的基本思想后,大家或许也知道了为什么它的速度如此之快,相应的,大家应该也能理解为什么它没有"快速排序","归并排序"那么实用了,那就是"额外空间复杂度太高"
⭐ 图示:

📖 代码示例:
public static void countingSort(int[] array) {int max = array[0];for (int i = 1; i < array.length; i++) {if (array[i] > max) {max = array[i];}}int[] arr = new int[max + 1];for (int i = 0; i < array.length; i++) {int index = array[i];arr[index]++;}int k = 0;for (int i = 0; i < arr.length; i++) {while (arr[i] != 0) {array[k] = i;arr[i]--;k++;}}}
② 计数排序(优化)
上述代码中,我们简单实现了计数排序,但是这样是有缺点的:
📕 当数组中元素过大:如 [5000,5005,5010],如果创建一个大小为 5011 的数组,那么浪费的空间就会特别大。
📕 当数组中存在负数:如 [1,2,3,-1],创建数组后,是搜索不到 ' -1 ' 下标的。
📚 算法思想:
在原来的基础上,同时算出数组中的最小值,创建一个大小为[max - min + 1]的数组,这样就能有效的降低额外空间的损耗。
并且放入和取出元素时,寻找的下标也相应变成 arr[index] - min ,这样就能够彻底避免访问下标小于0的非法访问。
📖 代码示例:
public static void countingSort(int[] array) {int max = array[0];int min = array[0];for (int i = 1; i < array.length; i++) {if (array[i] > max) {max = array[i];}if (array[i] < min) {min = array[i];}}int[] arr = new int[max - min + 1];for (int i = 0; i < array.length; i++) {int index = array[i] - min;arr[index]++;}int k = 0;for (int i = 0; i < arr.length; i++) {while (arr[i] != 0) {array[k] = i + min;arr[i]--;k++;}}}
③ 效率测试

顺便一提,快速排序达到的速度为40ms左右,归并排序达到的速度为30ms左右~
二、桶排序
稳定性:稳定
时间复杂度:O(n)
额外空间复杂度:O(m)
上面的计数排数,很快倒是很快,但是它也有相应的缺点
📕 无法对浮点型数据进行排序,因为无法通过浮点型数据查找对应下标

这个算法属于计数排序的一种升级版,它的思想和计数排序类似,也是通过数据的值进行分类。
但它和计数排序也有些不同:
📕 它并没有通过数据的值来直接对应下标,而是通过创建一些"桶",并且为它们设定"区间",从而通过数据查找对应区间,这样就能够避免"浮点数非法查找下标"的问题了。
① 桶排序
📚 算法思想:
桶排序的基本思想:根据原数组的最大值 max 和最小值 min 来划分区间,由这些区间来创造一些"桶"。而每一个桶代表一个区间范围,里面可以承载一个或多个元素。
创建好"桶"后,遍历原数组,将数组中的数据放到对应区间的桶中,然后再分别将桶中的元素排序,这样排好序后,就能够得到我们最终想要的有序数组了。
⭐ 图示:

📖 代码示例:
public static double[] bucketSort(double[] array) {//取最大值和最小值,并求出差值int len = array.length;double max = array[0];double min = array[0];for (int i = 1; i < len; i++) {max = Math.max(array[i], max);min = Math.min(array[i], min);}double d = max - min;//创建桶int bucketNum = len;ArrayList<LinkedList<Double>> bucketList = new ArrayList<LinkedList<Double>>(bucketNum);for(int i = 0;i < bucketNum;i++){bucketList.add(new LinkedList<Double>());}//将数组元素放入桶中for(int i = 0;i < len;i++){int num = (int)((array[i] - min) * (bucketNum - 1) / d);bucketList.get(num).add(array[i]);}//对每个桶进行排序for(int i = 0;i < bucketList.size();i++){Collections.sort(bucketList.get(i));}double[] sortArr = new double[len];int index = 0;for(LinkedList<Double> list:bucketList){for(double element: list){sortArr[index++] = element;}}return sortArr;}

三、基数排序
稳定性:稳定
时间复杂度:O(n * k)
额外空间复杂度:O(n * k)
① 基数排序
📚 算法思想:
基数排序的基本思想:基数排序的算法思想是,将整数按照位数分别切割成不同的数字。
当每次将数组中的数据按位数分割结束后,分别放入以位数为单位的"桶"中。
然后遍历桶,按照顺序将元素取出,再重新进行分割,入桶等操作,直到分割位数的次数达到了数组中位数最高的元素的限制,排序结束。
📖 代码示例:
public static int[] radioSort(int[] arr) {if(arr == null || arr.length < 2) return arr;int n = arr.length;int max = arr[0];// 找出最大值,计算最大值是几位数for (int i = 1; i < n; i++) {if(max < arr[i]) max = arr[i];}int num = 1;while (max / 10 > 0) {num++;max = max / 10;}// 创建10个桶ArrayList<LinkedList<Integer>> bucketList = new ArrayList<>(10);for (int i = 0; i < 10; i++) {bucketList.add(new LinkedList<Integer>());}// 进行排序for (int i = 1; i <= num; i++) {for (int j = 0; j < n; j++) {int radio = (arr[j] / (int)Math.pow(10,i-1)) % 10;bucketList.get(radio).add(arr[j]);}int k = 0;for (int j = 0; j < 10; j++) {for (Integer t : bucketList.get(j)) {arr[k++] = t;}}}return arr;}
那么这篇关于计数排序,桶排序,基数排序的文章到这里就结束啦,作者能力有限,如果有哪里说的不够清楚或者不够准确,还请各位在评论区多多指出,我也会虚心学习的,我们下次再见啦
相关文章:
数据结构与算法之排序算法-(计数,桶,基数排序)
排序算法是数据结构与算法中最基本的算法之一,其作用就是将一些可以比较大小的数据进行有规律的排序,而想要实现这种排序就拥有很多种方法~ 📚 非线性时间比较类: 那么我将通过几篇文章,将排序算法中各种算法细化的&a…...
Word正文中每两个字符之间插入一个英文半角空格
Word正文中每两个字符之间插入一个英文半角空格 修改前 修改后 替换方法 快捷键 Ctrl H 唤出查找和替换界面依次输入上述内容全部替换即可 参考链接 【【2025年3月】计算机二级MS Office 2016 真题讲解视频打卡】 【精准空降到 25:27】...
把 DeepSeek1.5b 部署在显卡小于4G的电脑上
这里写自定义目录标题 介绍准备安装 Ollama查看CUDA需要版本安装CudaToolkit检查Cuda是否装好设置Ollama环境变量验证是否跑在GPU上ollama如何导入本地下载的模型安装及配置docker安装open-webui启动open-webui开始对话 调整gpu精度 介绍 Deepseek1.5b能够运行在只用cpu和gpu内…...
A4988一款带转换器和过流保护的 DMOS 微步驱动器的使用方式
A4988是一款带转换器和过流保护的 DMOS 微步驱动器,用于驱动双极步进电动机。它支持全、半、1/4、1/8 及 1/16 步进模式,输出驱动性能可达 35 V 及 2 A。其特点包括简单的步进和方向控制接口、可调电位器调节最大电流输出、自动电流衰减模式检测/选择以及…...
一口井深7米,一只蜗牛从井底往上爬每天爬3米掉下去1米,问几天能爬上井口?
一个井深7米,一只蜗牛从井底往上爬每天爬3米掉下去1米,问几天能爬上井口? 1. 通用解法 构建一个通用的解法,适用于任何井深和蜗牛的爬升、下滑距离。 问题描述: 井深为 H H H 米。蜗牛每天向上爬升 U U U 米。每…...
Asp.Net Core MVC 中级开发教程
Asp.Net Core MVC 中级开发教程 一、Asp.Net Core Mvc 区域使用 ASP.NET Core MVC的Areas使用整理 - 天马3798 - 博客园 二、Asp.Net Core 路径处理 Asp.Net Core Web相对路径、绝对路径整理 Asp.Net Core获取当前上下文对象 三、Asp.Net Core 服务使用和封装 四、Asp.Net …...
Windows上安装Go并配置环境变量(图文步骤)
前言 1. 本文主要讲解的是在windows上安装Go语言的环境和配置环境变量; Go语言版本:1.23.2 Windows版本:win11(win10通用) 下载Go环境 下载go环境:Go下载官网链接(https://golang.google.cn/dl/) 等待…...
C++效率掌握之STL库:string底层剖析
文章目录 1.学习string底层的必要性2.string类对象基本函数实现3.string类对象的遍历4.string类对象的扩容追加5.string类对象的插入、删除6.string类对象的查找、提取、大小调整7.string类对象的流输出、流提取希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力…...
【Erdas实验教程】004:影像镶嵌拼接
文章目录 一、实验目标二、实验数据三、实验过程一、实验目标 掌握具有坐标系且有重叠的多个影像的镶嵌。 二、实验数据 本实验数据为2景landsat TM影像和1景mss影像,如下所示: 数据获取方式:订阅专栏后,从私信查收。 三、实验过程 (1)启动镶嵌工具 在erdas中,常用…...
SpringMVC 请求参数接收
目录 请求 传递单个参数 基本类型参数传递 未传递参数 ?传递参数类型不匹配 传递多个参数 传递对象 后端参数重命名 传递数组 传递集合 传递JSON数据 JSON是什么 JSON的优点 传递JSON对象 获取URL中的参数 文件上传 在浏览器与程序进行交互时,主要…...
[高等数学]换元积分法
一、知识点 (一) 第一类换元法 定理1 设 f ( u ) f(u) f(u) 具有原函数, u φ ( x ) u\varphi(x) uφ(x) 可导,则有换元公式: ∫ f [ φ ( x ) ] φ ′ ( x ) d x [ ∫ f ( u ) d u ] u φ ( x ) . \int f[\varphi(x)]\varphi (x)dx[\int f(u)du]…...
Redis简介、常用命令及优化
文章目录 一、关系数据库??与非关系型数据库概述 1. 关系型数据库2. 非关系型数据库3.关系数据库与非关系型数据库区别 二、Redis简介 1.Redis的单线程模式2.Redis 优点3.Redis 缺点 三、安装redis四、Redis 命令工具五、Redis 数据库常用命令六、Redis 多数据库常用命令七、…...
大模型训练为什么依赖GPU
近年来,随着人工智能技术的飞速发展,特别是深度学习领域的进步,大模型的训练逐渐成为研究和工业界的热点。作为大模型训练中的核心硬件,GPU(图形处理单元)扮演了至关重要的角色。那么,为什么大模…...
帕金森病与三叉神经痛的基因关联分析
帕金森病(Parkinsons Disease, PD)和三叉神经痛(Trigeminal Neuralgia, TN)是两种不同的神经系统疾病,前者主要影响运动功能,而后者则表现为剧烈的面部疼痛。尽管这两种疾病在临床表现上有显著差异…...
【Android开发】华为手机安装包安装失败“应用是非正式版发布版本,当前设备不支持安装”问题解决
问题描述 我们将Debug版本的安装包发送到手机上安装,会发现华为手机有如下情况 解决办法 在文件gradle.properties中粘贴代码: android.injected.testOnlyfalse 最后点击“Sync now”,等待重新加载gradle资源即可 后面我们重新编译Debug安装…...
栈与队列(C语言版)
文章目录 栈与队列1. 栈基本操作实现(基于链表)代码运行结果 应用场景 2. 队列基本操作实现代码运行结果 应用场景 栈与队列 1. 栈 栈是一种操作受限的线性结构。操作受限体现在,栈只能在一端添加和删除元素,符合后进先出 ( LIFO ) 的特性,…...
stl里的deque 中控map 假如用完了,该如何处理
在 C 的标准模板库(STL)中,std::deque(双端队列)使用一种分段连续的存储结构,通过一个中控器(通常称为中控 map)来管理多个固定大小的存储块(缓冲区)。当这个…...
Git GUI设置中文的方法及使用
链接: Git Bash和Git GUI设置中文的方法 链接: Git 基本操作...
代码书写常用快捷建
唤出剪切板 Windows 系统 :Win V Mac 系统: 在 Mac 电脑上,可以点击桌面菜单栏中的 “编辑”,在下拉菜单中选择 “显示剪贴板” 来打开剪贴板。 跳转和撤回跳转 在vscode软件中可以通过ctrl+鼠标左键可以进行跳转…...
MySQL 索引失效处理:原因分析与优化实战
MySQL 索引失效处理:原因分析与优化实战 MySQL 索引失效处理:原因分析与优化实战引言一、什么是索引失效?二、索引失效的常见原因2.1 查询条件中使用函数或表达式示例:原因: 2.2 数据类型不匹配示例:原因&a…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
