堆的Java实现

article/2025/11/7 13:41:24

一.概念

堆是计算机科学中一类特殊的数据结构的统称,堆通常可以被看做是一棵完全二叉树的数组对象。
堆的特性

  1. 它是完全二叉树,除了树的最后一层结点不需要是满的,其它的每一层从左到右都是满的,如果最后一层结点不是满的,那么要求左满右不满。保证叶结点只能出现在最下层or次下层
    快速辨别: 看最后一层的最后一个结点G,G之前是满的就是完全二叉树。而红色的树 G之前未满,则是不完全二叉树
    在这里插入图片描述
    在这里插入图片描述

  2. 它通常用数组来实现。 具体方法就是将二叉树的结点按照层级顺序放入数组中,根结点在索引位置1处(舍弃索引0),它的子结点在位置2和3,而子结点的子结点则分别在位置4,5,6和7,以此类推。
    在这里插入图片描述
    抛弃0号索引,从1开始存更方便!

规律
如果一个结点的位置为k,则它的父结点的位置为k/2 ,
而它的两个子结点的位置则分别为2k2k+1
这样,在不使用指针的情况下,我们也可以通过计算数组的索引在树中上下移动:从a[k]向上一层,就令k等于k/2,向下一层就令k等于2k或2k+1。
③每个结点的key值都大于等于它的两个子结点。
这里要注意堆中仅仅规定了每个结点大于等于它的两个子结点,但这两个子结点的顺序并没有做规定,跟我们之前学习的二叉查找树不一样!。 堆并不是完全有序的 !
其中最大的元素就放在索引1处(舍弃索引0 ,从索引1开始放元素)

二.实现

insert()插入方法的实现
堆是用数组完成数据元素的存储的,由于数组的底层是一串连续的内存地址,所以我们要往堆中插入数据,我们只能往数组中从索引1处开始,依次往后存放数据,但是堆中对元素的顺序是有要求的。
每一个结点的数据要大于等于它的两个子结点的数据, 所以每次插入一个元素,都会使得堆中的数据顺序变乱,这个时候我们就需要通过一些方法让刚才插入的这个数据放入到合适的位置。

swim()方法逻辑:比较新添加的元素k和他的父节点的大小,如果k大于他的父节点,则交换k和他的父节点的位置;交换完后再将k和他的父节点进行比较… 直到k不再大于他的父节点

delMax删除最大的元素的实现
由堆的特性我们可以知道,索引1处的元素,也就是根结点就是最大的元素,当我们把根结点的元素删除后,需要有一个新的根结点出现,这时我们可以暂时把堆中最后一个元素放到索引1处,充当根结点,但是它有可能不满足堆的有序性需求,这个时候我们就需要通过一些方法,让这个新的根结点放入到合适的位置,然后通过下沉sink()方法对堆的顺序进行调整。

sink()方法逻辑:求出当前结点左右子节点的最大值max,若当前结点小于max就将当前结点和max进行交换。

代码

