当前位置:

首页 > 编程开发 > Java数据结构之堆怎么建立

Java数据结构之堆怎么建立

堆的性质堆逻辑上是一棵完全二叉树,堆物理上是保存在数组中。总结:一颗完全二叉树以层序遍历方式放入数组中存储,这种方式的主要用法就是堆的表示。并且如果已知父亲(parent)的下标,则:左孩子(left)下标=2*parent+1;右孩子(right)下标=2*parent+2;已知孩子(不区分左右)(child)下标,则:双亲(parent)下标=(child-1)/2;堆的分类大堆:根节点大于左右两个子节点的完全二叉树(父亲节点大于其子节点),叫做大堆,或者大根堆,或者最大堆。小堆:根节点小于左右两个子

本文目录

    堆的性质

    堆逻辑上是一棵完全二叉树,堆物理上是保存在数组中 。

    Java数据结构之堆怎么建立

    总结:一颗完全二叉树以层序遍历方式放入数组中存储,这种方式的主要用法就是堆的表示。

    并且 如果已知父亲(parent) 的下标,

    则: 左孩子(left) 下标 = 2 * parent + 1;

    右孩子(right) 下标 = 2 * parent + 2;

    已知孩子(不区分左右)(child)下标,则:

    双亲(parent) 下标 = (child - 1) / 2;

    堆的分类

    大堆:根节点大于左右两个子节点的完全二叉树 (父亲节点大于其子节点),叫做大堆,或者大根堆,或者最大堆 。

    Java数据结构之堆怎么建立

    小堆:根节点小于左右两个子节点的完全二叉树叫 小堆(父亲节点小于其子节点),或者小根堆,或者最小堆。

    Java数据结构之堆怎么建立

    堆的向下调整

    现在有一个数组,逻辑上是完全二叉树,我们通过从根节点开始的向下调整算法可以把它调整成一个小堆或者大堆。向下调整算法有一个前提:左右子树必须是一个堆,才能调整。

    以小堆为例:

    1、先让左右孩子结点比较,取最小值。

    2、用较小的那个孩子结点与父亲节点比较,如果孩子结点<父亲节点,交换,反之,不交换。

    3、循环往复,如果孩子结点的下标越界,则说明已经到了最后,就结束。

    Java数据结构之堆怎么建立

    代码示例:

     //parent: 每棵树的根节点
     //len: 每棵树的调整的结束位置
    public void shiftDown(int parent,int len){
            int child=parent*2+1; //因为堆是完全二叉树,没有左孩子就一定没有右孩子,所以最起码是有左孩子的,至少有1个孩子
            while(child

    堆的建立

    给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但是还不是一个堆(左右子树不满足都是大堆或者小堆),现在我们通过算法,把它构建成一个堆(大堆或者小堆)。该怎么做呢?这里我们从倒数的第一个非叶子节点的子树开始调整,一直调整到根节点的树,就可以调整成堆。 这里我们就要用到刚才写的向下调整。

    public void creatHeap(int[] arr){
            for(int i=0;i=0;parent--){//数组下标从0开始
                shiftDown(parent,useSize);
            }
        }

    建堆的空间复杂度为O(N),因为堆为一棵完全二叉树,满二叉树也是一种完全二叉树,我们用满二叉树(最坏情况下)来证明。

    Java数据结构之堆怎么建立

    堆得向上调整

    现在有一个堆,我们需要在堆的末尾插入数据,再对其进行调整,使其仍然保持堆的结构,这就是向上调整。

    以大堆为例:

    Java数据结构之堆怎么建立

    代码示例:

    public void shiftup(int child){
            int parent=(child-1)/2;
            while(child>0){
                if(elem[child]>elem[parent]){
                    int tmp=elem[parent];
                    elem[parent]=elem[child];
                    elem[child]=tmp;
                    child=parent;
                    parent=(child-1)/2;
                }else{
                    break;
                }
            }
        }

    堆的常用操作

    入队列

    往堆里面加入元素,就是往最后一个位置加入,然后在进行向上调整。

    public boolean isFull(){
            return elem.length==useSize;
        }
    public void offer(int val){
            if(isFull()){
                elem= Arrays.copyOf(elem,2*elem.length);//扩容
            }
            elem[useSize++]=val;
            shiftup(useSize-1);
        }

    出队列

    把堆里元素删除,就把堆顶元素和最后一个元素交换,然后向整个数组大小减一,最后向下调整,就删除了栈顶元素。

    public boolean isEmpty(){
            return useSize==0;
        }
    public int poll(){
            if(isEmpty()){
                throw new RuntimeException("优先级队列为空");
            }
            int tmp=elem[0];
            elem[0]=elem[useSize-1];
            elem[useSize-1]=tmp;
            useSize--;
            shiftDown(0,useSize);
            return tmp;
        }

    获取队首元素

    public int peek() {
            if (isEmpty()) {
                throw new RuntimeException("优先级队列为空");
            }
            return elem[0];
        }

    TopK 问题

    给你6个数据,求前3个最大数据。这时候我们用堆怎么做的?

    解题思路:

    1、如果求前K个最大的元素,要建一个小根堆。

    2、如果求前K个最小的元素,要建一个大根堆。

    3、第K大的元素。建一个小堆,堆顶元素就是第K大的元素。

    4、第K小的元素。建一个大堆,堆顶元素就是第K大的元素。

    例子

    举个例子:求前n个最大数据

    Java数据结构之堆怎么建立

    代码示例:

     public static int[] topK(int[] array,int k){
            //创建一个大小为K的小根堆
            PriorityQueue minHeap=new PriorityQueue<>(k, new Comparator() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o1-o2;
                }
            });
            //遍历数组中元素,将前k个元素放入队列中
            for(int i=0;itop){
                        //先弹出后存入
                        minHeap.poll();
                        minHeap.offer(array[i]);
                    }
                }
            }
            //将堆中元素放入数组中
            int[] tmp=new int[k];
            for(int i=0;i< tmp.length;i++){
                int top=minHeap.poll();
                tmp[i]=top;
            }
            return tmp;
        }
        public static void main(String[] args) {
            int[] array={12,8,23,6,35,22};
            int[] tmp=topK(array,3);
            System.out.println(Arrays.toString(tmp));
        }

    结果:

    Java数据结构之堆怎么建立

    数组排序

    再者说如果要对一个数组进行从小到大排序,要借助大根堆还是小根堆呢?

    ---->大根堆

    Java数据结构之堆怎么建立

    代码示例:

      public void heapSort(){
            int end=useSize-1;
            while(end>0){
                int tmp=elem[0];
                elem[0]=elem[end];
                elem[end]=tmp;
                shiftDown(0,end);//假设这里向下调整为大根堆
                end--;
            }
        }
    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Java
    相关文章 更多
    Java单元测试入门:使用JUnit 5编写第一个测试用例
    Java单元测试入门:使用JUnit 5编写第一个测试用例

    面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

    Java变量未初始化报错解析:局部变量与成员变量默认值差异
    Java变量未初始化报错解析:局部变量与成员变量默认值差异

    深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

    详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

    Java中final与static final常量的定义及初始化规则
    Java中final与static final常量的定义及初始化规则

    深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

    Java抽象方法与接口方法的区别及选型建议
    Java抽象方法与接口方法的区别及选型建议

    深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

    Java实现HTTP请求与JSON解析的完整代码示例
    Java实现HTTP请求与JSON解析的完整代码示例

    本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

    Java递归出现StackOverflowError的原因分析及栈空间优化方案
    Java递归出现StackOverflowError的原因分析及栈空间优化方案

    详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

    Java空指针异常(NPE)的代码排查与修复实例
    Java空指针异常(NPE)的代码排查与修复实例

    针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。