【Java】5大排序算法总结(插入排序+希尔排序+选择排序+堆排序+冒泡排序)

2023-11-18

1. 稳定性

两个相等的数据,如果经过排序后,排序算法能保证其相对位置不发生变化,则我们称该算法是具备稳定性的排序算法。
在这里插入图片描述

图中排序后a仍然在b前面,此时这个排序就是稳定的。

常见的排序算法有 :
在这里插入图片描述

2 . 插入排序

步骤:

  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取下一个元素下标定义为i,并且放到变量tmp中,从已排序的元素序列从后往前扫描
  3. 如果该元素大于tem,则将该元素移到下一位
  4. 重复步骤3,直到找到已排序元素中小于等于tem的元素,直接break
  5. tem插入到该元素的后面(array[j+1]=tmp;),如果已排序所有元素都大于tem,则将tem插入到下标为0的位置
  6. 重复步骤2~5
 /**
     * 直接插入排序
     * 时间复杂度:O(N^2) 逆序的时候
     * (最好的情况是O(N):对于直接插入排序来说,最好的情况就是数组有序的时候)
     * 根据这个结论:推导出另一个结论:对于直接插入排序来说,数据越有序,越快
     * 直接插入排序所以也用于其他排序的优化!
     * 空间复杂度:O(1)
     * 稳定性:稳定
     * 一个稳定的排序,可以实现一个不稳定的排序
     * 但是一个本身就不稳定的排序就不可以变成稳定的排序
     * 经常使用在 数据量不多 且 整体数据趋于有序了
     * @param array
     */
    public 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 {
                    // 只要j回退的时候,遇到了比tmp小的元素,就结束这次的比较
                    break;
                }
            }
            //j回退到了 小于0 的地方
            array[j+1]=tmp;
        }
    }

动图演示如下:
请添加图片描述

3. 希尔排序

步骤:

  1. 先选定一个小于N的整数gap作为第一增量,然后将所有距离为gap的元素分在同一组,并对每一组的元素进行直接插入排序。然后再取一个比第一增量小的整数作为第二增量,重复上述操作…
  2. 当增量的大小减到1时,就相当于整个序列被分到一组,进行一次直接插入排序,排序完成。
  /**
     * 希尔排序
     * 时间复杂度:O(N^1.3-N^1.5)
     * 空间复杂度:O(1)
     * 稳定性 : 不稳定的
     *  看在比较的过程当中,是否发生了跳跃式的交换,如果发生了跳跃式的交换 那么就是不稳定的排序
     *  (基本上没有考过)
     *
     * @param array
     * @param gap 组数
     */
    public 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 {
                    // 只要j回退的时候,遇到了比tmp小的元素,就结束这次的比较
                    break;
                }
            }
            //j回退到了 小于0 的地方
            array[j+gap]=tmp;
        }
    }
    public static void shellSort(int[] array){
        int gap=array.length;
        while (gap>1){
            shell(array,gap);
            gap/=2;
        }
        shell(array,1);
    }

动图演示如下:
请添加图片描述

4. 选择排序

思路:
每次从待排序列中选出一个最小值,然后放在序列的起始位置,直到全部待排数据排完即可。

实际上,我们可以一趟选出两个值,一个最大值一个最小值,然后将其放在序列开头和末尾,这样可以使选择排序的效率快一倍。

/**
     * 选择排序
     * 时间复杂度:O(N^2)
     * 空间复杂度:O(1)
     * 稳定性:不稳定的排序
     * @param array
     */
    public static void swap(int[] array,int i,int j){
        int tmp=array[i];
        array[i]=array[j];
        array[j]=tmp;
    }

    //优化选择排序:每次交换都是当前遍历j时候的最小值

    public static void selectSort1(int[] array){
        for (int i = 0; i < array.length; i++) {
            int minIndex=i;
            for (int j = i+1; j < array.length ; j++) {
                if (array[j]<array[minIndex]){
                    minIndex=j;
                }
            }
            swap(array,i,minIndex);
        }

    }

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

动图演示如下 :
请添加图片描述

5. 堆排序

基本原理也是选择排序,只是不在使用遍历的方式查找无序区间的最大的数,而是通过堆来选择无序区间的最大的数。
注意: 排升序要建大堆;排降序要建小堆。

堆排序可以参考之前写的一篇博文:堆详解

也可以借鉴大佬的一篇关于堆排的文章,博主看了受益匪浅:堆排序

