【HBZ分享】java之二叉堆排序实战代码

2023-10-27

废话不多说,直接上代码,注释都在代码中,利用大顶堆排序(最终数组从小到大),复制即用无需导包

package 大顶堆;

import java.lang.reflect.Array;
import java.util.Arrays;

public class HeapSort {



    public static void sort(int[] source){
        // 第一步: 构建堆,数组下标0不存储
        int[] heap = new int[source.length + 1];

        // 步骤二:待排序数组,构建一个无序堆
        System.arraycopy(source, 0, heap, 1, source.length);


        // 步骤三:堆中元素下沉操作, 长度的一半开始,因为堆的特性,有一半都是叶子节点,叶子之间不需要比较
        // 此处构建出来一个标准大顶堆,大顶堆中的数组其实是无序的
        for(int i = heap.length / 2; i > 0; i--){
            down(heap, i, heap.length - 1);
        }
        System.out.println("大顶堆: " + Arrays.toString(heap));

        // 步骤四:堆排序
        // 记录最大需要排序的索引下标, 因为每一次排序,最后一个都不需要进行比较,因为每一次都会排好一个,而这个会沉到最后
        // 而第一次排序时,所以元素都要进行排序比较,所以需要排序的个数 以及 下标,就是source.length - 1就是全要参与比较
        int maxUnSortIndex = source.length - 1;
        // 循环排序,当排到只剩最后一个时就不用排了
        // 这里为什么还要排序? 因为上面排好的大顶堆中数组是无序的,而我们要的是数组是有序的,所以下面代码就相当于循环获取大顶堆中的元素。
        // 而按照大顶堆取法来说,最上面元素一定是最大的
        // 第一次循环之后,最大值会落到最后一个节点,即数组最后一个
        // 第二次循环,新的最大值(第二大的值)就会落到倒数第二个节点
        // 第三次循环如此往复,就会按照从小到大的顺序排好
        while (maxUnSortIndex != 1){

            // 交换位置,由于是大顶堆,所以把最后一个要排序的节点和第一个交换,然后下沉,从第一个开始下沉
            // 因为大顶堆是大的值在最上面,而我们要的是从小打到排序,所以交换位置后,最大值会落到本次循环总节点数的最后一个节点上,即最大值沉到了最后
            swap(heap, 1, maxUnSortIndex);

            // 每次下沉完毕,本次最后一个元素就排好了,所以要maxUnSortIndex-1个,下次排序循环就不带这个排好的元素了,所以需要排序的元素个数就要-1
            // 减1后,下次循环就会把第二个最大值落到倒数第二个子节点的位置
            maxUnSortIndex--;

            // 继续堆堆顶元素进行下沉,重新堆化,把新的最大值再次放到最上面,然后供下次循环获取
            down(heap, 1, maxUnSortIndex);
        }

        // 把heap中排好序的数组复制到原始数组中
        System.arraycopy(heap, 1, source, 0, source.length);

    }

    /**
     * 堆排序下沉
     * @param heap  堆数组
     * @param k  下标
     * @param range 数组元素总个数
     */
    private static void down(int[] heap, int k, int range) {
        // 存在子节点时再进行while循环
        while (2 * k < range){

            // 存储左右子节点大的那个值的【下标】
            int maxValue;

            // 判断是否存在右节点
            if(2 * k + 1 < range){
                // 比较左右节点大小,【假设左为父,右为子】
                if(childBig(heap, 2 * k, 2 * k + 1)){

                    // 右节点大
                    maxValue = 2 * k + 1;
                }else{
                    // 左节点大
                    maxValue = 2 * k;
                }
            }else{
                // 不存在右子节点,则左节点就是大的值
                maxValue = 2 * k;
            }

            // 把当前k节点和较大的子节点比较
            if(childBig(heap, k, maxValue)){
                // 子节点大则交换父子节点位置
                swap(heap, k, maxValue);

                // 当前节点要下沉一层,则节点下标要更改为子节点的,然后循环继续和孙子节点比较
                k = maxValue;
            }else{
                // 子节点小,则不用再比较了,孙子节点一定更小,直接中断循环
                break;
            }

        }
    }

