当前位置: 首页 > news >正文

数据结构-8.Java. 七大排序算法(上篇)

本篇博客给大家带来的是排序的知识点, 由于时间有限, 分两天来写, 上篇主要实现 前四种排序算法: 直接插入, 希尔, 选择, 堆排。

文章专栏: Java-数据结构

若有问题 评论区见

欢迎大家点赞 评论 收藏 分享

如果你不知道分享给谁,那就分享给薯条.

你们的支持是我不断创作的动力 .

    

目录

    

  王子公主请阅

1.排序的概念及应用

1.1 排序的概念

1.3 常见的排序算法

2. 常见排序算法的实现(默认排升序)

2.1 插入排序

2.1.1基本思想:

2.1.2 直接插入排序

直接插入排序具体操作: 

2.1.3 希尔排序(缩小增量排序)

2.2 选择排序

2.2.1基本思想:

2.2.3 堆排序


  王子公主请阅

1.排序的概念及应用

1.1 排序的概念

排序:所谓排序,就是使一串记录按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。

稳定性 :假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j] ,且 r[i] r[j] 之前,而在排序后的序列中, r[i] 仍在 r[j] 之前,则称这种排序算法是稳定的;否则称为不稳定的。
内部排序 :数据元素全部放在内存中的排序。
外部排序 :数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

1.3 常见的排序算法

2. 常见排序算法的实现(默认排升序)

2.1 插入排序

2.1.1基本思想:

直接插入排序是一种简单的插入排序法,其基本思想是:

把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到 一个新的有序序列 。实际中我们玩扑克牌时,就用了插入排序的思想。

如下模拟动图: 

2.1.2 直接插入排序

当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,
此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置
array[i]插入,原来位置上的元素顺序后移
如下图: 

直接插入排序具体操作: 

第一步 理清思路:

 当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,

此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置
array[i]插入,原来位置上的元素顺序后移
第二步具体步骤: 

1.   定义 tmp 保存 排序前 i 下标对应的值.  for(i) 为 外循环, for(j) 为  内循环 , j = i -1 .

2.   遍历数组,  在内循环中,  tmp 与  array[ j ] 进行比较,, 若是 tmp 小 则  [ j + 1] = [ j ];

若是 tmp 大 则 直接 break;  

3.    在外循环中  将 最后 j + 1 位置的值 赋为 tmp值 , [ j + 1 ] = tmp;  

第三步  画图理解 , 一目了然 :

