当前位置: 首页 > news >正文

堆(Java实现)

一:堆(PriorityQueue)

1:堆的概念:

如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储 在一个一维数组中,并满足:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,则称为 小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

2:堆的性质

1:堆中某个节点的值总是不大于或不小于其父节点的值;2:堆总是一棵完全二叉树

1:小根堆:

根的值总是小于左子树和右子树,存储结果是采用层序遍历的结果。

2:大根堆

根的值总是大于左子树和右子树,存储结构是采用层序遍历的结果。

3:堆的存储方式

从堆的概念可知,堆是一棵完全二叉树,因此可以层序的规则采用顺序的方式来高效存储,

注意:对于非完全二叉树,则不适合使用顺序方式进行存储,因为为了能够还原二叉树,空间中必须要存储空节点,就会导致空间利用率比较低。

将元素存储到数组中后,可以根据二叉树章节的性质对树进行还原。假设i为节点在数组中的下标,则有:
1:如果i为0,则i表示的节点为根节点,否则i节点的双亲节点为 (i - 1)/2
2:如果2 * i + 1 小于节点个数,则节点i的
左孩子下标为2 * i + 1,否则没有左孩子(左孩子表示方式是:2 * i + 1
3:如果2 * i + 2 小于节点个数,则节点i的右孩子下标为2 * i + 2,否则没有右孩子(右孩子表示方式是:2 * i + 2

4:堆的创建

4.1:采用向下调整的方式创建堆

4.1.1:大根堆(小根堆只需要将下述的if语句代码改为<即可):

初始化数组:

对要排序的数组进行初始化,用userSize代表数组元素的个数,elem数组存储传入的数组元素。

4.1.2:向下调整(shifDown):

从最后一颗子树开始调整为大根堆,假设最后一棵树的根节点为parent,然后从parent所在的子树开始逐一调整,没调整一颗树parent就parent--,parent然后跳转到倒数第二课树,然后再将此树调整为大根堆。parent=(userSize-1-1)/2

注意:已知孩子节点下标为i 则双亲节点的值是多少?(i-1)/2
已知父亲节点下标为i
左孩子:2*i+1;右孩子:2*i+2

那么,siftDown方法如何编写呢,siftDown方法实现的是根节点与子节点的最大时比较,然后parent与子节点中的最大值交换位置,这样就实现了子树的大根堆。

swap方法是任意两个传过来的节点都可以交换位置,不只parent节点和child节点:


整个过程:

shifDown时间复杂度分析:

从根一路比较到叶子,比较的次数为完全二叉树的高度,即时间复杂度为logN

4.1.3:建根的时间复杂度

向上调整(shifUp):

向上调整是接收一个孩子节点的参数的位置,然后确定这个孩子节点的根节点parent,然后逐一遍历调整。

5:堆的插入(offer):

首先判断是否数组已满,已满扩容,然后在堆的末尾节点添加要插入val值,采用shifUp的形式对堆进行排序。
也可以直接用offer插入方法直接建大根堆,数组一开始为空,一个一个插入,然后一个一个调整。

6.堆的删除(delete)

注意:堆的删除一定删除的是堆顶元素。具体如下:
1:将堆顶元素对堆中最后一个元素交换
2:将堆中有效数据个数减少一个
3:对堆顶元素进行向下调整

二 : 用接口介绍:

 PriorityQueue的特性:

Java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的,主要介PriorityQueue。

三:top-k问题:最大或者最小的前k个数据。

设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。

求前k个最小的

1:整体排序

2:建立大小为k的小根堆

3:把前k个元素创建为大根堆,遍历剩下的N-k个元素,和堆顶比较,如果比堆顶小,则把堆顶删除,当前元素插入

第二种方法实现:

直接建立小根堆,然后poll出前k个即可。

第三种方法的实现:

四:堆的应用

4.1 PriorityQueue的实现

用堆作为底层结构封装优先级队列

4.2 堆排序

堆排序即利用堆的思想来进行排序,总共分为两个步骤

1:建堆
升序:   建大堆
降序:   建小堆
2:利用堆删除思想来进行排序

建堆和堆删除中都用到了向下调整,因此掌握了向下调整,就可以完成堆排序

http://www.xdnf.cn/news/1274455.html

相关文章:

  • Spark学习(Pyspark)
  • 整数规划-分支定界
  • 【软件测试】BUG篇 — 详解
  • ATF(TF-A)安全通告 TFV-13(CVE-2024-7881)
  • 33.搜索旋转排序数组
  • ECharts 的理解和简单应用笔记
  • Gin vs Beego vs Echo:三大主流 Go Web 框架深度对比
  • 使用Blender可视化多传感器坐标系转换
  • sqli-labs-master/Less-51~Less-61
  • 文件 IO
  • MySQL 子查询
  • 大模型时代的机器人研究趋势:从多模态融合到高效迁移
  • Flutter 与 Android NDK 集成实战:实现高性能原生功能
  • wordpress文章摘要调用的3种方法
  • AI(1)-神经网络(正向传播与反向传播)
  • String AOP、事务、缓存
  • Java数据结构——LinkedList
  • Python与MySQL数据库交互实践:自动化数据插入系统
  • Radiology:经颅交流电刺激调节轻度阿尔茨海默病皮层与海马功能连接
  • 【Docker实战】将Django应用容器化的完整指南
  • YOLOv8算法改进--通过yaml文件添加注意力机制【附代码】
  • 从Redisson源码角度深入理解Redis分布式锁的正确实现
  • JavaScript垃圾回收机制
  • 106-基于Flask的重庆充电桩投建数据可视化分析系统
  • Redis 监控与优化方案(C++项目)
  • ShadowKV 机制深度解析:高吞吐长上下文 LLM 推理的 KV 缓存“影子”方案
  • WSL创建虚拟机配置VNC
  • ADK【4】内置前端调用流程
  • Python数据分析常规步骤整理
  • [论文阅读] 人工智能 + 软件工程 | 大型语言模型对决传统方法:多语言漏洞修复能力大比拼