/**
     * 堆排序  排升序要建大堆;排降序要建小堆。
     * 时间复杂度 :O(N*logN)
     * 空间复杂度 : O(1)
     * 稳定性:不稳定的
     *
     * @param array
     */
    public static void heapSort(int[] array){
        //1.建堆 O(N)
        creatHeap(array);
        int end=array.length-1;
        //2.交换然后向下调整为大根堆 O(N*logN)
        while (end>0){
            swap(array,0,end);
            shiftDown(array,0,end);
            end--;
        }
    }

    public static void creatHeap(int[] array){
        for (int parent = (array.length-1-1)/2; parent >= 0 ; parent--) {
            shiftDown(array,parent,array.length);
        }
    }

    public static void shiftDown(int[] array,int parent,int len){
        int child=2*parent+1; //左孩子
        while (child<len){
            if (child+1<len && array[child]<array[child+1]){
                child++; //保证child下标,就是左右孩子最大值下标
            }
            if (array[child]>array[parent]){
                swap(array,child,parent);
                parent=child;
                child=2*parent+1;
            }else {
                break;
            }
        }
    }

算法图解 :
请添加图片描述

6 冒泡排序

原理:
在无序区间,通过相邻数的比较,将最大的数冒泡到无序区间的最后,持续这个过程,直到数组整体有序

思路:
排序一趟可以让最大的数字沉底
排序len-1趟,一趟排序len-1-i次
详细实现看代码


    /**
     * 冒泡排序(未优化)
     * 时间复杂度:O(N^2)
     * 空间复杂度:O(1)
     * 稳定性:稳定的排序
     * @param array
     */
    public static void bubbleSort(int[] array){
        for (int i = 0; i < array.length-1; i++) {
            for (int j = 0; j < array.length-1; j++) {
                if (array[j]>array[j+1]){
                    swap(array,j,j+1);
                }
            }

        }
    }


    /**
     * 冒泡排序(优化)
     * 时间复杂度:O(N^2) (最坏的情况)
     * (最好的情况 : 有序)  O(N)
     * 空间复杂度:O(1)
     * 稳定性:稳定的排序
     * @param array
     */

    public static void bubbleSort2(int[] array){
        for (int i = 0; i < array.length-1; i++) {
            boolean flg=false;
            for (int j = 0; j < array.length-1-i; j++) {
                if (array[j]>array[j+1]){
                    swap(array,j,j+1);
                    flg=true;
                }
            }
            if (flg==false){ //没交换的话说明flg没被制成TRUE,则说明已经有序,可以跳出循环了
                break;
            }
        }
    }

