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

Java——堆

目录

  • 一、什么是堆
  • 二、堆的存储方式
  • 三、堆的创建
    • 向下调整
    • 向上调整
  • 四、堆的时间复杂度
  • 五、堆的插入与删除
  • 常见习题
  • 完整代码

一、什么是堆

九月在老家是收割水稻的月份,每次打完水稻,农民伯伯就会拿稻杆累成一堆。我觉得这个稻杆堆和数据结构 外形有点相似哈。
在这里插入图片描述堆是一棵完全二叉树, 但是这个完全二叉树要满足条件:其中任意一个结点要 >= 其左孩子结点和有孩子结点,这叫大根堆;其中任意一个结点要 <= 其左孩子结点和有孩子结点,这叫小根堆。
堆的逻辑结构是一棵完全二叉树,但是其所有的元素是按完全二叉树的层序存储在一个一维数组当中的(物理结构是一维数组)。
在这里插入图片描述

二、堆的存储方式

堆是一棵完全二叉树,因此可以层序的规则采用顺序的方式来高效存储。对于非完全二叉树,则不适合使用顺序方式进行存储。
在这里插入图片描述
那么对于存储到数组中的堆,也要会还原成二叉树。
对于数组中的下标i

  • 如果i=0,则i表示为根节点,否则i结点的双亲为(i-1)/ 2
  • 对于i,如果 i * 2 + 1 小于数组的长度,则i的左孩子为 i * 2 + 1,否则无左孩子。
  • 对于i,如果 i * 2 + 2 小于数组的长度,则i的右孩子为 i * 2 + 2,否则无右孩子。

三、堆的创建

堆的创建有两种方式:向下调整和向上调整。

向下调整

对于一个不是堆的任意一个数组,采用向下调整为大根堆 我们可以这样做:
先调整最下面的每一层子二叉树变大根堆,再一层一层往上面调整,那么整棵树到最后也就变为大根堆了。

  • 1.先找到最后一个根结点 (叫child结点),再找child的父节点(叫parent 结点)。
  • 2.比较父结点与 左右孩子结点中最大的孩子结点的大小,如果大于最大孩子结点则不交换,小于则交换两结点 parent=child,child=child*2+1 同时child 要在数组有效数据的范围内。
  • parent - -,重复2,parent要在数组范围内。
    在这里插入图片描述
public class TestHeap {//堆存在一维数组elem中public int[] elem;//堆中的元素个数public int usedSize;public TestHeap() {this.elem = new int[10];}//先初始化数组public void  initElem(int[] array) {for (int i = 0; i < array.length; i++) {this.elem[i] = array[i];usedSize++;}}//创建堆public void createHeap() {//先调整最下面的每一层子二叉树变大根堆,再一层一层往上面调整。for (int parent = (elem.length-1-1)/2; parent >= 0 ;parent--) {siftDown(parent,this.usedSize);}}
//向下调整private void siftDown(int parent, int usedSize) {int child = parent*2+1;// child要在堆内while(child<usedSize) {//求出左右孩子中最大的孩子if(child+1<usedSize && elem[child]<elem[child+1]) {child++;}if(elem[child]>elem[parent]) {//大于就交换int tmp = elem[parent];elem[parent] = elem[child];elem[child] = tmp;//再看下其孩子树是否要交换parent = child;child = 2 * parent + 1;}else {break;}}}//打印elem数组public void printElem() {System.out.println(Arrays.toString(elem));}public static void main(String[] args) {int[] arr = {27,15,19,18,28,34,65,49,25,37};TestHeap heap = new TestHeap();heap.initElem(arr);heap.createHeap();heap.printElem();}}

如果想要得到小根堆,就只需求得左右孩子最小,在与父结点相比,如果父结点大则交换,否则不交换。

向上调整

因为向上调整是堆的插入的一个步骤,所以在后面写到。

四、堆的时间复杂度

向下调整建堆的时间复杂度为O(n)。向下调整建堆也是一般常用的建堆方法。
在这里插入图片描述
向上调整建堆的时间复杂度为O(n*log n )
在这里插入图片描述

五、堆的插入与删除

堆的插入:

    1. 先将元素插入到数组的后面(二叉树的最后一个元素),如果数组空间不够,则需扩容。
    1. 将最后新插入的节点向上调整,直到满足堆的性质。

在这里插入图片描述
向上调整为大根堆我们可以这样做:

  • 1.先找到最后一个根结点 (叫child结点),再找child的父节点(叫parent 结点)。
  • 2.比较父结点与 左右孩子结点中最大的孩子结点的大小,如果大于最大孩子结点则不交换,小于则交换两结点 child = parent,parent=(parent-1)/2 同时child 要>0。
//插入数据
public void push(int val) {if(isFull()) {this.elem = Arrays.copyOf(elem,elem.length*2);}elem[this.usedSize] = val;siftUp(usedSize);this.usedSize++;}
//向上调整private void siftUp(int usedSize) {int child = usedSize;int parent = (usedSize-1)/2;while(parent>=0) {if(elem[child]>elem[parent]) {int tmp = elem[child];elem[child] = elem[parent];elem[parent] = tmp;child = parent;parent = (parent-1)/2;}else {break;}}}
//判断数组是否满private boolean isFull() {return usedSize==elem.length;}

如果想让向上调整一个不是堆结构的数组为堆,就要一个一个数据的插入。
向上调整也可以调整为小根堆的。

堆的删除
堆的删除一定删除的是堆顶元素。
具体如下:

