基础数据结构 -- 堆

1. 简介

        堆可以看做是一种特殊的完全二叉树,它满足任意节点的值都大于或小于其子节点的值。

2. 功能

  • 插入元素:插入新元素时,先将元素放至数组末尾,然后通过上浮算法自底向上调整,使堆保持性质。
  • 删除堆顶元素:删除堆顶元素后,将最后一个元素移至堆顶,然后通过下沉算法自顶向下调整,重新满足堆的性质。
  • 建堆过程:从倒数第一个非叶子节点开始,对每个子树进行向下调整,直至整棵树满足堆的性质。

3. 图解

堆结构:

插入元素:

删除堆顶元素:

4. 实现

        在Java中,堆通常通过数组实现,利用数组的索引来表示节点之间的关系。

具体实现方式如下:

  • 定义一个数组来存储堆的元素。
  • 使用数组下标表示节点的位置,例如根节点的下标为0,左子节点的下标为2 * i + 1,右子节点的下标为2 * i + 2。
  • 在插入元素时,将新元素插入到数组末尾,然后通过上浮操作将其移动到正确的位置。
  • 在删除元素时,将最后一个元素替换到堆顶,然后通过下沉操作将其移动到正确的位置。
  • 堆排序时,将堆顶元素与最后一个元素交换,然后将堆的大小减一,再通过下沉操作将新的堆顶元素移动到正确的位置。

 小根堆代码实现:

public class MinHeap {private int[] data; // 存储堆元素的数组private int size; // 堆的大小public MinHeap(int capacity) {data = new int[capacity];size = 0;}// 返回堆的大小public int getSize() {return size;}// 返回堆是否为空public boolean isEmpty() {return size == 0;}// 返回父节点的索引private int parent(int index) {return (index - 1) / 2;}// 返回左子节点的索引private int leftChild(int index) {return 2 * index + 1;}// 返回右子节点的索引private int rightChild(int index) {return 2 * index + 2;}// 上浮操作private void siftUp(int index) {while (index > 0 && data[parent(index)] > data[index]) {swap(parent(index), index);index = parent(index);}}// 下沉操作private void siftDown(int index) {while (leftChild(index) < size) {int minIndex = leftChild(index);if (rightChild(index) < size && data[rightChild(index)] < data[minIndex]) {minIndex = rightChild(index);}if (data[index] <= data[minIndex]) {break;}swap(index, minIndex);index = minIndex;}}// 交换两个元素的位置private void swap(int i, int j) {int temp = data[i];data[i] = data[j];data[j] = temp;}// 向堆中插入元素public void insert(int value) {if (size == data.length) {throw new IllegalStateException("Heap is full");}data[size] = value;siftUp(size);size++;}// 从堆中删除最小元素(即堆顶元素)public int extractMin() {if (isEmpty()) {throw new IllegalStateException("Heap is empty");}int minValue = data[0];data[0] = data[size - 1];size--;siftDown(0);return minValue;}
}

也有一个偷懒的办法,我们可以通过 Java 内置的 PriorityQueue 类来实现最小堆。通过调用add() 方法可以向堆中插入元素,而通过调用 poll() 方法可以从堆中删除最小元素(即堆顶元素)。

需要注意的是,PriorityQueue  默认实现的是最小堆,如果需要实现最大堆,可以通过传递自定义比较器来实现。例如,使用 PriorityQueue<Integer>(Conleections.reverseOrder()) 来创建一个最大堆。

public class HeapTest {public static void main(String[] args) {// 创建一个最小堆PriorityQueue<Integer> minHeap = new PriorityQueue<>();// 向堆中插入元素minHeap.add(5);minHeap.add(2);minHeap.add(8);minHeap.add(1);minHeap.add(3);System.out.println("最小堆的元素: " + minHeap); // 输出: [1, 2, 8, 5, 3]// 从堆中删除最小元素(堆顶元素)int minElement = minHeap.poll();System.out.println("被删除的最小元素: " + minElement); // 输出: 1System.out.println("删除最小元素后的最小堆: " + minHeap); // 输出: [2, 3, 8, 5]}
}

7. 应用场景

