数据结构 堆与优先级队列

article/2025/6/30 12:34:31

文章目录

    • 📕1. 堆(Heap)
        • ✏️1.1 堆的概念
        • ✏️1.2 堆的存储方式
        • ✏️1.3 堆的创建
        • ✏️1.4 堆的插入
        • ✏️1.5 堆的删除
    • 📕2. 优先级队列(PriorityQueue)
        • ✏️2.1 堆与优先级队列的关系
        • ✏️2.2 优先级队列的构造方法
        • ✏️2.3 优先级队列的常用方法
    • 3. Java对象的比较
        • 3.1 基于Comparble接口类的比较
        • 3.2 基于比较器比较

📕1. 堆(Heap)

✏️1.1 堆的概念

堆(Heap)是一种特殊的完全二叉树,它满足父节点的值总是不大于或不小于其子节点的值。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。

堆满足以下两个性质:

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

在这里插入图片描述

✏️1.2 堆的存储方式

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

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

在这里插入图片描述
将元素存储到数组中后,假设i为节点在数组中的下标,则有:

  1. 如果i为0,则i表示的节点为根节点,否则i节点的双亲节点为 (i - 1)/2
  2. 如果2 * i + 1 小于节点个数,则节点i的左孩子下标为2 * i + 1,否则没有左孩子
  3. 如果2 * i + 2 小于节点个数,则节点i的右孩子下标为2 * i + 2,否则没有右孩子
✏️1.3 堆的创建

