【java数据结构之八大排序(上)-直接插入排序,希尔排序,选择排序,堆排序,向下调整(大根堆,小根堆)等知识详解】

在这里插入图片描述

🌈个人主页:努力学编程’
个人推荐:基于java提供的ArrayList实现的扑克牌游戏 |C贪吃蛇详解
学好数据结构,刷题刻不容缓:点击一起刷题
🌙心灵鸡汤总有人要赢,为什么不能是我呢
在这里插入图片描述

hello,今天带大家学数据结构的一个非常重要的部分,排序!!!,回想博主的学习路程 ,好像真正学过的排序就是冒泡排序,其实数据结构里面有很多的排序的算法,针对不同的数据,我们往往采用不同的排序算法,合适的排序算法处理数据时可能会大大减少内存的消耗,和较短的运行时间。下面就带大家学习几种常见的排序算法。
在这里插入图片描述

🍪插入排序:

🍰直接插入排序:

在这里插入图片描述

直接插入排序是一种简单直观的排序算法,将待排序的元素逐个插入到已经排序好的序列中的适当位置,从而得到一个新的、更长的有序序列。具体的实现呢,给大家列出来了:

1.初始状态:假设第一个元素已经是有序的序列。
遍历未排序部分:从第二个元素开始,逐个遍历未排序的元素。
插入操作:对于当前遍历到的元素,将其与已经排序好的序列中的元素依次比较,找到合适的位置插入。

2.移动元素:如果发现当前元素比已排序序列中的某个元素小(或大,取决于排序顺序),则将该元素后移一位,为当前元素腾出插入位置。
插入元素:找到合适的位置后,将当前元素插入到该位置。
重复:重复上述步骤,直到所有元素都被插入到有序序列中。

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;
                }
            }
            array[j+1] = tmp;
        }
    }

在这里插入图片描述
直接插入排序的特性总结:

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

🍰希尔排序

希尔排序又称为缩小增量排序,其本质是将所有的数据分成N组,每一组的元素对应的是从第一个开始,每N个的元素后的那个元素进行比较排序,依次对N组元素做同样的处理。

然后对数据重新分组,分为K组(K<N),然后重复上述操作对每组元素比较大小,直到分组为1,完成比较。
在这里插入图片描述
那么你可能会问,每次分组的时候,有什么依据吗,总不能想怎么分就怎么分吧,
在这里插入图片描述在这里插入图片描述
我们这里为了方便期间,采用gap=[N/2]的处理方法,向下取整,将数据划分直到化为1为止。完成排序。由于不同的人可能采用不同的gap去划分数据,时间复杂度也就相应的可能会不同,所以希尔排序的时间复杂度不太好计算。

稳定性:不稳定

 public static void shellSort(int[] array) {
        int gap = array.length;//n
        while (gap > 1) {
            gap = gap/3 + 1;
            shell(array,gap);
        }
    }

    /**
     * 每组进行插入排序
     * @param array
     * @param gap
     */
    private static void shell(int[] array,int gap) {
        //i++ 交替进行插入排序
        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;
        }
    }

    private static void swap(int[] array,int i,int j) {
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }

这里还是给大家具体演示一下,帮助大家理解。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

🍰选择排序

定义:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。

在这里插入图片描述
这里先给大家这个简单比较容易理解的版本:

public void selectSort(int[] array){
        for(int i=0;i<array.length;i++){
            int minindex=i;
            for(int j=i+1;j<array.length;j++){
                if(array[minindex]>array[j]){
                    minindex=j;
                }
            }
            swap(array,minindex,i);
        }
    }
    public void swap(int[]array,int i,int j){
        int tmp=array[i];
        array[i]=array[j];
        array[j]=tmp;
    }

进行测试:
完成测试
测试成功!!!

👋当然我们还有一种选择排序的另一种实现方法,我们每次遍历的时候,都选择两个元素,一个是这次遍历的最小元素,一个是最大的元素,分别放到数组的最左和最有端,然后就和上面的逻辑一样,继续遍历,更新最大值和最小值,遍历结束。