动图演示如下 :
请添加图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Java】5大排序算法总结(插入排序+希尔排序+选择排序+堆排序+冒泡排序) 的相关文章

  • string.split("(?!^)") 解释

    我正在尝试将字符串的字符拆分为字符串数组 我找到了解决方案here https stackoverflow com questions 5235401 split string into array of character strings
  • 我需要在 Java 9 中使用哪个模块才能使用 JPA?

    我正在使用一个需要 JPA 的项目测试 Java 9 javax persistence 类 当我添加module info java并声明我的模块 下的所有类javax persistece包变得不可用 我搜索了很多 但找不到在 Java
  • 从SQLite列中获取所有数字字符串并进行总和计算

    我是 Android 和 SQLite 的新手 我在 SQLite 中有一个只有数字的 AMOUNT 列 我可以在 ListView 中显示它 但我无法找到任何我理解的方法来将它们全部添加并显示在 TextView 中 这是数据库助手 im
  • 从 Eclipse 导出后,WAR 文件中缺少一些必要的库 - 为什么?

    我接手了一个大学的项目 其中包含一些 Web 服务 通过将项目导出为 WAR 文件 一些库包含在文件中 例如 Axis2 而另一些则不包含 hibernate JDBC 驱动程序 另外 添加到类路径中的 jar 尚未导出 所有库都位于硬盘驱
  • grails 中的 log4j:如何登录文件?

    我的 grails config groovy 中有这个 log4j 配置 log4j error org codehaus groovy grails web servlet controllers org codehaus groovy
  • 使用 Microsoft REST API - Java 将 Xbox-Live GamerTag 转换为 XUID

    我有一个 Java 应用程序 它需要能够获取用户输入的 Minecraft Bedrock Edition 玩家标签 并将其转换为给定帐户的 XUID 以便我可以将其存储起来以供稍后列入白名单和参考目的 我一直在浏览 Microsoft R
  • 在 Java 中生成 LaTeX 输出 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有用于从 Java 生成 LaTeX 输出的 Java 库 渲染乳胶 JLatex数学 https
  • 无法删除临时文件夹(有时)

    当我启动应用程序时 我创建一个临时文件夹 public static File createTempDir String name throws IOException File tempDir File createTempFile na
  • SwingUtilities.invokeLater

    我的问题与SwingUtilities invokeLater 我应该什么时候使用它 每次需要更新 GUI 组件时都必须使用吗 它到底有什么作用 是否有替代方案 因为它听起来不直观并且添加了看似不必要的代码 Do I have to use
  • 在实现接口的类上强制使用单例模式

    我最好用一个例子来解释这个问题 我有一个接口模型可用于访问数据 模型可以有不同的实现 可以以各种格式表示数据 例如 XMl txt 格式等 Model不关心格式 可以说这样的一个实现是myxml模型 现在我想强迫myxml模型以及其他所有实
  • @Transactional 注解属于哪里?

    如果您将 Transactional in the DAO类和 或其方法 或者注释使用 DAO 对象调用的服务类是否更好 或者注释两个 层 是否有意义 我认为事务属于服务层 它是了解工作单元和用例的人 如果您将多个 DAO 注入到需要在单个
  • Java MYSQL/JDBC 查询从缓存的连接返回过时的数据

    我一直在 Stackoverflow 中寻找答案 但似乎找不到不涉及 Hibernate 或其他数据库包装器的答案 我直接通过 Tomcat 6 Java EE 应用程序中的 MYSQL 5 18 JDBC 驱动程序使用 JDBC 我正在缓
  • Java/Hibernate - 异常:内部连接池已达到其最大大小,当前没有可用的连接

    我第一次在大学项目中使用 Hibernate 而且我还是个新手 我想我遵循了我的教授和我阅读的一些教程给出的所有指示 但我不断收到标题中的异常 Exception in thread main org hibernate Hibernate
  • 为什么 CompletableFuture 的 thenAccept() 不在主线程上运行

    我在 CompletableFuture 的 SupplyAsync 中处理长时间运行的操作 并将结果放入 thenAccept 中 有时 thenAccept 在主线程上执行 但有时它在工作线程上运行 但我只想在主线程上运行 thenAc
  • 尝试通过 Java 8 中的 JDBC-ODBC 连接到 .accdb 文件时出现 ClassNotFoundException

    我正在 Eclipse EE IDE 中的 Java 项目中工作 我必须在其中查询 accdb文件 问题是当我尝试加载驱动程序然后连接到数据库时 它给了我一个异常错误 My code try String filePath myfilepa
  • Java 执行器和长寿命线程

    我继承了一些使用 Executors newFixedThreadPool 4 的代码运行 4 个长寿命线程来完成应用程序的所有工作 这是推荐的吗 我读过Java 并发实践 https rads stackoverflow com amzn
  • Bipush 在 JVM 中如何工作?

    我知道 iload 接受整数 1 到 5 但是如何使用 bipush 指令扩展到更高的数字 特定整数如何与字节码一起存储 有几种不同的指令可用于推送整数常量 最小的是iconst 指令 这些只是一个字节 因为该值是在操作码本身中编码的 ic
  • Swing GUI 出现 IntelliJ 错误“contentPane 无法设置为 null。”从终端编译时

    当我从 IntelliJ 编译我的项目时 没有任何问题 我的程序运行顺利 但是当我尝试使用 javac 从终端编译它时 警告 注意 Victor presentation TableControllerMenu java 使用未经检查或不安
  • 为什么我们不能在函数式接口中重载抽象方法? (爪哇)

    所以我熟悉java中的函数式接口 以及它们与lambda表达式的使用 一个函数式接口只能包含一个抽象方法 当从 lambda 表达式使用这一孤独方法时 您不需要指定其名称 因为接口中只有一个抽象方法 编译器知道这就是您正在引用的方法 Exa
  • RetentionPolicy CLASS 与 RUNTIME

    两者之间有什么实际区别RetentionPolicy CLASS and RetentionPolicy RUNTIME 看起来两者都被记录到字节码中 并且无论如何都可以在运行时访问 无论如何 两者都可以在运行时访问 那不是那个javado

