时间复杂度接近O(n)的三种排序算法

1.桶排序

桶排序,顾名思义,会用到“桶”,核心思想是将要排序的数据分到几个有
序的桶里,每个桶内的数据再单独进行排序。桶内排完序之后,再把每个桶内的数据按照顺序依次
取出,组成的序列就是有序的了。

桶排序对要排序数据的要求是非常苛刻的。
首先,要排序的数据需要很容易就能划分成m个桶,并且,桶与桶之间有着天然的大小顺序。这样
每个桶内的数据都排序完之后,桶与桶之间的数据不需要再进行排序。

其次,数据在各个桶之间的分布是比较均匀的。如果数据经过桶的划分之后,有些桶内的数据非常
多,有些非常少,很不平均,那桶内数据排序的时间复杂度就不是常量级了。在极端情况下,如果
数据都被划分到一个桶内,那就退化为O(nlogn)的排序算法了。

桶排序比较适合用在外部排序中。所谓的外部排序就是数据存储在外部磁盘中,数据量比较大,内
存有限,无法将数据全部加载到内存中。
在这里插入图片描述

/*** 桶排序* 原地排序:否* 稳定排序:是* 空间复杂度:* 时间复杂度:O(n)*/
public class BucketSort {public static void main(String[] args) {int[] arr = { 1, 45, 32, 23, 22, 31, 47, 24, 4, 15 };bucketSort(arr);System.out.println(Arrays.toString(arr));}//存数区间0-9,10-19,20-29,30-39,40-49public static void bucketSort(int[] arr) {ArrayList bucket[] = new ArrayList[5];//初始化桶for(int i=0;i<bucket.length;i++) {bucket[i] = new ArrayList<Integer>();}//像桶内放入数据for(int i=0;i<arr.length;i++) {int index = arr[i]/10;bucket[index].add(arr[i]);}int index = 0;for(int i=0;i<bucket.length;i++) {bucket[i].sort(null);//对每个桶进行排序for(int j=0;j<bucket[i].size();j++) {arr[index++] = (int) bucket[i].get(j);}}}
}

2.计数排序

计数排序可以理解为是桶排序的一种特殊情况。当要排序的n个数据,所处的范围并不大的
时候,比如最大值是k,我们就可以把数据划分成k个桶。每个桶内的数据值都是相同的,省掉了桶
内排序的时间。

计数排序只能用在数据范围不大的场景中,如果数据范围k比要排序的数据n大很多,
就不适合用计数排序了。而且,计数排序只能给非负整数排序,如果要排序的数据是其他类型的,
要将其在不改变相对大小的情况下,转化为非负整数。
假定有原始数组A[8],它们分别是:2,5,3,0,2,3,0,3。数据范围从0-5

先用一个数组大小为6的数组C来存储在k值上数据有几个。
在这里插入图片描述

接着对数组顺序求和,C数组存储的数据就变成了,C[k]里存储小于等于分数k的的数据。
在这里插入图片描述

定义临时数组R,依次扫描数组原始数组A,将数据A入到R[C[k]]位置上,同时C[k]位置上的数据要减掉1,最后将R数组复制到原始数组A中。
在这里插入图片描述