这里也把代码给大家,这端代码说起来简单,但是还是有很多的小细节的,大家细细品味一下。

public 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[maxIndex])  maxIndex=i;
               if(array[i]<array[minIndex])  minIndex=i;

            }
            swap(array,minIndex,left);
            //[10,6,4,8,7]这个例子大家按照代码的逻辑画个图
            //就会发现,排序失败原因是maxIndex==left我们在
            //第一次交换之后就会把maxIndex对应的值交换到minIndex中了
            //所以必须加一个判断
            if(left==maxIndex)  maxIndex=minIndex;
            swap(array,maxIndex,right);
            left++;
            right--;
        }
    }

我把需要注意的地方注释出来了,希望大家还是可以自己在纸上画一下,这样会对整个过程有一个更加全面的认识。

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

🍰堆排序

堆排序是我们所学的排序当中非常重要的一种排序,它实际上是建立在我们上一篇发布的文章优先级队列的基础上创建的一种排序方式,如果你对堆的概念还没有印象的话我建议你先去看看我的上一篇文章。

堆排序是建立在堆上的一种选择排序的算法,需要大家特别注意的是如果你要建立的是升序的序列的话。那么必须建立大根堆,降序的话,建立的是小根堆。

其实他的本事就是堆 里面的向下调整,我们上一篇文章也已经讲过了,那么他的过程到底是怎么样的,这里给大家演示一下。
在这里插入图片描述
那我们第一步其实是创建一个大根堆,相信这个应该对大家来说不太难,我把代码给大家,里面有详细的注释,大家可以对照看看:

private void createBigHeap(int[] array){
        for(int parent=(array.length-1-1)/2;parent>0;parent--){
            //从最后一个叶子节点的父节点开始遍历,向下调整
            siftDown(parent,array,array.length);
        }
    }
    public void siftDown(int parent,int[] array,int end){
        int child=parent*2+1;
        while(child<end){
            if(child+1<end&&array[child]<array[child+1]){
                child++;
            }
            if(array[child]>array[parent]){
                swap(array,child,parent);
                //这里是因为把孩子节点与父节点交换之后可能有问题
                //所以对树的底层都要检查一下
                parent=child;
                child=parent*2+1;
            }else{
                break;
            }
        }
    }

接下来按照堆排序的定义,我们以此交换根节点和最后一个叶子节点,然后向下调整,直到结束,下面是完整的代码:

 private void createBigHeap(int[] array){
        for(int parent=(array.length-1-1)/2;parent>0;parent--){
            //从最后一个叶子节点的父节点开始遍历,向下调整
            siftDown(parent,array,array.length);
        }
    }
    public void siftDown(int parent,int[] array,int end){
        int child=parent*2+1;
        while(child<end){
            if(child+1<end&&array[child]<array[child+1]){
                child++;
            }
            if(array[child]>array[parent]){
                swap(array,child,parent);
                //这里是因为把孩子节点与父节点交换之后可能有问题
                //所以对树的底层都要检查一下
                parent=child;
                child=parent*2+1;
            }else{
                break;
            }
        }
    }
    public void HeapSort(int[] array){
        createBigHeap(array);
        int end=array.length-1;
        while(end>=0){
            swap(array,end,0);
            siftDown(0,array,end);
            end--;
        }

    }

简单测试一下:
在这里插入图片描述
测试成功!!!

1.堆排序使用堆来选数,效率就高了很多。
2. 时间复杂度:O(N*logN)
3. 空间复杂度:O(1)
4. 稳定性:不稳定
好了今天就带大家学习这么多了,下次带大家学习剩下的几种排序,觉得文章对你有帮助的话,一键三连,支持一下,同时欢迎评论区留下你宝贵的建议~~~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度学习之基于YOLOv5的山羊行为识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 基于YOLOv5的山羊行为识别系统是一个结合了深度学习和目标检测技术的项目&#xff0c;旨在通过图像或视频实现对山羊…

DELL PowerEdge服务器通过iDRAC升级BIOS遇到的问题

