算法 堆排序 heapSort

2023-11-05

堆排序 heapSort

堆是一种数据结构,一种叫做完全二叉树的数据结构。
堆排序是利用堆数据结构而设计的一种排序算法,堆排序是一种选择排序,
其最坏,最好,平均时间复杂度均为O(nlogn),同时也是不稳定排序。

堆的性质

这里我们用到两种堆,其实也算是一种。

大顶堆:每个节点的值都大于或者等于它的左右子节点的值。
对于大顶堆:arr[i] >= arr[2i + 1] && arr[i] >= arr[2i + 2]

小顶堆:每个节点的值都小于或者等于它的左右子节点的值。
对于小顶堆:arr[i] <= arr[2i + 1] && arr[i] <= arr[2i + 2]

堆排序的基本思想是:

  • 1、将带排序的序列构造成一个大顶堆,根据大顶堆的性质,当前堆的根节点(堆顶)就是序列中最大的元素;
  • 2、将堆顶元素和最后一个元素交换,然后将剩下的节点重新构造成一个大顶堆;
  • 3、重复步骤2,如此反复,从第一次构建大顶堆开始,每一次构建,我们都能获得一个序列的最大值,然后把它放到大顶堆的尾部。
  • 最后,就得到一个有序的序列了。
// 大顶堆 升序
public static void main(String[] args) {
        int[] arr = new int[]{5, 2, 15, 9, 60, 10, 30, 8, 2, 3, 11};
        heapSort(arr);

        System.out.println(Arrays.toString(arr));
    }

    public static void heapSort(int[] arr) {
        if (arr == null || arr.length == 0) {
            return;
        }

        int len = arr.length;

        buildMaxHeap(arr, len);

        // 最大值放到最后一位
        for (int i = len - 1; i > 0; i--){
            swap(arr, i, 0);

            len--;
            adjust(arr, 0, len);
        }

    }

    /**
     * 创建大顶堆
     * 使每层父节点大于子节点
     * @param arr
     * @param len
     */
    private static void buildMaxHeap(int[] arr, int len) {
        for (int i = len / 2 - 1; i >= 0; i--) {
            adjust(arr, i, len);
        }
    }

    /**
     * 堆交换
     * @param arr
     * @param i
     * @param len
     */
    private static void adjust(int[] arr, int i, int len) {
        int l = 2 * i + 1;
        int r = 2 * i + 2;
        // 默认当前节点为最大节点
        int m = i;

        // 与子节点比较,交换最大节点下标
        if(l < len && arr[l] > arr[m]){
            m = l;
        }
        if(r < len && arr[r] > arr[m]){
            m = r;
        }

        if(m != i){
            swap(arr, i, m);
            // 最大节点发生改变,继续改变节点与子节点的大小
            adjust(arr, m, len);
        }
    }

    /**
     * 元素交换
     * @param arr
     * @param x
     * @param y
     */
    private static void swap(int[] arr, int x, int y){
        arr[x] += arr[y];
        arr[y] = arr[x] - arr[y];
        arr[x] -= arr[y];
    }

// 小顶堆 降序
public static void main(String[] args) {
        int[] arr = new int[]{5, 2, 15, 9, 60, 10, 30, 8, 2, 3, 11};
        heapSort(arr);

        System.out.println(Arrays.toString(arr));
    }

    private static void heapSort(int[] arr){
        if(arr == null || arr.length <= 0){
            return;
        }
        int len = arr.length;

        // 创建堆 使每层父节点小于子节点
        buildMinHeap(arr, len);
        // 数据交换
        for (int i = len - 1; i > 0; i--){
            swap(arr, i, 0);
            len--;
            adjust(arr, 0, len);
        }

    }

    private static void buildMinHeap(int[] arr, int len){
        for (int i = len / 2 - 1; i >= 0; i--) {
            adjust(arr, i, len);
        }
    }

    private static void adjust(int[] arr, int i, int len){
        int l = 2 * i + 1;
        int r = 2 * i + 2;
        int m = i;

        if(l < len && arr[l] <= arr[m]){
            m = l;
        }
        if(r < len && arr[r] <= arr[m]){
            m = r;
        }

        if(m != i){
            swap(arr, m, i);
            adjust(arr, m, len);
        }

    }

    private static void swap(int[] arr, int x, int y){
        arr[x] += arr[y];
        arr[y] = arr[x] - arr[y];
        arr[x] -= arr[y];
    }