public class heap <T extends Comparable<T>>{private T[] items;private int N;public heap(int capacity){this.items= (T[]) new Comparable[capacity+1]; // comparable类this.N=0;}  //数组是定长的,要先指定初始容量private boolean more(int i,int j){ //比较i索引的key是否小于j索引处的keyreturn ( items[i].compareTo(items[j])>0 );}private void swap(int i,int j){ //交换T temp=items[i]; //临时变量items[i]=items[j];items[j]=temp;}public void insert(T t){items[++N]=t;  //先让N+1 ,就可以废弃掉0索引,同时元素的个数也是正确的swim(N); //让N索引处的值通过上浮放到合适的位置}public T delMax(){  //删除最大元素即根结点T max= items[1]; //记录根结点//交换根节点max和 索引最大处的元素swap(1,N);//将根节点放到索引N处即删掉最大索引处的元素,即交换后的根节点maxitems[N]=null;N--;//从新的根节点开始,使用下沉sink方法sink(1);return max; //只是返回要被删除的元素}private void  swim(int k){  //上浮算法,使索引k处的元素处于一个正确的位置//通过循环不断和父节点进行比较,大于父节点则和父节点交换,while(k>1){//比较当前结点和父节点if(more(k,k/2)){ //如果当前结点k大于 其父k/2,则交换swap(k,k/2);}k=k/2; //当不满足if,k会越来越小直到跳出while}}private void sink(int k) {   //下沉算法,使索引k处的元素处于一个正确的位置//通过循环对比, 如果当前结点元素 < 两个子节点中较大值,则交换int max;//记录较大元素的索引while ( (2*k <=N) { //循环条件: 节点k存在左子节点//获取两个子节点中的最大值记录为max,再将k节点和max比较,若大于max则不需要下沉if (2 * k + 1 <= N) { //有左子结点且有右子结点if (more(2 * k, 2 * k + 1)) { //如果左子结点大于右子节点max = 2 * k;} else {max = 2 * k + 1;}} else {max = 2 * k; //只有左子节点,没有右子节点直接让max为左子节点}if (more(k, max)) {break; //当前k结点大于 左右子节点中最大结点,则不需要交换,循环结束} else {  //k节点小于max,则需要继swap(k, max);k = max; //变换k的值}}}public static void main(String[] args) {heap<String> h=new heap<String>(12);p.insert("E");p.insert("B");p.insert("F");p.insert("G");p.insert("D");p.insert("C");p.insert("A");//通过循环从堆中删除数据String result=null;while(   (result=h.delMax())  !=null){ //循环条件:只要还有数据可删System.out.println(result+" ");  //每次删除掉的都是最大的元素}}
}

结果:A B C D E F G
测试为循环删除堆中最大的元素并返回,测试结果为G到A依次输出。


http://chatgpt.dhexx.cn/article/XBbqMyjU.shtml

相关文章

堆的创建---java

目录 1、堆的概念 2.堆的存储方式 3、堆的创建 3.1、堆向下调整 3.2、堆的创建 1、堆的概念 如果有一个关键码的集合K {k0&#xff0c;k1&#xff0c; k2&#xff0c;…&#xff0c;kn-1}&#xff0c;把它的所有元素按完全二叉树的顺序存储方式存储 在一个一维数组中&…

【堆】堆的实现(Java)

今天学习堆这种数据结构。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质&#xff1a; 堆中某个结点的值总是不大于或不小于其父结点的值&#xff1b;堆总是一棵完全二叉树。 将根结点最大的堆叫做最大堆或大根堆&#xff0c;根结点最小的堆叫做最小堆或小根堆…

Java之堆和堆排序

目录 一.什么是堆 1.基本介绍 2.堆的实现方式 二.最大堆的实现 1.最大堆 2.思路分析 0.基础操作 1.添加上浮操作 2.删除下沉操作 3.将数组堆化操作 2.代码实现 三.堆排序 1.什么是堆排序 2.思路分析 3.代码实现 一.什么是堆 1.基本介绍 堆是一种数据结构&#…

六、Java堆

一、堆的核心概述 1、概述 1、堆针对一个JVM进程来说是唯一的&#xff0c;也就是一个进程只有一个JVM&#xff0c;但是进程包含多个线程&#xff0c;他们是共享同一堆空间的。 2、一个JVM实例只存在一个堆内存&#xff0c;堆也是Java内存管理的核心区域。 3、Java堆区在JVM启动…

Java数据结构-堆

目录 一、简介二、堆的实现&#xff08;1&#xff09;堆的插入&#xff08;2&#xff09;删除根节点&#xff08;3&#xff09;上浮操作① 大根堆的上浮② 小根堆的上浮 &#xff08;4&#xff09;下沉操作① 大根堆的下沉② 小根堆的下沉 &#xff08;5&#xff09;堆的构造&a…

JVM JAVA中的堆

堆的核心概述&#xff1a; 一个进程对应一个JVM的实例&#xff0c;一个JVM实例中只有一个运行时数据区&#xff0c;里面只有一个方法区和堆&#xff0c;一个进程的多个线程共享方法区和堆&#xff0c;那就要考虑线程的安全问题。 每个线程各有一套程序计数器、本地方法栈、虚拟…

Java堆是如何划分的?

写在前面 本文隶属于专栏《100个问题搞定Java虚拟机》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和文献引用请见100个问题搞定Java虚拟机 解答 Java 虚拟机将堆划分为…

数据结构-堆和堆的Java实现

1. 定义 堆&#xff08;英语&#xff1a;heap)是计算机科学中一类特殊的数据结构的统称。 堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质&#xff1a; 1.堆中某个节点的值总是不大于或不小于其父节点的值&#xff1b; 2.堆总是一棵完全二叉树。 常见的堆有二…

Java数据结构之堆(Heap)

文章目录 一、基本概念二、上浮操作(siftUp)三、下沉操作(siftDown)四、数组堆化五、实现大根堆 提示&#xff1a;以下是本篇文章正文内容&#xff0c;Java系列学习将会持续更新 一、基本概念 堆在逻辑上就是一棵完全二叉树。堆在物理上是储存在数组中。满足任意根节点值>…

JVM--堆

45. JVM--堆 1. 堆的核心概述 一个进程对应一个JVM的实例&#xff0c;一个JVM实例中只有一个运行时数据区&#xff0c;里面只有一个方法区和堆&#xff0c;一个进程的多个线程共享方法区和堆&#xff0c;那就要考虑线程的安全问题。 每个线程各有一套程序计数器、本地方法栈、虚…

java中的堆

文章目录 一、堆的分类二、详述Java堆中各个区域1、堆大小2、新生代 ( Young ) 的划分3、工作原理4、GC日志 一、堆的分类 Java 中的堆是 JVM 管理的最大的一块内存空间&#xff0c;主要用于存放Java类的实例对象 其被划分为两个不同的区域&#xff1a;新生代 ( Young )和老年…

Java数据结构--堆

一.堆的定义及本质 要知道在Java中&#xff0c;堆是以优先级队列来表示的。因此学会了堆&#xff0c;我们也就学会优先级队列 1.堆的定义 当一颗二叉树的每个节点都大于等于它的两个子字节时&#xff0c;它被称为堆有序。而堆是一组能够用堆有序的完全二叉树排序的元素&…

Java数据结构之堆

堆的概念 堆逻辑上是一棵完全二叉树堆物理上是保存在数组中满足任意结点的值都大于其子树中结点的值&#xff0c;叫做大堆&#xff0c;或者大根堆&#xff0c;或者最大堆反之&#xff0c;则是小堆&#xff0c;或者小根堆&#xff0c;或者最小堆堆的基本作用是快速找集合中的最…

常用三极管引脚定义

给大家总结了常用封装的三极管的引脚定义 配套的视频讲解 常用三极管引脚定义

常用电子器件 ——三极管

说明&#xff1a;   本文章旨在总结备份、方便以后查询&#xff0c;由于是个人总结&#xff0c;如有不对&#xff0c;欢迎指正&#xff1b;另外&#xff0c;内容大部分来自网络、书籍、和各类手册&#xff0c;如若侵权请告知&#xff0c;马上删帖致歉。   QQ 群 号&#xf…

三极管开关特性

三极管在我们数字电路和模拟电路中都有大量的应用&#xff0c;在我们开发板上也用了多个三极管。在我们板子上的 LED 小灯部分&#xff0c;就有这个三极管的应用了&#xff0c;图 3-5 的 LED 电路中的 Q16就是一个 PNP 型的三极管。 图 3-5 LED 电路 三极管的初步认识 三极管…

常用三极管入门级电路设计(如何选型和搭电路?)

转自&#xff1a; 常用的三极管电路设计-电阻到底是怎么选的&#xff08;修正后&#xff09;-面包板社区 硬件基础知识---如何设计一个三极管放大电路_学无止境的专栏-CSDN博客_uce怎么算 今天的内容超级简单&#xff0c;主要给硬件新手写点东西&#xff0c;关于三极管实用方…

三极管相关知识点

1.两种类型的三极管图示如下&#xff0c;基极&#xff08;Base&#xff09;、集电极&#xff08;Collector&#xff09;和发射极&#xff08;Emitter&#xff09;&#xff0c;等效二极管电路如图所示 2.三极管的几种工作状态&#xff0c; 3.三极管做开关功能时&#xff0c;工…

三极管的一些基本知识

导通条件 NPN型三极管的导通条件是C点电位>B点电位>E点电位&#xff0c;三极管饱和导通的条件是Ub>Ue,Ub>Uc。 PNP型三极管的导通条件是E点电位>B点电位>C点电位&#xff0c;三极管饱和导通的条件是Ue>Ub,Uc>Ub。 NPN型三极管 1、定义&#xff1a; …

三极管的几点应用

关注星标公众号&#xff0c;不错过精彩内容 直接来源 | 巧学模电数电单片机 在复杂多变的模拟电路中&#xff0c;少不了学习三极管&#xff0c;过往的血泪史&#xff0c;不想再提&#xff0c;什么正偏反偏都给我统统滚蛋&#xff01;今天来点实际的。 三极管有三个工作状态&…