热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

二叉树之堆

TopK问题现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构&#x

TopK问题
在这里插入图片描述
现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。

1 、堆的概念


  • 堆中某个节点的值总是不大于或不小于其父节点的值;
  • 堆总是一棵完全二叉树。
  • 按照层序遍历的结果储存在数组中
  • 堆的基本作用是快速找集合中的最值
    在这里插入图片描述

2、堆的实现


2.1堆向下调整建大堆

前提:左右子树必须已经是一个堆,才能调整,即只有一个不满足堆的性质

//向下调整建大堆private static void CreateBig(int[] arr, int index) {//index就是要调整的parentint max &#61; index * 2 &#43; 1;/*** 保证有右孩子&#xff0c;再比较* 不是叶子结点&#xff0c;一定有左孩子&#xff0c;但不一定有右孩子* (1)没有右孩子&#xff0c;左边大* (2)有右孩子&#xff0c;左边大或者右边大* *///当有左孩子时执行以下while (max < arr.length) {//如果有右孩子&#xff0c;并且右孩子大于左孩子&#xff0c;改变max的值if (max &#43; 1 < arr.length && arr[max &#43; 1] > arr[max]) {max&#43;&#43;;}//判断交换调整//当parent小于孩子时交换&#xff0c;否则不执行if (arr[index] < arr[max]) {int t &#61; arr[max];arr[max] &#61; arr[index];arr[index] &#61; t;//改变index的max的值&#xff0c;使循环继续index &#61; max;max &#61; 2 * index &#43; 1;} else {break;}}}

2.2堆向下调整建小堆

//向下调整&#xff0c;建小堆private static void CreateSmall(int[] arr, int index) {//左孩子下标&#xff0c;代表 index 的最小值孩子的下标int min &#61; index * 2 &#43; 1;//1.有叶子结点while (min < arr.length) {//2.保证有右孩子的前提下&#xff0c;右孩子比较小//其他情况min就是最小的&#xff0c;即左孩子小if (min &#43; 1 < arr.length && arr[min &#43; 1] < arr[min]) {min&#43;&#43;;}//3.根小于该孩子结点则不执行if (arr[index] <&#61; arr[min]) {break;}//4.否则的话交换int t &#61; arr[min];arr[min] &#61; arr[index];arr[index] &#61; t;//以该结点为根&#xff0c;继续向下调整index &#61; min;min &#61; 2 * min &#43; 1;}}

2.3向上调整建大堆

/* 向上调整为大堆 */&#64;Overridepublic void adjustUp(int[] array, int index) { //index为插入的下标//父亲结点int parent &#61; (index - 1) / 2;//一直调整到堆顶while (parent >&#61; 0) {if (item[index] > item[parent]) {int t &#61; item[index];item[index] &#61; item[parent];item[parent] &#61; t;index &#61; parent;parent &#61; (index - 1) / 2;} else {break;}}}

2.4建堆

给出一个数组&#xff0c;逻辑上是一个二叉树&#xff0c;但是还不是堆&#xff0c;从倒数的第一个非叶子节点的子树开始调整&#xff0c;一直调整到根节点的树&#xff0c;就可以调整成堆。
时间复杂度为O(N*logN)&#xff0c;实际是O&#xff08;N&#xff09;