随机推荐

  • python学习小报2--python软件使用的注意事项

    一 命令行基本操作 安装好python之后 可以通过右键windows 选中运行 然后输入cmd进入系统页面 点击确定 进入系统页面 gt gt gt 表示提示符 此时在提示符之后输入python点击回车 即可进入python编程 从图中即
  • 2023年第二届计算与人工智能国际会议(ISCAI 2023)

    会议简介 Brief Introduction 2023年第二届计算与人工智能国际会议 ISCAI 2023 会议时间 2023年10月13 15日 召开地点 中国 上海 大会官网 www iscai org 2023年第二届计算与人工智能
  • 机器学习之基础知识(全)

    目录 1 机器学习概述 1 1 人工智能概述 1 1 1 人工智能使用场景 1 1 2 人工智能小案例 1 2 人工智能发展历程 1 2 1 图灵测试 1 2 2 发展历程 1 2 3 小结 1 3 人工智能主要分支 1 3 1 人工智能
  • RxJS新手入门

    文章目录 1 介绍 2 核心概念 3 基本运作过程 4 RxJS 如何通过运算符过滤资料 5 RxJS 主体物件 Subject 的用法 6 弹珠图 7 如何选择运算符 1 介绍 RxJS 是什么 用一句话类概括就是 RxJS 是用于 Ja
  • Kali Linux没有无线网卡?玩个锤纸~

    Kali Linux没有无线网卡 玩个锤纸 一 USB无限网卡 使用Kali linux 先准备好一个适合Kali系统的USB外置无限网卡 注意内置网卡并不适合渗透测试 Linux系统的指令相对于一般人来说比较晦涩难懂 最好选择免驱动类型
  • 基于Servlet-API型JAVA内存马(filter型、servlet型、listener型)

    前言 常规的木马实际写出落地后容易被检查出来 并且webshell被发现后也就导致我们的行动被发现 很容易造成木马被查杀 利用漏洞被修复 使我们的攻击变得更加艰难 所以内存马的出现与利用无疑是增强了隐蔽性 可以让我们的攻击更加稳定 持久 而
  • eclipse创建web service全过程

    创建Web Service步骤 一 创建服务端工程 1 WebServerTest web 工程 File New Other 选择Dynamic Web Project 配置Tomcat服务器 点击Browse选择Tomcat所在目录 点
  • Anaconda常用命令

    文章目录 一 简介 二 常用命令 2 1管理环境 2 2管理包 三 实践 参考 一 简介 Anaconda是Python环境和包的管理工具 可以给Python创建环境 并在创建的环境中添加需要的包 二 常用命令 Windows打开 Anac
  • 南方科技大学计算机学科评估,全国第四轮学科评估结果公布 我校7个学科进入B类...

    原标题 全国第四轮学科评估结果公布 我校7个学科进入B类 近日 教育部学位与研究生教育发展中心公布了全国第四轮学科评估结果 我校25个参评学科有13个上榜 其中 7个学科进入B类 6个学科进入C类 入选学科数位居省属高校第4位 学科评估是教
  • 基于LU分解的矩阵求逆

    import numpy as np import sys def LU deco inverse m dim m shape 0 E np mat np eye dim L np mat np eye dim U m copy for i
  • 无偏估计的数学证明和分析

    最近学习PCA 在求最大化方差 2 1 P 1
  • 自动化测试高频面试题-90%可能会被问到

    Hello 你们的好朋友九九又又又来了 今天猜猜我给大家带来点啥干货呢 最近很多小伙伴出去面试的时候经常会被问到跟自动化测试相关的面试题 所以 今天九九特意给大家整理了一些经常被公司问到的自动化测试相关的面试题 停 咱先收藏起来好吗 别到时
  • js中过一段时间后终止while循环,防止死循环的方法

    今天发现了一个比较有趣的事 相信很多人遇到过写while循环时 在测试时很容易陷入死循环 导致要关闭页面再重启才能继续测试 那如果频繁调试 就每死循环一次就重启一次 很烦 所以想写一个到一定时间就终止循环的函数 刚开始用setTimeout
  • rhel8订阅注册激活

    先注册账号进行订阅 注册系统 https www howtoing com enable rhel subscription in rhel 8
  • JDK1.8的新特性(详细总结)

    目录 前言 一 jdk8简介 二 Lambda表达式语法 函数式接口 三 jdk8 内置四大核心函数接口 消费型接口 海王式接口 只知道索取 供给型接口 舔狗式接口 只知道付出 不索取回报的 函数型接口 双向奔赴 有输入有输出 断言型接口
  • C语言上机实验思路分享5

    实验内容 方法和步骤 1 编写一个函数 由实参传来一个整数n 将它各个位上的数字逆序输出 例如输入 123 输出为321 2 求方程ax 2 bx c O的根 用3个函数分别求当 b 2 4ac大于0 等于0和小于0时的根 并输出结果 从主
  • js使用AjaxFileupload插件实现文件上传

    最近做项目 需要上传表单元素中的文件POST到目标URL 并把得到的数据显示到本页面上 而不跳转到目标URL 那么 现在就要明确两件事 1 不能直接提交表单 因为一旦点击submit就会自动跳转到action界面 2 可以选择ajax进行异
  • Spring boot 整合 log4j2日志、程序异常,发送邮件通知

    官方文档 https logging apache org log4j 2 x 1 Maven修改如下
  • html 元素平滑滚动到某一位置

    在网上查了大半天 有人用高度算 然后setTimeout的 那个观感真的是差到家了 还有人说用 js动画库的 其实很简单 直接用window scrollTo 这个方法就完事了 回到顶部 window scrollTo top 0 beha
  • 【Java】5大排序算法总结(插入排序+希尔排序+选择排序+堆排序+冒泡排序)

    快速导航 1 稳定性 2 插入排序 3 希尔排序 4 选择排序 5 堆排序 6 冒泡排序 1 稳定性 两个相等的数据 如果经过排序后 排序算法能保证其相对位置不发生变化 则我们称该算法是具备稳定性的排序算法 图中排序后a仍然在b前面 此时这