/*** 计数排序* 原地排序:否* 稳定排序:是* 空间复杂度:O(k+n) k为数据范围大小* 时间复杂度:O(n+k)*/
public class CountSort {public static void main(String[] args) {int[] arr = new int[]{5,3,1,3,2,8,6,9,10,4,6,4,8,10,7,4,2,1,6,7};CountingSort(arr,arr.length);System.out.println(Arrays.toString(arr));}public static void CountingSort(int[] a,int n) {if(n<=-1) return;//查找数组中最大值int max = a[0];for(int i=1;i<a.length;i++) {if(max<a[i]) {max = a[i];}}//申请一个计数数组C下标为0到maxint[] c = new int[max+1];for(int i=0;i<c.length;i++) {c[i] = 0;}//计算每个元素的个数,放入数组C中for(int i=0;i<a.length;i++) {c[a[i]]++;}//依次累加for(int i=0;i<max;i++) {c[i+1] = c[i]+c[i+1];}//临时数组R,存储排序之后的数组int[] r = new int[a.length];//计数排序的关键步骤for(int i=a.length-1;i>=0;i--) {int index = c[a[i]]-1;r[index] = a[i];c[a[i]]--;}//将结果拷贝给a数组for(int i=0;i<a.length;i++) {a[i] = r[i];}}
}

3.基数排序

先按照数据最后以位来排序,然后,再按照倒数第二位重新排序,以此类推,最后按照第一位重新排序。经过多次排序之后,数据就都有序了。如果数据长度不一致,需要补齐数据到相同长短。

基数排序对要排序的数据是有要求的,需要可以分割出独立的“位”来比较,而且位之间有递进的关系,如果a数据的高位比b数据大,那剩下的低位就不需要较了。除此之外,每一位的数据范围不能太大,才可以用线性排序算法来排序,否则,基数排序的时间复杂度就无法做到O(n)了。
在这里插入图片描述

/*** 基数排序* 原地排序:否* 稳定排序:是* 空间复杂度:O(d+n) k为数据范围大小* 时间复杂度:O(dn) d是维数*/
public class RadixSort {public static void main(String[] args) {int[] arrs = new int[] {153,26,78,342,123,241,96};int max = getMaxData(arrs);for(int exp=1;max/exp>0;exp=exp*10) {CountingSort(arrs,arrs.length,exp);System.out.println(Arrays.toString(arrs));}}public static int getMaxData(int[] a) {//查找数组中最大值int max = a[0];for(int i=1;i<a.length;i++) {if(max<a[i]) {max = a[i];}}return max;}public static void CountingSort(int[] a,int n,int exp) {if(n<=-1) return;//查找数组中最大值int max = (a[0]/exp)%10;for(int i=1;i<a.length;i++) {if(max<(a[i]/exp)%10) {max = (a[i]/exp)%10;}}//申请一个计数数组C下标为0到maxint[] c = new int[max+1];for(int i=0;i<c.length;i++) {c[i] = 0;}//计算每个元素的个数,放入数组C中for(int i=0;i<a.length;i++) {c[(a[i]/exp)%10]++;}//依次累加for(int i=0;i<max;i++) {c[i+1] = c[i]+c[i+1];}//临时数组R,存储排序之后的数组int[] r = new int[a.length];//计数排序的关键步骤for(int i=a.length-1;i>=0;i--) {int index = c[(a[i]/exp)%10]-1;r[index] = a[i];c[(a[i]/exp)%10]--;}//将结果拷贝给a数组for(int i=0;i<a.length;i++) {a[i] = r[i];}}}

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

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

相关文章

使用vue creat搭建项目

一、查看是否安装node和npm&#xff08;显示版本号说明安装成功&#xff09; node -v npm -v 显示版本号说明安装成功&#xff0c;如果没有安装&#xff0c;则需要先安装。 二、安装vue-cli脚手架 查看安装的版本&#xff08;显示版本号说明安装成功&#xff09; vue -V 三…

【雕爷学编程】 MicroPython动手做(35)——体验小游戏3

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

30. 利用linprog 解决 生产决策问题(matlab程序)

1.简述 线线规划的几个基本性质&#xff1a;【文献[1]第46页】 (1)线性规划问题的可行域如果非空&#xff0c;则是一个凸集-凸多面体&#xff1b; (2)如果线性规划问题有最优解&#xff0c;那么最优解可在可行域的顶点中确定&#xff1b; (3)如果可行域有界&#xff0c;且可行域…

企业电子招投标系统源码之电子招投标系统建设的重点和未来趋势 tbms

​ 功能模块&#xff1a; 待办消息&#xff0c;招标公告&#xff0c;中标公告&#xff0c;信息发布 描述&#xff1a; 全过程数字化采购管理&#xff0c;打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力&#xff0c;为…

SpringBoot + ajax 实现分页和增删查改

0目录 1.SpringBoot 2.SpringBoot分页&#xff1b;增删改查 1.SpringBoot分页 创建数据库和表 创建SpringBoot工程&#xff0c;引入springboot下的分页依赖 配置application.yml 实体类 Mapper接口 Mapper.xml Service接口 Service实现类 控制层 测试 加…

新手Vite打包工具的使用并解决yarn create vite报错

一、手动创建 1.创建vite-Demo文件夹 2.初始化 yarn init -y 3.安装vite yarn add -D vite 4.打包准备 说明&#xff1a;不需要在src下面创建&#xff0c;在vite-Demo文件夹创建 4.1index.js文件 document.body.insertAdjacentHTML("beforeend","<h1>…

排序八卦炉之冒泡、快排【完整版】

文章目录 1.冒泡排序1.1代码实现1.2复杂度 2.快速排序2.1人物及思想介绍【源于百度】2.2hoare【霍尔】版本1.初识代码2.代码分析3.思其因果 2.3挖坑版本1.初始代码2.代码分析3.思想比较 2.4指针版本1.初识代码2.代码分析3.问题探讨 2.5集体优化2.6极致优化2.7非递归版本1.初识代…

sql语句字符函数,数学函数

一、trim&#xff08;&#xff09;去掉前后单元格 SELECT LENGTH(TRIM( 张三 )) AS 姓名 trim&#xff08;aa from bb) 除掉bb中前后包含的aa&#xff0c;中间的保留 SELECT TRIM(班 FROM class) AS 姓名 FROM user_test 二、lpad&#xff08;&#xff09;用指定字符做左…

【css】css实现一个简单的按钮

四种链接状态分别是&#xff1a; a:link - 正常的&#xff0c;未访问的链接a:visited - 用户访问过的链接a:hover - 用户将鼠标悬停在链接上时a:active - 链接被点击时 <style> a:link, a:visited {//未访问、访问过background-color: #07c160;//设置背景颜色color: wh…

Day10-NodeJS和NPM配置

Day10-NodeJS和NPM 一 Nodejs 1 简介 Nodejs学习中文网:https://www.nodeapp.cn/synopsis.html Nodejs的官网:https://nodejs.org/ 概念:Nodejs是JavaScript的服务端运行环境.Nodejs不是框架,也不是编程语言,就是一个运行环境. Nodejs是基于chrome V8引擎开发的一套js代码…

Toyota Programming Contest 2023#4(AtCoder Beginner Contest 311)D题题解

文章目录 [Grid Ice Floor](https://atcoder.jp/contests/abc311/tasks/abc311_d)问题建模问题分析1.分析移动时前后两个点之间的联系2.方法1通过BFS将所有按照给定运动方式可以到达的点都标记代码 3.方法2采用DFS来标记路径上的点的运动状态代码 Grid Ice Floor 问题建模 给定…

测试岗?从功能测试进阶自动化测试开发,测试之路不迷茫...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 测试新人在想什么…

IO进程线程day7(2023.8.4)

一、Xmind整理&#xff1a; 二、课上练习&#xff1a; 练习1&#xff1a;创建两个线程&#xff1a;其中一个线程拷贝前半部分&#xff0c;另一个线程拷贝后半部分。 只允许开一份资源&#xff0c;且用互斥锁方式实现。 提示&#xff1a;找临界区--->找临界资源。 #includ…

swagger相关问题

swagger相关问题 swagger版本为&#xff1a; <dependency><groupId>com.github.xiaoymin</groupId><artifactId>swagger-bootstrap-ui</artifactId><version>1.9.6</version> </dependency> <dependency><groupId&…

网络安全设备-等保一体机

本文为作者学习文章&#xff0c;按作者习惯写成&#xff0c;如有错误或需要追加内容请留言&#xff08;不喜勿喷&#xff09; 本文为追加文章&#xff0c;后期慢慢追加 等保一体机的功能 等保一体机产品主要依赖于其丰富的安全网元&#xff08;安全网元包括&#xff1a;防火…

sentinel组件

目录 定义 4.加SentinelResource,blockHander是超过阈值之后执行的函数 5.设置阈值 6.springboot集成sentinel 定义 1.sentinel知道当前流量大小&#xff0c;在浏览器和后端之间加sentinel控制流量&#xff0c;避免大批量的瞬时请求都达到服务上&#xff0c;将服务压垮 2.…

汉字姓名转拼音

import osimport pandas as pdfrom xpinyin import Pinyindownpath/Users/Kangyongqing/Downloads/ file1教师姓名转拼音.xlsxdtpd.read_excel(downpathfile1) print(dt.info()) dt[pinyin]dt[教师姓名].apply(lambda x:Pinyin().get_pinyin(x).split(-)[0].capitalize() .join…

linux的搭建以及网关配置

Linux 目前国内 Linux 更多的是应用于服务器上,而桌面操作系统更多使用的是 Windows 安装linux虚拟机 网址 VMware下载网址 点击Workstation 16 Pro for Windows下载 安装CentOS centO下载网址 依次点击 7.6.1810/ isos/ x86_64/ CentOS-7-x86_64-DVD-1810.…

Vue3 watch监听器

概览&#xff1a;watch监听器的定义以及使用场景。在vue3中的监听器的使用方式&#xff0c;watch的三个参数&#xff0c;以及进一步了解第一个参数可以是一个属性&#xff0c;也可以是一个数组的形式包含多个属性。 watch在vue3和vue2中的使用&#xff1a; vue3中&#xff1a…

uniapp-疫情应急管理系统学生端

1 疫情资讯展示 <template><view class"container"><uni-section title"自定义卡片内容" type"line"><uni-card title"基础卡片" class"card-box" v-for"(item,index) in epidemicNewsList"…