private static void CreateHeap(int[] arr) {//从最后一个非叶子结点的下标开始for (int i &#61; (arr.length - 1 - 1) / 2; i >&#61; 0; i--) {//不断地做向下调整//CreateSmall(arr, i);CreateBig(arr,i);}}

2.3堆的插入、查看、删除

public class IHeapImpl implements IHeap {private int[] item;private int userSize;public IHeapImpl(int[] arr) {this.item &#61;Arrays.copyOf(arr,arr.length);// 代表数组中被视为堆数据的个数this.userSize &#61; 0;}/* 1.堆的插入 */ //先插入一个数字到数组的尾上&#xff0c;长度&#43;&#43;&#xff0c;再进行向上调整算法&#xff0c;直到满足堆。&#64;Overridepublic void add(int item) {if (Full()) {this.item &#61; Arrays.copyOf(this.item, 2 * this.item.length &#43; 1);}this.item[userSize] &#61; item;this.userSize&#43;&#43;;//加到最后一个了&#xff0c;所以要向上调整adjustUp(this.item, this.userSize - 1);}/* 向上调整为大堆 */&#64;Overridepublic void adjustUp(int[] array, int index) { //index为插入的下标//父亲结点int parent &#61; (index - 1) / 2;//一直调整到堆顶while (parent >&#61; 0) {if (item[index] > item[parent]) {int t &#61; item[index];item[index] &#61; item[parent];item[parent] &#61; t;index &#61; parent;parent &#61; (index - 1) / 2;} else {break;}}}&#64;Overridepublic int peek() {if (isEmpty()) {//不支持的异常throw new UnsupportedOperationException("堆为空");}return this.item[0];}//返回堆顶元素&#xff0c;并该数据元素//删除堆是删除堆顶的数据&#xff0c;将堆顶的数据根和最后一个数据一换&#xff0c;然后删除数组最后一个数据&#xff0c;再进行向下调整算法。&#64;Overridepublic int pop() {if (isEmpty()) {//抛出不支持的异常throw new UnsupportedOperationException("堆为空");}//先保留堆顶元素int old&#61;this.item[0];//先交换&#xff0c;把堆顶元素和最后一个元素交换,最后一个元素下标为usedSize-1int t &#61; this.item[0];this.item[0] &#61; this.item[this.userSize - 1];this.item[this.userSize - 1] &#61; t;//完了之后将交换后的最后一个元素删除&#xff0c;只要userSize--&#xff0c;说明下次做向下调整的时候就不走这里了this.userSize--;//此时只有0位值不满足堆的性质&#xff0c;向下调整建大堆adjustDown(this.userSize , 0);return old;}//向下调整&#64;Overridepublic void adjustDown(int len, int index) {int max &#61; index * 2 &#43; 1;while (max < len) {if (max &#43; 1 < len && this.item[max] < this.item[max &#43; 1]) {max&#43;&#43;;}if (item[index] >&#61; item[max]) {break;}int t &#61; item[index];item[index] &#61; item[max];item[max] &#61; t;index &#61; max;max &#61; index * 2 &#43; 1;}}//创建大根堆&#64;Overridepublic void createHeap(int[] array) {this.userSize&#61;array.length;for (int i &#61; (array.length - 1 - 1) / 2; i >&#61; 0; i--) {adjustDown(this.userSize, i);}}&#64;Overridepublic void show() {for (int i &#61; 0; i < this.userSize; i&#43;&#43;) {System.out.print(item[i] &#43; " ");}}&#64;Overridepublic boolean Full() {return this.userSize &#61;&#61; this.item.length;}&#64;Overridepublic boolean isEmpty() {return this.userSize &#61;&#61; 0;}
}


推荐阅读
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • C语言常量与变量的深入理解及其影响
    本文深入讲解了C语言中常量与变量的概念及其深入实质,强调了对常量和变量的理解对于学习指针等后续内容的重要性。详细介绍了常量的分类和特点,以及变量的定义和分类。同时指出了常量和变量在程序中的作用及其对内存空间的影响,类似于const关键字的只读属性。此外,还提及了常量和变量在实际应用中可能出现的问题,如段错误和野指针。 ... [详细]
  • JVM:33 如何查看JVM的Full GC日志
    1.示例代码packagecom.webcode;publicclassDemo4{publicstaticvoidmain(String[]args){byte[]arr ... [详细]
  • Python中程序员的面试题有哪些
    小编给大家分享一下Python中程序员的面试题有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
author-avatar
小Q理性的激情农_885
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有