    /**
     * 比较父子节点大小大小, item[parent]的元素是否小于item[child]元素的大小
     *
     * 这里要多一个heap, 以内之前的大顶堆items是本身类中的,而堆排序是传进来的数组,不带上不行
     */
    public static boolean childBig(int[] heap, int parent, int child){

        // 如果父节点 < 子节点,则返回true,表示需要交换
        return heap[parent] < heap[child];

    }


    /**
     * 交换父子节点元素位置
     * @param heap
     * @param parent
     * @param child
     */
    public static void swap(int[] heap, int parent, int child){

        int temp = heap[parent];
        heap[parent] = heap[child];
        heap[child] = temp;

    }

}


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

【HBZ分享】java之二叉堆排序实战代码 的相关文章

随机推荐

  • Struts2中关于"There is no Action mapped for namespace / and action name"的总结

    参考 http www cnblogs com gulvzhe archive 2011 11 21 2256632 html 今天在调试一个基础的Struts2框架小程序 总是提示 There is no Action mapped fo
  • 深度学习六、图像风格迁移

    所谓图像风格迁移 是指利用算法学习著名画作的风格 然后再把这种风格应用到另外一张图片上的技术 1 图像风格迁移的原理 在学习原始的图像风格迁移之前 可以先回忆一下ImageNet图像识别模型VGGNet 事实上 可以这样理解VGGNet的结
  • 云学python (第5章对象带你飞之储存 上下文管理器pickle 包)《vamei-从Python开始学编程》 笔记

    2 上下文管理器 文件操作常常和上下文管理器一起使用 上下文管理器 context manager 用于规定某个对象的使用范围 一旦进入或者离开该使用范围 则会有特殊操作被调用 比如为对象分配或者释放内存 下面是一段常规的文件操作程序 常规
  • RabbitMq消息收发详解(转)

    消费者有两种接收消息的方法 poll consumer 即拉模式 消费者主动去消息队列拉取消息 push consumer 即推模式 消息队列主动往消费者推送消息 一 消费者通过推 PUSH 方式获取消息 实现push模式最简单的方式就是使
  • Cmake中的Glog用法浅析

    Cmake中的Glog用法浅析 Glog是谷歌开源的C 日志库 用来记录程序运行时的输出信息 这里有几篇关于Glog库用法的博客 网址如下 http blog csdn net chdhust article details 5181337
  • 动态住宅代理VS静态住宅代理,怎么选择?

    现在 越来越多的海外代理服务商均支持动态住宅IP与静态住宅IP 很多小伙伴就疑惑 这二者有什么区别呢 哪个更好 其实 没有哪个更好 只有哪一个更合适您的业务 无论动态住宅IP还是静态住宅IP都来自真实的住宅IP地址 都可以提供IP隐匿作用
  • 电机矢量控制方法

    在工业控制领域 电动机是一个重要的研究方向 发电厂60 的能量都去驱动电动机来为人类服务 可见电机的控制在工业以及军事方面的重要性 电动机分为直流电机和交流电机 而交流电机包括同步交流电机和异步交流电机 同步电动机和异步电动机的区别在于 同
  • 跳出for循环

    跳出for循环有三种方式 1 continue 跳出当次循环 可继续进行下一个循环 function ceshi for var i 0 i lt 6 i if i 3 continue console log i ceshi 效果图 2
  • 如何设计管理员和用户登录界面C语言,管理员登录设计(第7节)

    本文实现管理员登录效果 当用户名和密码正确时 弹出登录成功提示 否则弹出用户名或密码错误提示 今天有以下三大学习任务 学习任务一 了解命名空间的定义 定义 namespace 空间名 类 引用 using 空间名 学习任务二 实现管理员登陆
  • 【micropython】SPI触摸屏开发

    背景 最近买了几块ESP32模块 看了下mircopython支持还不错 所以买了个SPI触摸屏试试水 记录一下使用过程 硬件相关 SPI触摸屏 使用2 4寸屏幕 常见淘宝均可买到 驱动为ILI9341 具体参数如下图 引脚描述 ESP32
  • C++中【字符串】与【整型】和【浮点型】转换攻略

    异想之旅 本人原创博客完全手敲 绝对非搬运 全网不可能有重复 本人无团队 仅为技术爱好者进行分享 所有内容不牵扯广告 本人所有文章仅在CSDN 掘金和个人博客 一定是异想之旅域名 发布 除此之外全部是盗文 C 算法刷题等过程中经常会遇到字符
  • 化工安全生产管理平台:融合重大危险源监控预警、可燃有毒气体检测报警、企业安全风险分区于一体

    产品概述 化工企业安全生产信息化管理平台 以实现化工企业安全生产数字化 信息化 智能化管理为目标 建设融合重大危险源监控预警管理 可燃有毒气体检测报警管理 企业安全风险分区管理 生产人员在岗在位管理和企业生产全流程管理于一体的安全生产信息化
  • 测试从业1到3年经验,常见软件测试工程师面试题总结

    前言 软件测试工程师 和开发工程师相比起来 虽然前期可能不会太深 但是涉及的面还是比较广的 前期面试实习生或者一年左右的岗位 问的也主要是一些基础性的问题比较多 涉及的知识主要有MySQL数据库的使用 Linux操作系统的使用 软件测试框架
  • SpringMVC文件的上传下载&JRebel的使用

    目录 前言 一 JRebel的使用 1 IDea内安装插件 2 激活 3 离线使用 使用JRebel的优势 二 文件上传与下载 1 导入pom依赖 2 配置文件上传解析器 3 数据表 4 配置文件 5 前端jsp页面 6 controlle
  • 【多目标跟踪MOT学习笔记】字节跳动ByteTrack论文研究(一):BYTE策略

    文章目录 前言 一 是什么ByteTrack 二 BYTE 1 BYTE method 概览 2 First Association 关联1 3 Second Association 关联2 4 Post Processing 后处理 4
  • 涅槃重生,BitKeep如何闯出千万用户新起点

    在全球 BitKeep钱包现在已经有超过千万用户在使用 当我得知这个数据的时候 有些惊讶 也有点意料之中 关注BitKeep这几年 真心看得出这家公司的发展之迅速 还记得2018年他们推出第一个版本时 小而美 简洁顺手 他们大胆且略显理想主
  • [非线性控制理论]4_反馈线性化_反步法

    非线性控制理论 1 Lyapunov直接方法 非线性控制理论 2 不变性原理 非线性控制理论 3 基础反馈稳定控制器设计 非线性控制理论 4 反馈线性化 反步法 非线性控制理论 5 自适应控制器 Adaptive controller 非线
  • 【操作系统 · 线程】介绍、分类、多线程

    线程 介绍 分类 多线程 一 介绍 1 进程与线程 2 多线程 3 线程的功能 二 线程分类 1 用户级线程 2 内核级线程 3 其他方案 三 多核 多线程 一 介绍 进程中有两个重要概念 资源所有权 执行 因这一区别 许多操作系统中出现了
  • ueditor1.5 新版ueditor设置字体大小文件所在位置

    ueditor src plugins font js文件 将想添加的字体大小设置即可 fontsize 10 11 12 14 16 18 20 24 36 72
  • 【HBZ分享】java之二叉堆排序实战代码

    废话不多说 直接上代码 注释都在代码中 利用大顶堆排序 最终数组从小到大 复制即用无需导包 package 大顶堆 import java lang reflect Array import java util Arrays public