本文对PowerEdge 12G系统&#xff0c;也就是iDRAC 7版本升级BIOS中遇到的几个问题做个总结&#xff0c;对于其他版本理论上应该也是适用的。如果还遇到其他问题&#xff0c;可以添加VX&#xff0c;VX号为 StorageExpert 进行进一步的分析探讨。 第一个问题&#xff0c;成功下载…

C#调用skiasharp实现绘制并拖拽图形

SkiaSharp是基于.net的跨平台二维图形库&#xff0c;封装的谷歌的Skia库&#xff0c;SkiaSharp支持在以下平台或运行时中使用&#xff0c;能够在图片中绘图&#xff0c;也提供控件在Winform、WPF等使用。本文学习skiasharp在Winform的基本用法&#xff0c;并参照参考文献5实现绘…

【Unity动画系统】详解Root Motion动画在Unity中的应用(一)

Root Motion动画与普通动画的区别 普通动画&#xff1a;动画文件里记录的是物体的绝对坐标和方向&#xff0c;在播放动画时&#xff0c;Unity会根据Animation中记录的值&#xff0c;直接修改游戏对象的坐标和方向&#xff0c;每一帧的坐标和方向都是通过插值计算得出来的&…

【Camera KMD ISP SubSystem笔记】Request 流转与Bubble机制

ISP中断类型 SOF: 一帧图像数据开始传输 EOF: 一帧图像数据传输完成 REG_UPDATE: ISP寄存器更新完成(每个reg group都有独立的这个中断) EPOCH: ISP某一行结尾(默认20)就会产生此中断 BUFFER DONE: 一帧图像数据ISP完全写到DDR了 管理Isp request的几个List st…

锂电池SOH预测 | 基于CNN的锂电池SOH预测(附matlab完整源码)

锂电池SOH预测 锂电池SOH预测完整代码锂电池SOH预测 锂电池的SOH(状态健康度)预测是一项重要的任务,它可以帮助确定电池的健康状况和剩余寿命,从而优化电池的使用和维护策略。 SOH预测可以通过多种方法实现,其中一些常用的方法包括: 容量衰减法:通过监测电池的容量衰减…

AMBA-CHI协议详解(二)

《AMBA 5 CHI Architecture Specification》 文章目录 2.1 Channels综述2.2 Channel域段2.2.1 request fields2.2.2 Response fields2.2.3 Snoop request fields2.2.4 Data fields 2.3 事务结构2.3.1 Read transactions2.3.1.1 Allocating Read2.3.1.2 Non-allocating Read 2.…

字符串类型漏洞之updatexml函数盲注

UPDATEXML 是 MySQL 数据库中的一个函数&#xff0c;它用于对 XML 文档数据进行修改和查询。然而&#xff0c;当它被不当地使用或与恶意输入结合时&#xff0c;它可能成为 SQL 注入攻击的一部分&#xff0c;从而暴露敏感信息或导致其他安全漏洞。 在 SQL 注入攻击中&#xff0…

通过Cmake官网下载.gz文件安装最新版本的CMAKE、适用于debian

1.前往官网下载最新版本debian https://cmake.org/download/ 2.选他 3. 通过XFTP传输到服务器 4. 解压文件 #cd 进入对应目录&#xff0c;然后执行下面命令解压 $ tar -zxvf cmake-3.29.2.tar.gz5.执行这个文件 $ ./bootstrap6.完成之后再执行这个 $ make7.然后&#xff…

C语言--贪吃蛇小游戏

目录 一、Win32API介绍 1.1Win32API 1.2控制台程序 1.3控制台屏幕上的坐标COORD 1.4GetStdHandle 1.5GetConsoleCursorInfo 1.6 CONSOLE_CURSOR_INFO 1.7 SetConsoleCursorInfo 1.8SetConsoleCursorPosition 1.9GetAsyncKeyState 二、贪吃蛇游戏设计与分析 2.1地图 …

双重注意力模块 DoubleAttention | A2-Nets: Double Attention Networks