  1. 将堆顶元素对堆中最后一个元素交换
  2. 将堆中有效数据个数减少一个
  3. 对堆顶元素进行向下调整
    在这里插入图片描述
    在这里插入图片描述

常见习题

1.下列关键字序列为堆的是:()
A: 100,60,70,50,32,65
B: 60,70,65,50,32,100
C: 65,100,70,32,50,60
D: 70,65,100,32,50,60

2.已知小根堆为8,15,10,21,34,16,12,删除关键字8之后需重建堆,在此过程中,关键字之间的比较次数是()
A: 1 B: 2 C: 3 D: 4

3.最小堆[0,3,2,5,7,4,6,8],在删除堆顶元素0之后,其结果是()
A: [3,2,5,7,4,6,8]
B: [2,3,5,7,4,6,8]
C: [2,3,4,5,7,8,6]
D: [2,3,4,5,6,7,8]

[参考答案]
1.A
2.C
在这里插入图片描述
3.C

完整代码

package Tree;import java.util.Arrays;public class TestHeap {public int[] elem;public int usedSize;public TestHeap() {this.elem = new int[10];}public void  initElem(int[] array) {for (int i = 0; i < array.length; i++) {this.elem[i] = array[i];usedSize++;}}public void createHeap() {for (int parent = (elem.length-1-1)/2; parent >= 0 ;parent--) {siftDown(parent,this.usedSize);}}//向下调整private void siftDown(int parent, int usedSize) {int child = parent*2+1;while(child<usedSize) {if(child+1<usedSize && elem[child]<elem[child+1]) {child++;}if(elem[child]>elem[parent]) {int tmp = elem[parent];elem[parent] = elem[child];elem[child] = tmp;parent = child;child = 2 * child + 1;}else {break;}}}//简单打印数组public void printElem() {System.out.println(Arrays.toString(elem));}//插入元素public void push(int val) {if(isFull()) {this.elem = Arrays.copyOf(elem,elem.length*2);}elem[this.usedSize] = val;siftUp(usedSize);this.usedSize++;}//向上调整private void siftUp(int usedSize) {int child = usedSize;int parent = (usedSize-1)/2;while(parent>=0) {if(elem[child]>elem[parent]) {int tmp = elem[child];elem[child] = elem[parent];elem[parent] = tmp;child = parent;parent = (parent-1)/2;}else {break;}}}public boolean isFull() {return usedSize==elem.length;}//出堆头元素public int poll() {if(isEmpty()) {return -1;// 抛出异常}int tmp = elem[usedSize-1];elem[usedSize-1] = elem[0];elem[0] = tmp;usedSize--;siftDown(0,usedSize);return tmp;}public boolean isEmpty() {return usedSize==0;}//取堆头元素public int peek() {if(isEmpty()) {return -1;}return elem[0];}public static void main(String[] args) {int[] arr = {27,49,65,25,37,34,19,18,15,28};TestHeap heap = new TestHeap();heap.initElem(arr);heap.createHeap();heap.printElem();//80入堆heap.push(80);heap.printElem();//80出堆heap.poll();heap.printElem();}}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 路灯集中控制器与智慧照明:塑造未来城市的智能光影
  • 亦菲喊你来学机器学习(20) --PCA数据降维
  • 江协科技stm32————11-5 硬件SPI读写W25Q64
  • explicit 的作用(如何避免编译器进行隐式类型转换)
  • 并发编程:synchronized 关键字
  • 【Linux】Linux 可重入函数
  • 0.ffmpeg面向对象oopc
  • 项目实战系列三: 家居购项目 第五部分
  • C++ STL-Map容器从入门到精通详解
  • HarmonyOs DevEco Studio小技巧9--翻译软件
  • 怎么利用XML发送物流快递通知短信
  • qml Component 组件
  • 【设计模式】设计模式的八大原则
  • 无线麦克风哪个品牌音质最好?十大音质最好的麦克风品牌推荐
  • Lua5.3 参考手册
  • ----------
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • Android开发 - 掌握ConstraintLayout(四)创建基本约束
  • Hibernate【inverse和cascade属性】知识要点
  • js数组之filter
  • Quartz初级教程
  • Unix命令
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 产品三维模型在线预览
  • 汉诺塔算法
  • 学习Vue.js的五个小例子
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 云栖大讲堂Java基础入门(三)- 阿里巴巴Java开发手册介绍
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • ​如何使用QGIS制作三维建筑
  • ‌U盘闪一下就没了?‌如何有效恢复数据
  • (1)(1.19) TeraRanger One/EVO测距仪
  • (1)Android开发优化---------UI优化
  • (173)FPGA约束:单周期时序分析或默认时序分析
  • (C++)八皇后问题
  • (C语言)球球大作战
  • (day 12)JavaScript学习笔记(数组3)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第13章第1节 (全局数据、栈和堆)
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (补)B+树一些思想
  • (分类)KNN算法- 参数调优
  • (规划)24届春招和25届暑假实习路线准备规划
  • (汇总)os模块以及shutil模块对文件的操作
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (一)appium-desktop定位元素原理
  • (一)RocketMQ初步认识
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)大型网站的系统架构
  • (自适应手机端)行业协会机构网站模板
  • ***通过什么方式***网吧
  • .NET Core IdentityServer4实战-开篇介绍与规划