  • 堆排序:利用最大堆或最小堆的性质,可以进行高效的排序操作。堆排序是一种时间复杂度为O(n log n)的排序算法,它通过建堆和反复删除堆顶元素进行排序。
  • 中位数查询:使用最大堆和最小堆可以在O(log n)的时间内查询一组数据的中位数,这对于实时数据分析等领域非常重要。
  • Top K问题:对于一个数据流,需要在其中找到前K大或前K小的元素,可以使用堆来实现。维护一个大小为K的堆,遍历数组,从数组中取出数据与堆顶元素比较,如果比堆顶元素大,则将堆顶元素删除,并将这个元素插入到堆中;如果比堆顶元素小,则不做处理,继续遍历数组。这样等数组中的数据都遍历完之后,堆中的数据就是前K大数据了。

6. 总结

        综上所述,堆是Java中一种非常重要的基础数据结构,它提供了高效的数据插入和删除操作,广泛应用于堆排序、top k问题等场景。理解堆的基本操作和应用,对于开发者来说非常有益,有助于更好地利用这一数据结构来解决实际问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/345982.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

App UI 风格,尽显魅力

精妙无比的App UI 风格

动态内存管理(malloc,calloc,realloc,free)+经典笔试题

动态内存管理 一. malloc 和 free1. malloc2. free 二. calloc三. realloc四.动态内存的错误1.对NULL指针的解引用操作2.对动态开辟空间的越界访问3.对非动态开辟内存使用free释放4.使用free释放一块动态开辟内存的一部分5.对同一块动态内存多次释放6.动态开辟内存忘记释放&…

ROS 获取激光雷达数据(C++实现)

ROS 获取激光雷达数据&#xff08;C实现&#xff09; 实现思路 在机器人ROS系统中&#xff0c;激光雷达通常会有一个对应的节点&#xff0c;这个节点一般是由雷达的厂商提供&#xff0c;我们只需要简单的配置以下端口参数&#xff0c;就能和激光雷达的电路系统建立连接&#…

“安全生产月”专题报道:AI智能监控技术如何助力安全生产

今年6月是第23个全国“安全生产月”&#xff0c;6月16日为全国“安全宣传咨询日”。今年全国“安全生产月”活动主题为“人人讲安全、个个会应急——畅通生命通道”。近日&#xff0c;国务院安委会办公室、应急管理部对开展好2024年全国“安全生产月”活动作出安排部署。 随着科…

单臂路由的配置(思科、华为)

#交换设备 不同vlan属于不同广播域&#xff0c;不能互相通信&#xff0c;他们配置的是不同网段的IP地址&#xff0c;针对不同网段的IP地址进行通信&#xff0c;就需要用到路由技术 实现不同vlan之间的通信技术有两种 单臂路由三层交换 单臂路由 一、思科设备的单臂路由配…

AutoCAD Mechanical机械版专业的计算机辅助设计软件安装包下载安装!

AutoCAD机械版作为一款专业的计算机辅助设计软件&#xff0c;不仅具备卓越的二维绘图功能&#xff0c;更是拥有令人瞩目的3D建模工具&#xff0c;为机械设计师们提供了前所未有的创作空间。 在AutoCAD机械版的3D建模环境中&#xff0c;用户可以借助一系列简洁明了的命令&#…

【EDA】SSTA中最慢路径与最快路径统计计算

假设(X1,X2)为二元高斯随机向量,均值(μ1,μ2),标准差(σ1,σ2),相关系数ρ 定义:X=max(X1,X2),Y=min(X1,X2) SSTA中计算setup/hold的worst delay时即求X、Y,路径N对应维度为N维。 X的概率密度函数PDF为f(x)=f1(-x)+f2(-x),f1和f2为: 其中小Φ和大Φ…

在Linux上的Java项目导出PDF乱码问题

在Linux上的Java项目导出PDF乱码问题 场景&#xff1a;一个Java项目导出PDF&#xff0c;在我本地导出是没有问题&#xff0c;但是部署上Linux上后&#xff0c;导出就出现了乱码了。 处理方案 我这里使用的处理方案是在Linux服务器上安装一些PDF需要使用的字体 1.把字体上传到…

Dell服务器根据GPU温度调整风扇转速

前言 dell服务器自动风扇是根据CPU温度来调速的&#xff0c;我跑AI的时候cpu温度不高但是GPU温度很高导致显卡卡死PVE虚拟机直接挂起无法运行&#xff0c;我看了下也没有基于显卡温度调速的脚本&#xff0c;于是我就自己写了一个 基于ipmi工具 乌班图等linux先安装ipmi apt …

Springboot结合redis实现关注推送

关注推送 Feed流的模式 Timeline:不做内容筛选&#xff0c;简单的按照内容发布时间排序。常用于好友与关注。例如朋友圈的时间发布排序。 优点:信息全面&#xff0c;不会有缺失。并且实现也相对简单 缺点:信息噪音较多&#xff0c;用户不一定感兴趣&#xff0c;内容获取效率…

Transparent 且 Post-quantum zkSNARKs

1. 引言 前序博客有&#xff1a; SNARK原理示例SNARK性能及安全——Prover篇SNARK性能及安全——Verifier篇 上图摘自STARKs and STARK VM: Proofs of Computational Integrity。 上图选自&#xff1a;Dan Boneh 斯坦福大学 CS251 Fall 2023 Building a SNARK 课件。 SNARK…

如何在npm上发布自己的包

如何在npm上发布自己的包 npm创建自己的包 一、一个简单的创建 1、创建npm账号 官网&#xff1a;https://www.npmjs.com/创建账号入口&#xff1a;https://www.npmjs.com/signup 注意&#xff1a;需要进入邮箱验证 2、创建目录及初始化 $ mkdir ufrontend-test $ cd ufron…

Java程序设计————从控制台输入

向控制台输入信息可以借助Scanner扫描器类来实现 语法&#xff1a; Scanner input new Scanner(System.in); 提示 &#xff08;1&#xff09;在使用Scanner类型之前&#xff0c;需要首先指明Scanner类所在的位置&#xff0c;既通过代码 import java.util.Scanner; &…

WordPress 高级缓存插件 W3 Total Cache Pro 详细配置教程

说起来有关 WordPress 缓存插件明月已经发表过不少文章了,但有关 W3 Total Cache Pro 这个 WordPress 高级缓存插件除了早期【网站缓存插件 W3 Total Cache,适合自己的才是最好的!】一文后就很少再提及了,最近因为明月另一个网站【玉满斋】因为某些性能上的需要准备更换缓存…

OpenGauss数据库-5.数据更新

第1关&#xff1a;插入数据 gsql -d postgres -U gaussdb -W "passwd123123" create table student (id integer primary key,name char(20),age integer ); insert into student values(1,"lily",20),(2,lily,21),(3,marry,19); 第2关&#xff1a;删除数…

Nginx | 正向代理与Proxy插件整合

写在前面 &#x1f341;个人主页&#xff1a;微枫Micromaple 在企业开发环境中&#xff0c;局域网内的设备通常需要通过正向代理服务器访问互联网。正向代理服务器充当中介&#xff0c;帮助客户端请求外部资源并返回结果。局域网内也就是我们俗称的内网&#xff0c;局域网外的互…

Qt——控件

目录 概念 QWidget核心属性 enabled geometry WindowFrame的影响 windowTitle windowIcon qrc的使用 windowOpacity cursor font toolTip focusPolicy ​编辑 styleSheet 按钮类控件 PushButton RadioButton CheckBox 显示类控件 Label textFormat pixm…

Flink的简单学习四

一 有状态计算 1.1 概念 1.状态;上一次计算的结果 2.需要基于上一个结果来进行计算&#xff0c;被称为有状态计算 1.2 未使用有状态计算 1.下面这个代码将相同的key发送到同一个task任务里面计算。就是因为这个导致了&#xff0c;明明之前没有输入b&#xff0c;但是输入b之…

Linux 安装ab测试工具

yum -y install httpd-tools ab -help #10个并发连接&#xff0c;100个请求 ab -n 200 -c 100 http://www.baidu.com/

【最新鸿蒙应用开发】——总结ArkUI生命周期

鸿蒙ArkUI相关的生命周期都有哪些? 1. UIAbility生命周期 onCreate、onWindowStageCreate、onForeground、onBackground、onWindowStageDestroy、onDestroy。 onCreate&#xff1a;Create状态为在应用加载过程中&#xff0c;UIAbility实例创建完成时触发&#xff0c;系统会调…