论文名称&#xff1a;《 A 2 A^2 A2-Nets: Double Attention Networks》 论文地址&#xff1a;https://arxiv.org/pdf/1810.11579.pdf 学习捕捉远距离关系对于图像/视频识别是基础性的。现有的CNN模型通常依靠增加深度来建模这些关系&#xff0c;这在很大程度上效率低下。在这…

数字旅游打造个性化旅行体验,科技让旅行更精彩:借助数字技术,旅行者可以定制专属旅行计划,享受个性化的旅行体验

目录 一、引言 二、数字旅游的兴起与发展 三、数字技术助力个性化旅行体验 1、智能推荐系统&#xff1a;精准匹配旅行者需求 2、定制化旅行计划&#xff1a;满足个性化需求 3、实时互动与分享&#xff1a;增强旅行体验 四、科技提升旅行便捷性与安全性 1、移动支付与电…

boot https ssl 使用http协议访问报错

在springboot中配置ssl以后&#xff0c; 再次使用http访问对应的接口就会报错 可以考虑如下设置&#xff0c;将http访问的端口重定向到https对应的端口 import org.apache.catalina.Context; import org.apache.catalina.connector.Connector; import org.apache.tomcat.util…

图像处理ASIC设计方法 笔记18 轮廓跟踪算法的硬件加速方案

目录 1排除伪孤立点&#xff08;断裂链表&#xff09;方法1 限制链表的长度方法2 增加判断条件排除断裂链表方法3 排除不必要跟踪的轮廓&#xff08;推荐用这个方法&#xff09; P129 轮廓跟踪算法的硬件加速方案 1排除伪孤立点&#xff08;断裂链表&#xff09; 如果图像中某…

探索开源的容器引擎--------------Docker容器操作

目录 一、Docker 容器操作 1.1容器创建 1.2查看容器的运行状态 1.3启动容器 1.4创建并启动容器 1.4.1当利用 docker run 来创建容器时&#xff0c; Docker 在后台的标准运行过程是&#xff1a; 1.4.2在后台持续运行 docker run 创建的容器 1.4.3创建容器并持续运行容器…

Pytorch基础:torch.load_state_dict()方法在加载时不会检查类型

相关阅读 Pytorch基础https://blog.csdn.net/weixin_45791458/category_12457644.html?spm1001.2014.3001.5482 笔者在使用torch.nn.module的load_state_dict中出现了一个问题&#xff0c;一个被注册的张量在加载后居然没有变化&#xff0c;一开始以为是加载出现了问题&#…

Kafka 3.x.x 入门到精通(07)——Java应用场景——SpringBoot集成

Kafka 3.x.x 入门到精通&#xff08;07&#xff09;——Java应用场景——SpringBoot集成 4. Java应用场景——SpringBoot集成4.1 创建SpringBoot项目4.1.1 创建SpringBoot项目4.1.2 修改pom.xml文件4.1.3 在resources中增加application.yml文件 4.2 编写功能代码4.2.1 创建配置…

debian配置BIND DNS服务器

前言 局域网内有很多台主机&#xff0c;IP难以记忆。 而修改hosts文件又难以做到配置共享和统一&#xff0c;需要一台内网的DNS服务器。 效果展示 这里添加了一个域名hello.dog&#xff0c;将其指向为192.168.1.100。 同时&#xff0c;外网的域名不会受到影响&#xff0c;…

基于粒子滤波器的电池剩余使用寿命计算matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 粒子滤波器基础 4.2 电池剩余使用寿命建模与预测 4.3 粒子滤波器在电池寿命预测中的应用 5.完整工程文件 1.课题概述 基于粒子滤波器的电池剩余使用寿命计算。根据已知的数据&#xff0c;预测未来…

前端框架编译器之模板编译

编译原理概述 编译原理&#xff1a;是计算机科学的一个分支&#xff0c;研究如何将 高级程序语言 转换为 计算机可执行的目标代码 的技术和理论。 高级程序语言&#xff1a;Python、Java、JavaScript、TypeScript、C、C、Go 等。计算机可执行的目标代码&#xff1a;机器码、汇…