【算法】计数排序、桶排序、基数排序

算法系列八:非比较排序

一、计数排序

1.实现

1.1步骤

1.2代码

2.性质

2.1稳定性

2.1.1从前往后前始版:

2.1.2从后往前末始版:

2.2复杂度

2.2.1时间复杂度

2.2.2空间复杂度

二、桶排序

1.实现

1.1步骤

1.2代码

2.稳定性

三、基数排序

1.原理

2.代码


鸽巢原理

鸽子归巢,待排序数据归到有序组群中按大小归进有序组群来排数越大,归到的有序组就在越后的数越小,归到的有序组就在越前的

  • 如果有序组以一个元素一个元素划分的,实现的是元素组归巢排序,即计数排序
  • 如果有序组按范围多个元素为一组划分的,实现的是范围组归巢排序,即桶排序

一、计数排序

1.实现

1.1步骤

  1. 开辟数据范围内的所有元素都有各自对应的元素组巢穴,范围内一共有多少种个数据,就开辟每种个数据都有对应的多大的数组,比如90(max) - 10(min) = 80(种个数据)
  2. 归巢时,通过该数据-数据范围内的最小值得到所归巢的下标,然后在数组元素巢中计数表示归巢
  3. 因为巢内只有一种个数据直接就是有序的,所以所有数据归完巢在巢层面有序时所有数据就已经有序了,最后将它们按顺序地赶出巢加回去即得原来有序的数据


1.2代码

    public static void countSort(int[] array) {//1.求当前数据的最大值和最小值int minVal = array[0];int maxVal = array[0];for (int i = 1; i < array.length; i++) {if(array[i] < minVal) {minVal = array[i];}if(array[i] > maxVal) {maxVal = array[i];}}//2.根据数据最大值和最小值来确定元素组巢穴数组的大小int[] count = new int[maxVal-minVal+1];//3.遍历原来的数据进行归巢排序for (int i = 0; i < array.length; i++) {count[array[i]-minVal]++;}//4.将元素组巢穴里已排好序的数据按顺序写回arrayint index = 0;//重新表示array数组的下标for (int i = 0; i < count.length; i++) {while (count[i] > 0) {array[index] = i+minVal;index++;count[i]--;}}}
}

2.性质

2.1稳定性

每个数据都归到巢中完成有序时,根据巢中有序来的元素的计数个数,可以将巢改装成装每种个元素有序排的始位置,通过对应顺序遍历原数组将数据正确稳定地放在排好序的各自位置上,能实现稳定的排序,所以计数排序是稳定的排序

2.1.1从前往后前始版:

原本巢中装的是鸽子的计数数量,现在巢里面改装成装种个鸽子从前往后的起始位置进行排序:


2.1.2从后往前末始版:

 巢里面改装成装种个鸽子从后往前的起始位置进行排序:


2.2复杂度

2.2.1时间复杂度

找最大最小值确定范围种个数据遍历原数组用了n原数组数据每个去归巢用了n范围x种个元素巢每个去赶,所以时间复杂度为2n + x,即O(n+x)


2.2.2空间复杂度

范围x种个数据需要开辟x个元素巢的数组,所以空间复杂度为O(x)


二、桶排序

1.实现

1.1步骤

  1. 开辟数据范围内所有元素都有对应的范围数组组巢穴将所有数据入范围组巢穴先进行第一轮巢穴外的排好序,此时巢外已经有序了
  2. 再进行第二轮各自巢穴内的排好序,此时就巢外、巢内都有序所有数据都有序了
  3. 最后按顺序地将它们从数组巢中赶出即得有序的数据