第四步  代码实现: 

 /*** 时间复杂度:*            最好情况:数据完全有序的时候 1 2 3 4 5 :O(N)*            最坏情况:数据完全逆序的时候 5 4 3 2 1 :O(N^2)*         结论: 数据越有序,排序越快, *         场景: 现在有一组基本有序的数据,那么用哪个排序好点? - 直接插入排序.* 空间复杂度: O(1)* 稳定性:  稳定的排序*      一个本身就是稳定的排序 是可以实现为不稳定的排序的*      相反 一个本身就不稳定的排序  是不可以实现为稳定的排序的.** @param //直接插入排序*/public static void insertSort(int[] array) {for (int i = 1; i < array.length; i++) {int tmp = array[i];int j = i-1;for (; j >= 0; j--) {if(array[j] > tmp) {  // >= 会变成不稳定的array[j+1] = array[j];}else {//array[j+1] = tmp; 执行了一次break;}}//当j=-1时,a[j+1]=tmp这条语句没被执行,所以再写一次array[j+1] = tmp; //执行了两次, 故把第一次屏蔽.}}

最后总结: 

1. 元素集合越接近有序,直接插入排序算法的时间效率越高
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1),它是一种稳定的排序算法
4. 稳定性:稳定 

2.1.3 希尔排序(缩小增量排序)

希尔排序本质上 就是 在对直接插入排序做优化。

第一步 了解基本思想: 

先选定一个整数 gap ,把待排序文件中所有记录分成多个组,
此处 gap 通常都是 初始化成 gap = array.length/2;
所有 距离为 gap 的记录 在同一组内,并对每一组内的记录进行直接插入排序。
每进行一次直接插入排序 gap /= 2 重复上述分组和排序的工作。当 gap =  时,所有记录在同一组内进行直接插入排序
第二步 画图辅助理解: 
第三步 具体步骤:
具体步骤与 直接插入排序的大体相同, 将 外循环条件换成for (int i = gap; i < array.length; i++),
外循环中 j = i - gap 而不是 - 1;  
同时, 内循环变成for (; j >= 0; j -= gap)
赋值条件变为array[j+gap] = tmp;
最后在直接插入排序外加一层 gap /= 2 的循环 就大功告成了.
第四步  代码实现: 
/*** 希尔排序** 时间复杂度:*        n^1.3 - n^1.5*  空间复杂度: O(1)**  稳定性: 不稳定* @param //shell*/public static void shellSort(int[] array) {int gap = array.length;while(gap > 1) {gap /= 2;shell(array,gap);}//gap /= 2;不用写   因为gap=2或3时, gap/2 = 1.已经进行了直接插入排序.}private static void shell(int[] array,int gap) {for (int i = gap; i < array.length; i++) {int tmp = array[i];int j = i-gap;for (; j >= 0; j -= gap) {if(array[j] > tmp) {array[j+gap] = array[j];}else {break;}}array[j+gap] = tmp;}}

最后 希尔排序的特性总结

1. 希尔排序是对直接插入排序的优化。
2. gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。
3. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的希尔排序的时间复杂度都不固定:O(n^1.25) ~ O(1.6 * n^1.25)
4. 稳定性:不稳定

2.2 选择排序

2.2.1基本思想:

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。
如下模拟动图: 
第一步 理清思路:
在元素集合 array[ i ] ~ array[ n-1 ] 中选择关键码最 的数据元素
若它不是这组元素中的 第一个 元素,则将它与这组元素中的最后一个(第一个)元素交换
在剩余的 array[ i ]  ~ array[ n-2 ] array[ i+1 ]  ~  array[ n-1 ] )集合中,重复上述步骤,直到集合剩余 1 个元素
第二步 具体步骤: 
1.  写个双层循环, for( i ) 为 外层循环,  for( j ) 为外层循环, 定义minIndex =  i , j = i + 1;
2.   [minIndex] 与 [ j ] 比较, 当[minIndex] > [ j ] 时  二者交换. 
第三步  代码实现:
/*** 选择排序** 时间复杂度:*      最好: O(N^2)*      最坏: O(N^2)*空间复杂度:O(N)** 稳定性: 不稳定** @param array*/public static void selectSort(int[] array) {for (int i = 0; i < array.length-1; i++) {int minIndex = i;for (int j = i+1; j < array.length; j++) {if(array[j] < array[minIndex]) {minIndex = j;}}swap(array,minIndex,i);}}public static void swap(int[] array,int i,int j) {int tmp = array[i];array[i] = array[j];array[j] = tmp;}

选择排序有 第二种写法,  反正都要遍历一遍数组, 不如把最大值和最小值都找出来, 最小的往最前放, 最大的往最后放. 

第二种写法步骤:

 1.  定义 left = 0, right = array.length-1, i = left + 1; minIndex = maxIndex = 0;

2.   while( left < right )循环,  i 在循环中, 遍历数组 找到最小元素下标 和 最大元素下标, 出循环 与 minIndex 和 maxIndex 交换.  

3. 出循环后 考虑一个特殊情况 , 当 left = 0 下标 对应的值就是最大值时, 第二步出循环后的交换操作 将最大值交换到minIndex下标处了. 需要 再将 maxIndex 标记到最大值.

第二种写法代码实现:

public static void swap(int[] array,int i,int j) {int tmp = array[i];array[i] = array[j];array[j] = tmp;}//选择排序的第二种写法.public static void selectSort2(int[] array) {int left = 0;int right = array.length-1;while(left < right) {int minIndex = left;int maxIndex = left;for (int i = left; i <= right; i++) {if(array[i] < array[minIndex]) {minIndex = i;}if(array[i] > array[maxIndex]) {maxIndex = i;}}swap(array,left,minIndex);//有一种情况是maxIndex原本就在left位置上,上面的交换将最大值交换到minIndex下标处了.导致后续的排序不正确.if(maxIndex == left) {maxIndex = minIndex;}swap(array,right,maxIndex);left++;right--;}}

第四步 直接选择排序的特性总结:

1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1)
4. 稳定性:不稳定

2.2.3 堆排序

堆排序 (Heapsort) 是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。
第一步  具体步骤:
1. 排升序, 建大堆 , 向下调整算法 , parent 从 (array.length - 1)/2 开始 减到 1 
2. 将最后一个元素与首元素交换, 除末尾元素外, 其余元素调整成大根堆
3. 定义一个end = array.length - 1; while (end > 0) 循环中进行 2 步骤.
第二步  代码实现: 
 /***堆排序** 时间复杂度:O(N)+O(N*logN) 约等于 O(N*logN)** 如果都以最坏的情况来看,堆排序是目前来说最快的,希尔排序其次.* 假设希尔排序为O(N^1.3) 当N越大时,logN趋于不变所以,堆排序O(N*logN)要快一些.**  空间复杂度:O(1)*  稳定性:不稳定*/public static void heapSort(int[] array) {//建大堆createBigHeap(array);//O(N)int end = array.length-1;//O(N*logN)while(end > 0) {swap(array,0,end);shiftDown(array,0,end);end--;}}private static void createBigHeap(int[] array) {for (int parent = (array.length-1-1)/2; parent >= 0; parent--) {shiftDown(array,parent,array.length);}}private static void shiftDown(int[] array,int parent,int end) {int child = (parent*2)+1;while(child < end) {//保证右子树存在并且当右子树大的时候,child++来到右子树的下标.if(child+1 < end && array[child+1] > array[child]) {child++;}if(array[child] > array[parent]) {swap(array,child,parent);parent = child;child = parent*2+1;}else {//本身就是大根堆break;}}}

第三步   堆排序的特性总结:

1. 堆排序使用堆来选数,效率就高了很多。
2. 时间复杂度:O(N*logN)
3. 空间复杂度:O(1)
4. 稳定性:不稳定

相关文章:

数据结构-8.Java. 七大排序算法(上篇)

本篇博客给大家带来的是排序的知识点, 由于时间有限, 分两天来写, 上篇主要实现 前四种排序算法: 直接插入, 希尔, 选择, 堆排。 文章专栏: Java-数据结构 若有问题 评论区见 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 …...

YOLOV5/rknn生成可执行文件部署在RK3568上

接上一篇文章best-sim.rknn模型生成好后&#xff0c;我们要将其转换成可执行文件运行在RK3568上&#xff0c;这一步需要在rknpu上进行&#xff0c;在强调一遍&#xff01;&#xff01;rknpu的作用是可以直接生成在开发板上运行的程序 退出上一步的docker环境 exit1.复制best-…...

java http body的格式 ‌application/x-www-form-urlencoded‌不支持文件上传

在Java中&#xff0c;HTTP请求的body部分可以包含多种格式的数据&#xff0c;主要包括以下几种‌&#xff1a; ‌application/x-www-form-urlencoded‌&#xff1a;这种格式将数据编码成键值对的形式&#xff0c;键和值都进行了URL编码&#xff0c;键值对之间用&符号连接。…...

GPU服务器厂家:为什么要选择 GPU 服务器?

文章来源于百家号&#xff1a;GPU服务器厂家 嘿&#xff0c;各位小伙伴们&#xff01;今天咱来聊聊为啥要选择 GPU 服务器&#xff0c;特别是定制化的那种哦。 你们知道吗&#xff1f;现在定制化 GPU 服务器那可是超火的&#xff0c;简直就是科研项目的超强 “外挂”&#x…...

Python操作neo4j库py2neo使用之py2neo 删除及事务相关操作(三)

Python操作neo4j库py2neo使用之py2neo 删除及事务相关操作&#xff08;三&#xff09; py2neo 删除 1、连接数据库 from py2neo import Graph graph Graph("bolt://xx.xx.xx.xx:7687", auth(user, pwd), nameneo4j)2、删除节点 # 删除单个节点 node graph.node…...

Idea忽略提交文件、Idea设置文件隐藏、Idea提交时隐藏部分文件、git提交时忽略文件

文章目录 一、在idea中commit文件时隐藏文件方式一&#xff1a;创建.gitignore文件&#xff08;推荐&#xff09;方式二&#xff1a;‌通过File Types设置隐藏文件方式三&#xff1a;通过Git配置忽略文件‌&#xff08;不推荐&#xff09;总结 二、可能遇到的问题2.1、.gitigno…...

python如何使用spark操作hive

文章目录 1、服务启动2、修改配置3、验证4、开发环境编写代码操作hive 1、服务启动 # 启动hdfs和yarn start-all.sh # 日志服务也需要启动一下 mapred --daemon start historyserver # 启动spark的日志服务 /opt/installs/spark/sbin/start-history-server.sh #启动hive的meta…...

观察者模式和订阅模式

观察者模式和订阅模式在概念上是相似的&#xff0c;它们都涉及到一个对象&#xff08;通常称为“主题”或“发布者”&#xff09;和多个依赖对象&#xff08;称为“观察者”或“订阅者”&#xff09;之间的关系。然而&#xff0c;尽管它们有相似之处&#xff0c;但在某些方面也…...

基于ToLua的C#和Lua内存共享方案保姆级教程

C#和Lua内存共享方案保姆级教程 前言 在介绍C#和Lua内存共享方案之前,先介绍下面两个点来支撑这个方案的必要性 跨语言交互很费 Lua和C#交互最早是基于反射的方式实现的,后来为了提升性能发展成Luajit+C#静态方法导出注入到lua虚拟机的方式至此Lua+Unity的性能才达到了实…...

OpenCV与AI深度学习|16个含源码和数据集的计算机视觉实战项目(建议收藏!)

本文来源公众号“OpenCV与AI深度学习”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;分享&#xff5c;16个含源码和数据集的计算机视觉实战项目 本文将分享16个含源码和数据集的计算机视觉实战项目。具体包括&#xff1a; 1. 人…...

Vue 如何简单更快的对 TypeScript 中接口的理解?应用场景?

TypeScript 中接口&#xff08;Interface&#xff09;的理解与应用 在 TypeScript 中&#xff0c;接口&#xff08;Interface&#xff09; 是一种用来定义对象的结构或形状的方式。接口可以指定对象中应该包含哪些属性、这些属性的类型以及它们的函数签名。接口帮助我们在代码…...

R语言绘图过程中遇到图例的图块中出现字符“a“的解决方法

R语言绘图过程中遇到图例的图块中出现字符的解决方法 因为我遇到这个问题的时候没在网上找到合适的方法&#xff0c;找到个需要付费的&#xff0c;算了。也许是因为问的方式不同&#xff0c;问了半天AI也回答出来&#xff0c;莫名有些烦躁&#xff0c;打算对代码做个分析&…...

视图合并机制解析 | OceanBase查询优化

背景 在默认配置下&#xff0c;若查询语句中嵌入了视图&#xff0c;系统会先等待视图内部所包含的查询完全执行完成后&#xff0c;再继续执行父查询。这种方式造成优化器无法将视图查询与外层查询视为一个整体来进行优化处理&#xff0c;从而限制了优化效果。因此&#xff0c;…...

sql注入报错分享(mssql+mysql)

mysql mysql的报错内容比较多 网上也有比较多的 这里重复的就不多介绍了。一笔带过 溢出类 bigint 当超过mysql的整形的时候&#xff0c;就会导致溢出&#xff0c;mysql可能会将错误信息带出。这里user()是字母默认为0 取反以后1可能就会导致异常。 报错特征 BIGINT UNSIG…...

PHP 高并发解决方案

PHP作为一种脚本语言&#xff0c;在处理高并发请求时可能面临一些挑战。但通过合理的设计和优化&#xff0c;可以有效提升PHP应用程序的性能和并发处理的能力。 一、缓存 页面缓存&#xff1a;将生成的页面缓存起来&#xff0c;减少对数据库的查询&#xff0c;提高响应速度。…...

k8s1.30.0高可用集群部署

负载均衡 nginx负载均衡 两台nginx负载均衡 vim /etc/nginx/nginx.conf stream {upstream kube-apiserver {server 192.168.0.11:6443 max_fails3 fail_timeout30s;#server 192.168.0.12:6443 max_fails3 fail_timeout30s;#server 192.168.0.13:6443 max_fails3…...

多摩川编码器协议及单片机使用

参考&#xff1a; https://blog.csdn.net/qq_28149763/article/details/132718177 https://mp.weixin.qq.com/s/H4XoR1LZSMH6AxsjZuOw6g 1、多摩川编码器协议 多摩川数据通讯是基于485 硬件接口标准NRZ 协议&#xff0c;通讯波特率为2.5Mbps 的串行通讯&#xff0c;采用差分两…...

Android 网络通信(三)OkHttp实现登入

学习笔记 目录 一. 先写XML布局 二、创建 LoginResponse 类 :封装响应数据 目的和作用: 三、创建 MyOkHttp 类 :发送异步请求 代码分析 可能改进的地方 总结 四、LoginActivity 类中实现登录功能 详细分析与注释: 总结: 改进建议: 零、响应数据样例 通过 P…...

分享一下arr的意义(c基础)(必看)(牢记)

arr 即数组名 一般指数组首元素地址 在两种情况下不是 1&#xff1a;sizeof&#xff08;arr&#xff09; arr指整个数组简单讲解一下strlen与sizeof&#xff08;c基础&#xff09;_strzeof在c语言中什么意思-CSDN博客 2&#xff1a;printf&#xff08;"%p",&…...

AGENT AI 综述核心速览

研究背景 研究问题&#xff1a;这篇文章探讨了多模态人工智能&#xff08;Agent AI&#xff09;系统在理解和响应视觉和语言输入方面的潜力&#xff0c;特别是在物理和虚拟环境中的应用。Agent AI旨在通过感知和行动来增强人工智能系统的交互性和适应性。研究难点&#xff1a;…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...