Java数据结构之堆(优先队列)


Posted in Java/Android onMay 20, 2022

堆(优先队列)是一种典型的数据结构,其形状是一棵完全二叉树,一般用于求解topk问题。根据双亲节点大于等于孩子节点或双亲节点小于等于孩子节点,可分为大顶堆和小顶堆,本文实现大顶堆。

根据大顶堆的定义,大顶堆的双亲节点大于等于其孩子节点,堆顶元素最大,对于每一个子树都是一个大顶堆,则从最后一个双亲节点进行调整为大顶堆,一直到根节点,则可构建一个大顶堆。

我们这里采用数组去存储,以heap={3,2,1,5,6,4}为例,需要一个init(int[] heap)初始化方法,从最后一个双亲节点开始将heap逐渐调整为大顶堆,其中需要使用到adjust(int[] heap, int i, int end)方法。

调整过程:从最后一个双亲节点出发,如果以当前双亲节点为根的树不符合大顶堆,则进行调整。

Java数据结构之堆(优先队列)

代码实现如下:

public void init(int[] heap) {
        //从最后一个双亲节点开始调整
        //逐渐往上进行调整
        for (int i = heap.length / 2 ; i > 0 ; i-- ) {
            this.adjust(heap, i, heap.length);
        }
    }

    public void adjust(int[] heap, int i, int end) {
        int j = i << 1;
        while (j <= end) {
            //找到两个孩子节点z中较大的节点
            if (j < end && heap[j - 1] < heap[j]) {
                j = j + 1;
            }
            //如果较大节点还小于根节点,则以当前节点为根节点的
            //二叉树已经是大顶堆,不需要进行调整
            if (heap[i - 1] > heap[j - 1]) {
                break;
            }
            //进行调整,将当前节点换到较大位置,再从当前位置进行调整
            int temp = heap[i - 1];
            heap[i - 1] = heap[j - 1];
            heap[j - 1] = temp;
            i = j;
            j = i << 1;
        }
    }

构建好了大顶堆之后,我们如何求得topk呢,此时堆顶元素为top1,我们只需要将top1元素拿走,将剩下元素调整为大顶堆,k次之后即可得到topk。

具体过程:我们将堆顶元素与最后一个元素进行交换,然后将堆顶到倒数第二个元素进行调整,依次类推。

Java数据结构之堆(优先队列)

以leetcode215数组中第k个最大元素为例:

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素

public int findKthLargest(int[] nums, int k) {
        this.init(nums);
        //找到第k大的数
        int end = nums.length;
        while (k > 1) {
            //将当前堆顶元素放到末尾,进行堆调整
            int temp = nums[0];
             nums[0] = nums[end - 1];
             nums[end - 1] = temp;
             end = end - 1;
             -- k;
             this.adjust(nums, 1, end);
        }
        return nums[0];
    }

Java数据结构之堆(优先队列)

此外,Java本身提供了优先队列集合类,但是对于这个题目效率不如自己实现的高

public int findKthLargest(int[] nums, int k) {
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(k);
        for (int num : nums) {
            if (priorityQueue.size() == k) {
                if (num > priorityQueue.peek()) {
                    priorityQueue.poll();
                    priorityQueue.add(num);
                }
                continue;
            }
            priorityQueue.add(num);
        }
        return priorityQueue.poll();
    }

Java数据结构之堆(优先队列)

到此这篇关于Java数据结构之堆(优先队列)的实现的文章就介绍到这了,更多相关Java 堆内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!


Tags in this post...

Java/Android 相关文章推荐
springboot中一些比较常用的注解总结
Jun 11 Java/Android
SpringCloud Alibaba项目实战之nacos-server服务搭建过程
Jun 21 Java/Android
Java循环队列与非循环队列的区别总结
Jun 22 Java/Android
mybatis 解决从列名到属性名的自动映射失败问题
Jun 30 Java/Android
JavaWeb Servlet实现网页登录功能
Jul 04 Java/Android
Java 语言中Object 类和System 类详解
Jul 07 Java/Android
dubbo集成zipkin获取Traceid的实现
Jul 26 Java/Android
Android基于Fresco实现圆角和圆形图片
Apr 01 Java/Android
Flutter Navigator 实现路由传递参数
Apr 22 Java/Android
springcloud整合seata
May 20 Java/Android
SpringBoot使用AOP实现统计全局接口访问次数详解
Jun 16 Java/Android
Java获取字符串编码格式实现思路
Sep 23 Java/Android
Java中Dijkstra(迪杰斯特拉)算法
Android Studio实现带三角函数对数运算功能的高级计算器
May 20 #Java/Android
springcloud整合seata
springboot读取nacos配置文件
May 20 #Java/Android
Android studio 简单计算器的编写
May 20 #Java/Android
mybatis 获取更新记录的id
May 20 #Java/Android
Android Studio 计算器开发
May 20 #Java/Android
You might like
DIY实用性框形天线
2021/03/02 无线电
PHP5 安装方法
2007/01/15 PHP
无需重新编译php加入ftp扩展的解决方法
2013/02/07 PHP
php jsonp单引号转义
2014/11/23 PHP
PHP面向对象程序设计之命名空间与自动加载类详解
2016/12/02 PHP
PHP实现的策略模式示例
2019/03/20 PHP
jquery实现marquee效果(文字或者图片的水平垂直滚动)
2013/01/07 Javascript
ExtJS自定义主题(theme)样式详解
2013/11/18 Javascript
Jquery实现动态切换图片的方法
2015/05/18 Javascript
JS实现仿QQ效果的三级竖向菜单
2015/09/25 Javascript
jQuery使用serialize()表单序列化时出现中文乱码问题的解决办法
2016/07/27 Javascript
AngularJS 工作原理详解
2016/08/18 Javascript
AngularJS实现路由实例
2017/02/12 Javascript
浅谈js使用in和hasOwnProperty获取对象属性的区别
2017/04/27 Javascript
nodejs实现超简单生成二维码的方法
2018/03/17 NodeJs
NodeJS服务器实现gzip压缩的示例代码
2018/10/12 NodeJs
element-ui upload组件多文件上传的示例代码
2018/10/17 Javascript
JavaScript装箱及拆箱boxing及unBoxing用法解析
2020/06/15 Javascript
JS的时间格式化和时间戳转换函数示例详解
2020/07/27 Javascript
Python3基础之输入和输出实例分析
2014/08/18 Python
Python实现子类调用父类的方法
2014/11/10 Python
Python 序列化 pickle/cPickle模块使用介绍
2014/11/30 Python
对python中array.sum(axis=?)的用法介绍
2018/06/28 Python
numpy库与pandas库axis=0,axis= 1轴的用法详解
2019/05/27 Python
Python使用tkinter模块实现推箱子游戏
2019/10/08 Python
Python函数的返回值、匿名函数lambda、filter函数、map函数、reduce函数用法实例分析
2019/12/26 Python
解决TensorFlow GPU版出现OOM错误的问题
2020/02/03 Python
Python Opencv实现单目标检测的示例代码
2020/09/08 Python
同程旅游英文网站:LY.com
2018/11/13 全球购物
美国在线艺术商店:HandmadePiece
2020/11/06 全球购物
项目采购员岗位职责
2014/04/15 职场文书
应届毕业生求职信范文
2014/05/08 职场文书
2014幼儿园大班工作总结
2014/11/10 职场文书
六年级学生期末评语
2014/12/26 职场文书
关于Python中*args和**kwargs的深入理解
2021/08/07 Python
Nginx location 和 proxy_pass路径配置问题小结
2021/09/04 Servers