1.2代码

    public static int[] bucketSort(int[] arr) {// 边界条件:空数组或单个元素直接返回if (arr.length <= 1) {return arr.clone();}// Step 1: 确定数据范围int minVal = Integer.MAX_VALUE;int maxVal = Integer.MIN_VALUE;for (int num : arr) {if (num < minVal) minVal = num;if (num > maxVal) maxVal = num;}// 处理所有元素相同的情况if (maxVal == minVal) {return arr.clone();}// Step 2: 初始化桶int bucketCount = (int) Math.sqrt(arr.length) + 1; // 桶数量=数组长度的平方根(经验值)double bucketRange = (double)(maxVal - minVal) / bucketCount;List<List<Integer>> buckets = new ArrayList<>(bucketCount);for (int i = 0; i < bucketCount; i++) {buckets.add(new ArrayList<>());}// Step 3: 元素分配到桶中for (int num : arr) {// 计算元素应该属于哪个桶int index = (int)((num - minVal) / bucketRange);// 处理最大值刚好落在最后一个桶外的情况if (index == bucketCount) index--;buckets.get(index).add(num);}// Step 4: 对每个桶内部排序for (List<Integer> bucket : buckets) {Collections.sort(bucket); // 使用内置排序算法,决定了桶排序的稳定性}// Step 5: 合并桶int[] sortedArr = new int[arr.length];int idx = 0;for (List<Integer> bucket : buckets) {for (int num : bucket) {sortedArr[idx++] = num;}}return sortedArr;}

2.稳定性

稳定性取决于在第二轮巢内开始排相同大小的元素时所用的排序方法是否具有稳定性


三、基数排序

1.原理

  1. 先进行个位排序,能实现个位一位数有序
  2. 个位有序下,再进行十位优先排序,能实现十位个位两位数有序
  3. 十个位有序下,再进行百位优先排序,能实现百位十位个位三位数有序


2.代码

    public static int[] radixSort(int[] arr) {if (arr.length <= 1) {return arr.clone();}// Step 1: 确定最大数的位数int maxNum = Integer.MIN_VALUE;for (int num : arr) {if (num > maxNum) maxNum = num;}// Step 2: 按每位进行计数排序(从低位到高位)int exp = 1; // 从个位开始while (maxNum / exp > 0) {// 初始化10个数字桶(0-9)List<List<Integer>> buckets = new ArrayList<>(10);for (int i = 0; i < 10; i++) {buckets.add(new ArrayList<>());}// 按当前位分配到桶中for (int num : arr) {int digit = (num / exp) % 10; // 提取当前位的数字buckets.get(digit).add(num);}// 重组数组int idx = 0;for (List<Integer> bucket : buckets) {for (int num : bucket) {arr[idx++] = num;}}exp *= 10; // 处理更高位}return arr;}

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

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

相关文章

JDK版本与Spring Boot版本之间对应关系

JDK&#xff08;Java Development Kit&#xff09;版本与Spring Boot版本之间存在一定的对应关系&#xff0c;选择合适的搭配对项目的稳定性、性能及功能实现至关重要&#xff0c;以下是详细介绍&#xff1a; 主要版本对应关系 Spring Boot版本发布日期支持的JDK版本备注3.2.…

如何检测Python项目哪些依赖库没有使用

要检测Python项目中哪些依赖库未被使用&#xff0c;可以采用以下方法&#xff1a; 1. 使用静态分析工具 vulture&#xff1a;静态分析工具&#xff0c;检测未使用的代码和导入 pip install vulture vulture your_project/pyflakes&#xff1a;检查未使用的导入语句 pip ins…

【智能指针】—— 我与C++的不解之缘(三十三)

一、智能指针的使用 还记得&#xff0c;在异常学习的时候&#xff0c;我们分析出了一个问题 double Divide(int x, int y) {if (y 0){throw string("the y is zero");}return (double)x / double(y); } void test(int x, int y) {int* arr new int[10];Divide(x,…

Hadoop+Spark 笔记 2025/4/21

读书笔记 定义 1. 大数据&#xff08;Big Data&#xff09; - 指传统数据处理工具难以处理的海量、高速、多样的数据集合&#xff0c;通常具备3V特性&#xff08;Volume体量大、Velocity速度快、Variety多样性&#xff09;。扩展后还包括Veracity&#xff08;真实性&#x…

femap许可不足如何解决

在复杂的工程仿真领域&#xff0c;Femap以其强大的功能和广泛的应用场景而备受青睐。然而&#xff0c;随着用户需求的增长和项目规模的扩大&#xff0c;Femap许可不足的问题逐渐凸显&#xff0c;成为了许多工程师和团队面临的挑战。本文将为您详细解析Femap许可不足的原因&…

【Microsoft Store 中的软件推荐】

目录&#xff1a; &#x1f600; TranslucentTB&#x1f600; Snipaste&#x1f600; Watt Toolkit&#x1f600; NVIDIA Control Panel&#x1f600; Typedown 微软应用商店中的软件会直接安装在C盘&#xff0c;所以&#xff0c;下面分享的这些是即超级好用&#xff0c;又占用…

AOSP Android14 Launcher3——RecentsView最近任务数据加载

最近任务是Launcher中的一个重要的功能&#xff0c;显示用户最近使用的应用&#xff0c;并可以快速切换到其中的应用&#xff1b;用户可以通过底部上滑停顿进入最近任务&#xff0c;也可以在第三方应用底部上滑进最近任务。 这两种场景之前的博客也介绍过&#xff0c;本文就不…

Flink介绍——实时计算核心论文之Flink论文

引入 通过前面的文章&#xff0c;我们梳理了大数据流计算的核心发展脉络&#xff1a; S4论文详解S4论文总结Storm论文详解Storm论文总结Kafka论文详解Kafka论文总结MillWheel论文详解MillWheel论文总结Dataflow论文详解Dataflow论文总结 而我们专栏的主角Flink正是站在前人的…

极狐GitLab CEO 柳钢受邀出席 2025 全球机器学习技术大会

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 2025 年 4 月 18 日至 19 日&#xff0c;2025 全球机器学习技术大会&#xff08;ML-Summit 2025&#xff09;在上海隆重举行。…

Linux Sed 深度解析:从日志清洗到 K8s 等12个高频场景

看图猜诗&#xff0c;你有任何想法都可以在评论区留言哦~ 摘要&#xff1a;Sed&#xff08;Stream Editor&#xff09;作为 Linux 三剑客之一&#xff0c;凭借其流式处理与正则表达式能力&#xff0c;成为运维场景中文本批处理的核心工具。本文聚焦生产环境高频需求&#xff…

C++ STL 容器简介(蓝桥杯适用精简版)

C的万能头文件是&#xff1a; #include <bits/stdc.h> 一、常用 STL 容器 1.vector&#xff08;动态数组&#xff09; #include<iostream> #include<string> #include <vector> #include <algorithm> // 包含排序所需的头文件 using namespa…

Java语言的进化:JDK的未来版本

作为一名Java开发者&#xff0c;我们正处在一个令人兴奋的时代&#xff01;Java语言正在以前所未有的速度进化&#xff0c;每个新版本都带来令人惊喜的特性。让我们一起探索JDK未来版本的发展方向&#xff0c;看看Java将如何继续领跑编程语言界&#xff01;&#x1f4aa; &…

不要使用Round函数保留小数位了

不要使用Round函数保留小数位了 如果你表格不需要保留公式&#xff0c;那么就不要使用Round函数保留小数位了。用Excel工作圈插件&#xff0c;可以轻松以数值形式保留小数位&#xff0c;且支持合并单元格、不连贯区域快速处理。 如下图&#xff0c;有文本&#xff0c;有跨行合并…

【C++】入门基础【下】

目录 一、缺省参数二、函数重载1. 函数类型不同2. 参数个数不同3、函数类型顺序不同 三、引用1、引用的概念和定义2、引用的功能2.1 功能1&#xff1a; 做函数形参&#xff0c;修改形参影响实参2.2 功能2&#xff1a; 做函数形参&#xff0c;减少拷贝&#xff0c;提高效率2.3 功…

git比较不同分支的不同提交文件差异

背景&#xff1a;只想比较某2个分支的某2次提交的差异&#xff0c;不需要带上父提交。 以commitA为基准&#xff0c;用commitB去比较差异 直接上代码&#xff1a; commitAxxxx1 commitBxxxx2 outputFile"output.txt"# 获取与第一个父提交的文件列表 filesA$(git di…

Linux内核之struct pt_regs结构

前沿 项目开发最近进行系统hook功能实现相关业务&#xff0c;主要在centos7和8系列环境开发下关功能。调研了相关知识点&#xff0c;发现在系统7和8上内核版本差别比较大&#xff0c;7-3.10.x系列版本&#xff0c;8-4.18.x系列版本。依据两个系统的内核情况根对应的内核符号表进…

《从混乱到有序:ArkUI项目文件结构改造指南》

在ArkUI开发的广袤天地里&#xff0c;构建一个清晰、有序的文件结构&#xff0c;是打造优质应用的关键。一个合理的文件结构&#xff0c;就像为开发者精心绘制的地图&#xff0c;在项目的各个阶段&#xff0c;都能提供明确的指引&#xff0c;让开发过程顺畅无阻。今天&#xff…

C#基于Sunnyui框架和MVC模式实现用户登录管理

C#基于Sunnyui框架和MVC模式实现用户登录管理 1 Controller1.1 UserManagementController.cs&#xff08;控制器入口&#xff09; 2 Model2.1 UserRepository.cs&#xff08;用户管理模型&#xff09;2.2 User.cs&#xff08;用户结构体&#xff09;2.3 SQLiteHelper.cs&#x…

自然语言处理(NLP)技术的实例

自然语言处理&#xff08;NLP&#xff09;技术在各个领域都有广泛的应用&#xff0c;以下是几个例子&#xff1a; 语音识别&#xff1a;通过NLP技术&#xff0c;计算机可以识别和理解语音指令&#xff0c;例如智能助手如Siri和Alexa就是通过语音识别技术实现与用户的交互。 机…

Spring Boot实战(三十六)编写单元测试

目录 一、什么是单元测试&#xff1f;二、Spring Boot 中的单元测试依赖三、举例 Spring Boot 中不同层次的单元测试3.1 Service层3.2 Controller 层3.3 Repository层 四、Spring Boot 中 Mock、Spy 对象的使用4.1 使用Mock对象的背景4.2 什么是Mock对象&#xff0c;有哪些好处…