想要创建堆,我们首先要了解向下调整(这里以创建小根堆为例):

  1. 我们将想要调整的节点标记为parent,child为该节点的左孩子(如果有孩子节点,则一定是现有左孩子)
  2. 如果有左孩子节点,则判断child<size(数组元素个数),然后进行以下操作,直到child<size条件不成立
    2.1 判断parent的右孩子是否存在,找到左右孩子中最小的那个,用child标记.(如果右孩子比左孩子小,child+=1)
    2.2 将parent与child比较,如果parent<child,则调整结束;否则进行元素交换,交换完之后,有可能新构建的子树又不满足小根堆,所以需要将parent = child,child = parent * 2 + 1. 然后继续重复2操作.这便是向下调整.
    public void siftDown(int[] arr,int parent){//此时child标记的左孩子,因为parent右孩子结点的话只能先有左孩子int child = parent * 2 + 1;int size = arr.length;while(child < size){// 如果右孩⼦存在,找到左右孩⼦中较⼩的孩⼦,⽤child进⾏标记if (child+1 < size && arr[child] < arr[child+1]){child+=1;}// 如果双亲⽐其最⼩的孩⼦还⼩,说明该结构已经满⾜堆的特性了if (arr[parent] <= arr[child]){break;}else {// 将双亲与较⼩的孩⼦交换int t = arr[parent];arr[parent] = arr[child];arr[child] = t;// parent中⼤的元素往下移动,可能会造成⼦树不满⾜堆的性质,因此需要继续向下调整parent = child;child = parent * 2 + 1;}}}

了解完向下调整,那给你任意一些数据,那我们该如何创建成小根堆呢?

public void createHeap(int[] arr){// 找倒数第⼀个⾮叶⼦节点,从该节点位置开始往前⼀直到根节点,遇到⼀个节点,应⽤向下调整int root = (arr.length-2)/2;for (; root >= 0 ; root--) {siftDown(arr,root);}
}

还需要注意的是,建堆的时间复杂度为O(N);

✏️1.4 堆的插入

堆的插入总共需要两个步骤;

  1. 先将元素放入到数组最后一个空间中(数组长度不够时需要扩容)
  2. 将新插入的节点利用向上调整,直到满足堆的性质

在这里插入图片描述

向上调整:

public void siftUp(int child){//以创建小根堆为例//找到child的根节点int parent = (child-1)/2;while(child > 0){// 如果双亲⽐孩⼦小,parent满⾜堆的性质,调整结束if (arr[parent] < arr[child]){break;}else {// 将双亲与孩⼦节点进⾏交换int tmp = arr[parent];arr[parent] = arr[child];arr[child] = arr[tmp];}// ⼩的元素向下移动,调整后的⼦树可能不满⾜堆的性质,因此需要继续向上调增child = parent;parent = (child-1)/2;}}

插入数据:

/**
* 插入数据:
* 每次插入到当前堆的最后一个(数组的最后一个),然后向上调整
*/public void offer(int val) {if(isFull()) {elem = Arrays.copyOf(elem,2*elem.length);}elem[size] = val;//调整siftUp(size);size++;}
✏️1.5 堆的删除

堆的插入总共需要两个步骤;

  1. 将堆顶元素与堆中最后一个元素交换
  2. 将对中有效数据减少一个
  3. 对堆顶元素进行向下调整

注意:堆的删除⼀定删除的是堆顶元素

📕2. 优先级队列(PriorityQueue)

之前我们已经学习过队列了,队列是一种先进先出(FIFO)的数据结构,但有些情况下,操作的数据可能带有优先级,出队列时,可能需要优先级高的元素先出队列 . 比如:在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话.该场景下,使用队列显然不合适,因此数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,⼀个是添加新的对象。这种数据结构就是优先级队列(PriorityQueue).

✏️2.1 堆与优先级队列的关系

首先大家要知道一点 , 堆是一种数据结构 , 而优先级队列也是一种数据结构 , 二者是完全单独且不同的数据结构.
优先队列本身就是一种数据结构,它的着重点是优先,而不是队列。优先是目标,队列只是形式.
优先级队列不仅可以用堆来实现 , 用链表也是可以模拟实现的 , 只不过在JDK1.8中 , PriorityQueue的底层实现使用了堆这种数据结构.

✏️2.2 优先级队列的构造方法

在这里插入图片描述

注意:默认情况下,PriorityQueue队列是小堆,如果需要大堆需要用户提供比较器

✏️2.3 优先级队列的常用方法

在这里插入图片描述
优先级队列的扩容说明:
• 如果容量小于64时,是按照oldCapacity的2倍方式扩容的
• 如果容量大于等于64,是按照oldCapacity的1.5倍方式扩容的
• 如果容量超过MAX_ARRAY_SIZE,按照MAX_ARRAY_SIZE来进行扩容

3. Java对象的比较

在SE阶段中,我们介绍了引用类型变量使用equals()方法进行比较 , 基本数据类型变量使用大于号小于号进行比较 , 故以上两种方法此处不再赘述.

3.1 基于Comparble接口类的比较

Comparble是JDK提供的泛型的比较接口类,源码实现具体如下:

public interface Comparable<E> {// 返回值:// < 0: 表⽰ this 指向的对象⼩于 o 指向的对象// == 0: 表⽰ this 指向的对象等于 o 指向的对象// > 0: 表⽰ this 指向的对象⼤于 o 指向的对象int compareTo(E o);
}

对于用户定义类型,如果要想按照大小的方式进行比较时:
在定义类时,实现Comparble接口即可,然后在类中重写compareTo方法。

public class Card implements Comparable<Card> {public int rank; // 数值public String suit; // 花⾊public Card(int rank, String suit) {this.rank = rank;this.suit = suit;}// 根据数值⽐较,不管花⾊// 这⾥我们认为 null 是最⼩的@Overridepublic int compareTo(Card o) {if (o == null) {return 1;}return this.rank - o.rank;}public static void main(String[] args){Card p = new Card(1, "♠");Card q = new Card(2, "♠");Card o = new Card(1, "♠");System.out.println(p.compareTo(o)); // == 0,表⽰牌相等System.out.println(p.compareTo(q)); // < 0,表⽰ p ⽐较⼩System.out.println(q.compareTo(p)); // > 0,表⽰ q ⽐较⼤}
}
3.2 基于比较器比较

Comparator是java.util 包中的泛型接口类 , 源码如下:

public interface Comparator<T> {// 返回值:// < 0: 表⽰ o1 指向的对象⼩于 o2 指向的对象// == 0: 表⽰ o1 指向的对象等于 o2 指向的对象// > 0: 表⽰ o1 指向的对象等于 o2 指向的对象int compare(T o1, T o2);
}

按照比较器方式进行比较,具体步骤如下:

  1. 用户自定义比较器类,实现Comparator接口
  2. 重写Comparator中的compare方法
import java.util.Comparator;class Card {public int rank; // 数值public String suit; // 花⾊public Card(int rank, String suit) {this.rank = rank;this.suit = suit;}
}class CardComparator implements Comparator<Card> {// 根据数值⽐较,不管花⾊// 这⾥我们认为 null 是最⼩的@Overridepublic int compare(Card o1, Card o2) {if (o1 == o2) {return 0;}if (o1 == null) {return -1;}if (o2 == null) {return 1;}return o1.rank - o2.rank;}public static void main(String[] args){Card p = new Card(1, "♠");Card q = new Card(2, "♠");Card o = new Card(1, "♠");// 定义⽐较器对象CardComparator cmptor = new CardComparator();// 使⽤⽐较器对象进⾏⽐较System.out.println(cmptor.compare(p, o)); // == 0,表⽰牌相等System.out.println(cmptor.compare(p, q)); // < 0,表⽰ p ⽐较⼩System.out.println(cmptor.compare(q, p)); // > 0,表⽰ q ⽐较⼤}
}

http://www.hkcw.cn/article/nCxnBFOSKP.shtml

相关文章

基于Java 实现 IM 业务回调

1.什么是业务回调 2.腾讯云回调的类型 功能角度 在线状态回调 资料关系链回调 单聊消息回调 群组系统回调 处理角度 事件发生之前回调&#xff1a;回调的主要目的在于让 App 后台可以干预该事件的处理逻辑&#xff0c;即时通信 IM 会根据回调返回码确定后续处理流程&…

印度空军高官不满:“国产战机”到底何时能交货

据俄罗斯卫星通讯社5月29日报道,印度空军参谋长辛格在印度工业联合会举办的年度商业峰会上严厉批评本国的航空制造业,称印度大型国防项目的落实没有如期进行,包括国产“光辉”战机在内的战斗机向空军交付均出现延迟。辛格指出,根据2021年与印度斯坦航空有限公司签订的价值4…

澳贸易部长谈美国进口钢铝关税 反对不合理加征

5月30日,美国总统特朗普宣布,自6月4日起,将把钢铁和铝的进口关税从25%提高至50%。次日,澳大利亚贸易部长法瑞尔对此作出回应,表示澳大利亚的立场始终明确且一致。他认为这些关税措施既不合理,也不符合朋友之间的行为准则。法瑞尔指出,这种做法是一种经济上的自我伤害,不…

水上竞渡 绿道长安 ‘艇’进未来

为推动文旅赋能“百千万工程”,加快落实文化强市建设任务,东莞市长安镇即将举办一场精彩的文旅盛宴。5月29日至31日,“绿道长安 ‘艇’进未来”2025年长安镇水上竞渡活动将在莲花山风景区水上活动中心举行。活动期间,水上活动中心、莲花湖绿道生态停车场、莲花湖绿道三大场…

保安27层高空索降盗窃67块玉石 现实版“疯狂的石头”

电影《疯狂的石头》中盗贼们盯上价值连城的翡翠并化身“蜘蛛人”空降盗窃的情节,在新疆乌鲁木齐某大厦真实上演。5月23日凌晨,该市一玉石展厅内共计67块玉石被盗,估价约1亿元。警方勘查现场发现门锁完好,但23楼窗户玻璃被砸,外侧有使用绳索痕迹。大厦顶层27层平台处发现了…

python出租车计费 2023年信息素养大赛复赛/决赛真题 小学组/初中组 python编程挑战赛 真题详细解析

python出租车计费 2023全国青少年信息素养大赛Python编程挑战赛复赛真题解析 博主推荐 所有考级比赛学习相关资料合集【推荐收藏】1、Python比赛 信息素养大赛Python编程挑战赛 蓝桥杯python选拔赛真题详解

陪酒坠楼女孩母亲称没收到主犯赔偿 赔偿未到位加剧家庭困境

四川女孩丹丹在成都鑫银汇KTV从事有偿陪侍工作。2023年8月26日凌晨,15岁的她酒后从KTV所在的三楼坠下,全身多处受伤入院。此后,涉事的鑫银汇KTV因组织未成年人进行有偿陪侍活动被立案侦查。案件二审已经终结,KTV负责人彭某及无业人员陈某某、林某等三人均被判刑。一审判决书…

原县委书记花上千万建10座公厕被查 豪华装修超预算

刚摘掉深度贫困县的帽子,时任县委书记李德明就斥资上千万元建了10个水冲公厕,内部装修豪华。吉林省纪委监委日前公开通报4起形式主义、官僚主义典型问题,其中提到省农业农村厅原厅长、白城市通榆县委原书记李德明搞劳民伤财的“形象工程”。李德明出生于1970年7月,曾任白城…

特朗普政府给哈佛30天提出异议 政策争议持续升级

当地时间29日,美国马萨诸塞州联邦地区法院法官艾莉森伯勒斯批准了哈佛大学提出的初步禁令请求,暂停了特朗普政府取消哈佛大学招收外国学生资质的政策。听证会后,法院决定此前发布的临时限制令将继续有效,直至各方协商并提交提议供法官审议。本月22日,美国国土安全部宣布取…

原县委书记搞形象工程建140平厕所 豪华装修引争议

刚摘掉深度贫困县帽子的通榆县,时任县委书记李德明便斥资上千万元建造了10个豪华装修的水冲公厕。日前,吉林省纪委监委公开通报了4起形式主义、官僚主义典型问题,其中就包括李德明搞劳民伤财的“形象工程”。李德明出生于1970年7月,曾任白城市住建局局长,2019年4月出任通榆…

级联的if else

级联的if else——if else嵌套的另一写法 /* 分段函数 f(x) -1 ; x < 0 0 ; x 0 2x ; x > 0 */ #include <stdio.h> int main() {int x,f;printf("请输入x的值&#xff1a;\n");scanf("%d",&x);getchar();if (x < 0) {f -1;} els…

宿茂臻携泰山队球员送儿童节祝福 签名送礼表心意

山东体育休闲频道报道,泰山足球俱乐部总经理宿茂臻携泰山队球员为小朋友们送上了六一节的祝福。宿茂臻及刘彬彬、张弛等泰山球员在球衣上签名并送去了礼物。宿茂臻表示:“六一儿童节来了,在这里代表山东泰山俱乐部向济南市、山东省以及全国的少年儿童说一句,祝你们六一儿童…

“他就是恶意的!”全运会球员遭对手从背后犯规暴力踢断腿,伤者发声 要求赔偿所有损失

第十五届全国运动会期间,七人制男子足球比赛中发生了一起严重事件。北京代表队的运动员曹某某在比赛中恶意踢伤了上海队的一名球员,导致对方左腿骨折。曹某某因此被罚停赛6场,并被要求限期离开佛山赛区。此外,北京代表队也受到了通报批评。受伤球员蔡先生对这一行为表示强烈…

法国升级改造空军基地有何目的 增强核威慑力量

法国已开始斥资17亿美元对吕克瑟伊空军基地进行现代化改造,以部署携带核武器的“阵风”战机。这一举措反映了欧洲安全局势的紧张情绪日益加剧。改造工作将耗时十年,从2035年起,吕克瑟伊空军基地的面积将扩大到现在的两倍,并将成为法国第四个也是最现代化的核武器储存基地。…

世界反兴奋剂机构主席驳斥美国指责 美体系存缺陷

世界反兴奋剂机构主席班卡在获得连任后表示,美国无端指责世界反兴奋剂机构,却无视自身存在的严重问题。他将继续大胆指出美国反兴奋剂体系的缺陷。在接受媒体采访时,班卡提到美国代表曾试图削弱他在世界反兴奋剂机构的领导地位,并试图更换领导人。由于美国政府停止了对世界…

男子疑似因疲劳驾驶连撞13车 马路变成碰碰车乐园

5月29日晚,台北某路口发生了一起惊心动魄的连环撞车事件。一位司机因疲劳驾驶,在晚高峰时段将马路变成了碰碰车乐园,连续撞击了13辆无辜车辆。监控画面显示,当时路口车水马龙,这位司机显然已经极度疲劳,车子像失控的野牛一样横冲直撞。先是撞上一辆出租车,接着追尾多辆车…

“美国施压台在野党:别挡路,买我武器要紧”

【文/观察者网 张菁娟】在中美贸易摩擦暂时“冻结”之际,美国总统特朗普又企图打“台湾牌”。路透社30日援引两名美国官员的话报道称,美国计划将对台军售提升至超过特朗普首个任期的水平,以强化对中国大陆的威慑力。与此同时,美方正施压台湾在野党,要求他们在增加防务预算…

王者荣耀铠动画剧集开播 颜值暴击震撼来袭

我宣布从今天开始铠爹就是我在峡谷最爱的,这动画太帅了吧,一出场直接颜值暴击!被画质震撼了!露娜也好美好美!我甚至看得清披风和铠甲的细节!但是怎么一上来就是大刀啊啊啊啊啊责任编辑:zx0001

你想看的福建舰又出镜了!“龙舟”竞渡硬核现场

var chan_v_w = 960,chan_v_h = 540,chan_v_p = https://mts-audio.huawangzhixun.com/image/20250531/news/4e87f4bc-b28b-436e-ab35-fa250691ec58.jpg,chan_v_s = https://vmts.china.com/api/video/onaliyun/query?id=3101098&ttype=mp4;谁说龙舟用桨划?战舰列阵引擎轰…

大V:普京用黄金换来了伊朗的强援 换取无人机技术支持

普京开始兑现承诺,将4吨黄金陆续送到盟友手中。在俄乌冲突爆发后,俄罗斯面临严峻挑战时,这些黄金帮助换取了伊朗的支持,为俄罗斯争取到了宝贵的喘息之机。据报道,普京政府向伊朗政府主导的“撒哈拉雷霆”公司转移了至少1.8吨黄金,以支付购买伊朗“沙赫德”系列自杀式无人…