参考:
堆排序

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

算法 堆排序 heapSort 的相关文章

  • 如何在java swing中的每个页面中打印带有页脚的整个JPanel

    好吧 这可能很简单 但想不通 我有一个包含 JTable 的 JPanel JTable 包含很少的行 有时更多 因为我推入其中的表模型取决于数据库 但是 我不使用任何包含 JTable 的 JScolpane 因此 当 JTable 包含
  • 在 Kotlin 中实现返回 Collection 的 Java 方法

    我将 Kotlin 与 Spring Security 结合使用 实现该方法时 public interface UserDetails extends Serializable Collection
  • 使用 Java 编程式 HTML 文档生成

    有谁知道如何在 Java 中以编程方式生成 HTMLDocument 对象 而不需要在外部生成字符串 然后使用 HTMLEditorKit read 来解析它 我问的两个原因 首先 我的 HTML 生成例程需要非常快 并且我认为将字符串解析
  • 使用 jdbc 程序连接到 Open Office odb 文件

    我编写了以下代码来连接到 OpenOffice db String db C Documents and Settings hkonakanchi Desktop Test odb Class forName org hsqldb jdbc
  • 如何在Spring的applicationContext.xml中指定默认范围来请求范围?

    我想让所有 bean 请求默认作用域 但是 Spring 文档说默认作用域是 Singleton 第 3 4 1 和 3 4 2 节http static springsource org spring docs 2 5 x referen
  • Java 的 QP 求解器 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Vertx HttpClient getNow 不工作

    我的 vertx HttpClient 有问题 下面的代码显示使用 vertx 和纯 java 测试 GET Vertx vertx Vertx vertx HttpClientOptions options new HttpClientO
  • java JFileChooser 文件大小过滤器

    我知道我可以按文件类型进行过滤 但是可以按文件大小进行过滤吗 例如 JFileChooser 仅显示 3 MB 以内的图片 简短的回答应该是 你尝试过什么 长答案是肯定的 JFileChooser fc new JFileChooser f
  • grails 上的同步块在 Windows 上有效,但在 Linux 上无效

    我有一个 grails 应用程序 它依赖于服务中的同步块 当我在 Windows 上运行它时 同步按预期工作 但当我在 ams linux 上运行时 会出现 StaleObjectStateException 该问题在以下示例中重现 cla
  • Java G1 GC 处理引用对象运行缓慢

    我已经在 J ava 上运行了计数器 它24小时工作 每秒点击通过100次左右 白天 GC 处理时间从 20 60 毫秒缓慢上升到 10000 60000 毫秒 然后下降到 20 60 毫秒 这种模式不时地重复 从 GC 日志中我发现 GC
  • java 属性文件作为枚举

    是否可以将属性文件转换为枚举 我有一个包含很多设置的属性文件 例如 equipment height equipment widht equipment depth and many more like this and not all a
  • Java中的DRY原则[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我一直在读关于DRY https en wikipedia org wiki Don 27t repeat yourself原则 虽然看起来
  • 字节码和位码有什么区别[重复]

    这个问题在这里已经有答案了 可能的重复 LLVM 和 java 字节码有什么区别 https stackoverflow com questions 454720 what are the differences between llvm
  • 存储过程将多个表返回到 spring jdbc 模板

    我正在使用 JdbcTemplate 从 Spring DAO 类调用存储过程 我的问题是 存储过程返回多个表 有没有办法使用 Spring JdbcTemplate 访问多个表 如果我使用jdbcTemplate queryForList
  • RMI 服务器:rmiregistry 或 LocateRegistry.createRegistry

    对于服务器端的RMI 我们需要启动吗rmiregistry程序 或者只是调用LocateRegistry createRegistry 如果两者都可以的话 各有什么优点和缺点 他们是同一件事 rmiregistry是一个单独的程序 您可以从
  • Java SE + Spring Data + Hibernate

    我正在尝试使用 Spring Data Hibernate 启动 Java SE 应用程序 并且到目前为止已经完成了以下操作 配置文件 Configuration PropertySource classpath hibernate pro
  • 使用 Android 的 Mobile Vision API 扫描二维码

    我跟着这个tutorial http code tutsplus com tutorials reading qr codes using the mobile vision api cms 24680关于如何构建可以扫描二维码的 Andr
  • Java 9 中紧凑字符串和压缩字符串的区别

    有什么优点紧凑的字符串 http openjdk java net jeps 254JDK9 中的压缩字符串 压缩字符串 Java 6 和紧凑字符串 Java 9 都有相同的动机 字符串通常实际上是 Latin 1 因此浪费了一半的空间 和
  • 将隐藏(生物识别)数据附加到 pdf 上的数字签名

    我想知道是否可以使用 iText 我用于签名 或 Java 中的其他工具在 pdf 上添加生物识别数据 我会更好地解释一下 在手写板上签名时 我会收集签名信息 例如笔压 签名速度等 我想将这些信息 java中的变量 与pdf上的签名一起存储
  • 如何使用 Spring AOP 建议静态方法?

    在执行类的静态方法之前和之后需要完成一些日志记录 我尝试使用 Spring AOP 来实现这一点 但它不起作用 而对于正常方法来说它起作用 请帮助我理解如何实现这一点 如果可以使用注释来完成 那就太好了 也许您应该在使用 Spring AO

随机推荐

  • Day.js 常用用法

    我认为克服恐惧最好的办法理应是 面对内心所恐惧的事情 勇往直前地去做 直到成功为止 罗斯福 Day js 时间戳转换 const nowTime dayjs format console log 获取当前时间 nowTime const n
  • GPT4来了!微软云能否反超亚马逊夺冠,就靠它了

    文 光锥智能 作者 刘雨琦 Azure 微软云 能否反超AWS 亚马逊云 夺冠 就靠ChatGPT了 今天凌晨 GPT4横空出世 支持图像输入和混合输入 多模态大模型的出现 将对算力产生更高的需求 一场由ChatGPT引发的算力革命 即将给
  • TCP的三次握手(一个好男人追女孩的故事)一看必懂系列

    网络世界如情场 女生指代服务端 在网络协议内 和TCP是纯情男的作风 UDP作风则称为 渣男 理由非常的简单 由于UDP的行为就是从来不会和任何女人产生感情 不建立连接 因此追女生的效率 具有高效率的特性 就比TCP作风高的多 从来不付出
  • 通过U盘向服务器拷贝文件

    目录 完整操作流程 检查U盘是否被识别 gt 挂载U盘 gt 拷贝文件 gt 卸载U盘 检查U盘是否被识别 挂载U盘 拷贝文件 卸载U盘 完整操作流程 检查U盘是否被识别 gt 挂载U盘 gt 拷贝文件 gt 卸载U盘 检查U盘是否被识别
  • 数据结构算法设计——深搜DFS(走迷宫)

    一 什么是深搜 深搜就是 深度搜索 也就是 深度优先的搜索 那什么是 深度优先 呢 我们拿最常见的迷宫问题举例 深度优先就是你照着一条路死命的走 有个形象的说法叫 不撞南墙不回头 一直到这条路走不通了 再返回上一步选择其他的方向 在算法中我
  • Java8 Streams用法总结大全 之 Collector用法详解

    1 前言 在 Java8 Streams用法总结大全 之 Stream中的常见操作 中 我们已经学习了Stream中的常用操作 其中也提到了collect 的用法 当时只是通过入参Collectors toList 实现了把Stream转为
  • [SQL]postgreSQL中如何查找无主键的sql语句

    查找postgreSQL数据库中 查找无主键的表 可以通下面语句查找 select from pg tables where hasindexes is false and schemaname public
  • 新编法学概论--吴祖谋

    新编法学概论 吴祖谋 2007 pdf 介绍法学概论的书籍 但是写的太官僚了 什么阶级论 之类的开头 让我读着那样的不理解 能不能有本写的比较通俗易懂的法学概论 这样的书籍 真心的不喜欢看 但是没办法 还是看一看吧 1 宪法 三次完全的更新
  • 什么是代码区、常量区、静态区(全局区)、堆区、栈区?

    前言 和作者有同样的感觉 对代码区 常量区 静态区 全局区 堆区 栈区没有较深刻的认识 通过查找网络找到本篇比较优秀的文章 特此转发 摘自CSDN https blog csdn net u014470361 article details
  • oracle中translate与replace的使用

    1 translate 语法 TRANSLATE char from to 用法 返回将出现在from中的每个字符替换为to中的相应字符以后的字符串 若from比to字符串长 那么在from中比to中多出的字符将会被删除 三个参数中有一个是
  • OpenCV中的图像腐蚀和膨胀操作有哪些?

    在OpenCV中 图像腐蚀 Erosion 和膨胀 Dilation 是常用的图像形态学操作 它们可以用于去除噪声 填充空洞 提取图像中的结构等 下面是几种常见的腐蚀和膨胀操作 腐蚀操作 图像腐蚀可以通过函数cv2 erode 来实现 腐蚀
  • [Linux Audio Driver] 音频POP音问题归纳总结

    1 板级电容 电感发声 情况就是你设备开机之后 啥也没干 然后听到呲啦刺啦的声音 这种情况我遇到过一次 这个是 不合理的结构设计或者走线导致的 硬件实力挖坑 需要改版解决 2 播放声音长时间有杂音 这个锅我们送给硬件 这个是芯片之间有干扰
  • SVN 启动模式

    首先 在服务端进行SVN版本库的相关配置 手动新建版本库目录 mkdir opt svn 利用svn命令创建版本库 svnadmin create opt svn runoob 使用命令svnserve启动服务 svnserve d r 目
  • java tomcat远程调试端口_tomcat开发远程调试端口以及利用eclipse进行远程调试

    一 tomcat开发远程调试端口 方法1 WIN系统 在catalina bat里 SET CATALINA OPTS server Xdebug Xnoagent Djava compiler NONE Xrunjdwp transpor
  • LeetCode2.两数相加

    给你两个 非空 的链表 表示两个非负的整数 它们每位数字都是按照 逆序 的方式存储的 并且每个节点只能存储 一位 数字 请你将两个数相加 并以相同形式返回一个表示和的链表 你可以假设除了数字 0 之外 这两个数都不会以 0 开头 示例 1
  • 了解VGG网络结构特点,利用VGG完成图像分类

    学习目标 知道VGG网络结构的特点 能够利用VGG完成图像分类 2014年 牛津大学计算机视觉组 Visual Geometry Group 和Google DeepMind公司的研究员一起研发出了新的深度卷积神经网络 VGGNet 并取得
  • 为什么同样是软件测试员,别人拿3万月薪,你却只能拿3千?你反思了没有?

    有人说软件测试入门门槛低 但是为什么同样是软件测试员 别人拿3万元的月薪 你却只能拿3千月薪 有的人只会抱怨 别人运气好 经验足等等 但是有没有去发现一些根本性的东西 最近我就看到一个有意思的视频 我觉得最能体现出软件测试员薪酬为什么区别这
  • 【机器学习】之Anaconda中使用的命令

    操作之前 点击上图入口 进入Prompt 示例是在base环境下 cls清屏 base C Users bubusa gt cls 1 base环境下的操作 1 列出所有虚拟环境 base C Users bubusa gt conda e
  • 浅拷贝&深拷贝

    什么是深 浅拷贝 他们跟赋值有什么关系 浅拷贝 浅拷贝是创建一个新对象 这个对象有着原始对象属性值的一份精确拷贝 如果属性是基本类型 拷贝的就是基本类型的值 如果属性是引用类型 拷贝的就是内存地址 所以如果其中一个对象改变了这个地址 就会影
  • 算法 堆排序 heapSort

    堆排序 heapSort 堆是一种数据结构 一种叫做完全二叉树的数据结构 堆排序是利用堆数据结构而设计的一种排序算法 堆排序是一种选择排序 其最坏 最好 平均时间复杂度均为O nlogn 同时也是不稳定排序 堆的性质 这里我们用到两种堆 其