Java实现优先级队列(堆)

前言

在学习完二叉树的相关知识后,我们对数据结构有了更多的认识,本文将介绍到优先级队列(堆)

1.优先级队列

1.1概念

前面介绍过队列,队列是一种先进先出(FIFO)的数据结构,但有些情况下,操作的数据可能带有优先级,一般出队列时,可能需要优先级高的元素先出队列,该中场景下,使用队列显然不合适,对此数据结构应该提供两个最基本的操作,一个是返回最高优先级对象一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)

1.2模拟实现

JDK1.8中的PriorityQueue底层使用了堆这种数据结构,而堆实际就是在完全二叉树的基础上进行了一些调整

2.堆

2.1概念

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


2.2性质 

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

2.3堆的存储方式

根据堆的概念以及性质,我们可以根据层序的规则采用顺序的方式来高效存储

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

根据我们对二叉树性质的学习,有一下性质:

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

2.4堆的创建 

我们以集合{ 27,15,19,18,28,34,65,49,25,37 }中的数据为例,建堆

按照二叉树的顺序排列发现,根子树已经为堆的结构,只需将根节点向下调整即可

2.4.1向下调整

以大根堆为例

    private void swap(int i,int j){int tmp=elem[i];elem[i]=elem[j];elem[j]=tmp;}//大根堆/*时间复杂度为从根一路比较到叶子,比较的次数为完全二叉树的高度,O(log2 n)*/public void siftDown(int parent,int end){int child=parent*2+1;//先标记左孩子,因为可能该树没有右孩子while(child<end) {if (child + 1 < end && elem[child] < elem[child + 1]) {//假如右孩子存在,找到其中较大的孩子child++;}//找到了最大的子孩子if (elem[child] > elem[parent]) {//若孩子比双亲大,进行交换,同时继续向下调整swap(child, parent);parent = child;child = 2 * parent + 1;} else {//若双亲大,则满足堆的特性,即跳出循环break;}}}

注意:在调整以parent为根的二叉树时,必须要满足parent的左子树和右子树已经是堆了才可以向下调整

2.4.2堆创建

但是当二叉树中,子树不满足堆时,该如何建堆呢?

这里,我们找到第一个非叶子节点,从该节点开始往前一直到根节点,遇到一个节点,向下调整

    public void creatHeap(){for (int parent = (usedSize-1-1/2); parent >=0 ; parent--) {siftDown(parent,usedSize);}}

2.5堆的插入与删除 

 2.5.1插入

堆的插入总共需要两个步骤:
1. 先将元素放入到底层空间中(注意:空间不够时需要扩容)
2. 将最后新插入的节点向上调整,直到满足堆的性质

//以大根堆为例public void siftUp(int child){int parent=(child-1)/2;while(parent>=0){if(elem[child]>elem[parent]){swap(child,parent);child=parent;parent=(child-1)/2;}else{break;}}}

2.5.2删除

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

  public boolean isFull(){return usedSize==elem.length;}public int poll(){if(isEmpty()){return -1;}int old=elem[0];swap(0,usedSize-1);usedSize--;siftDown(0,usedSize-1);return old;}public boolean isEmpty(){return usedSize==0;}

2.6模拟实现优先级

public class Test {public static void main(String[] args) {int[] array = {25, 56, 21, 45, 75};TestHeap testHeap = new TestHeap();testHeap.init(array);testHeap.creatHeap();testHeap.heapSort();}
}

 如果上述内容对您有帮助,希望给个三连谢谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/625898.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源无需root!一款功能强悍的手机电脑同屏工具,14K star拿捏了【文末带项目源码】

现在使用最常用的设备就是手机和电脑了&#xff0c;经常会需要将手机屏幕镜像到电脑&#xff0c;或者是用电脑来操控手机等。 今天给大家安利一款功能强悍好用的工具 - QtScrcpy。 简介 QtScrcpy 是一个强大的安卓手机实时投屏到电脑的开源项目&#xff0c;可以将你的安卓手机…

PHP-extract变量覆盖

[题目信息]&#xff1a; 题目名称题目难度PHP-extract变量覆盖1 [题目考点]&#xff1a; 变量覆盖指的是用我们自定义的参数值替换程序原有的变量值&#xff0c;一般变量覆盖漏洞需要结合程序的其它功能来实现完整的攻击。 经常导致变量覆盖漏洞场景有&#xff1a;$$&#x…

✌粤嵌—2024/3/29—合并两个有序数组 + 赎金信✌

1. 合并两个有序数组 代码实现&#xff1a; 方法一&#xff1a;将数组num2中的元素添加到数组num1的末尾&#xff0c;再排序 void merge(int *nums1, int nums1Size, int m, int *nums2, int nums2Size, int n) {for (int i 0; i < n; i) {nums1[m] nums2[i];}// 冒泡排序…

Navicat 干货 | 了解 PostgreSQL 规则

PostgreSQL 是一个强大的开源关系型数据库管理系统&#xff0c;为增强数据管理和操作提供了丰富的功能。这些功能中包含了规则&#xff0c;这是一种用于控制数据库内部查询和命令处理方式的机制。本文将探讨 PostgreSQL 规则的工作原理&#xff0c;以及它们与触发器的区别&…

【IDEA--dubug相关】Debug项目时启动不了(启动至一半卡住)

下面是一些经常在日常debug时用到的场景&#xff0c;方便查看、与君共勉&#xff01; 文章目录 1. 问题背景2. 可能原因3. 解决办法 最近遇到的一种SpringBoot启动失败的情况&#xff0c;如果有相同情况的&#xff0c;可以看看是否是这个原因 1. 问题背景 用Debug模式启动bo…

鸿蒙入门04-真机运行“遥遥领先”

如果你有一台真的 "遥遥领先"那么是可以直接在手机上真机运行你的项目的我们也来尝试一下运行 一、手机设置开发者模式 打开手机设置 打开手机设置界面 向下滑动到关于手机位置 快速连续点击版本号位置 下图所示位置快速连续点击 打开 3 - 5 次即可 会提示您已经进…

React-Redux(一)

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;React篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来React篇专栏内容:React-Redux&#xff08;一&#xff09; 目录 1、简介 2、三大原则&#xff08;重点&#xf…

数据结构——线性表(顺序表)

数据结构——线性表&#xff08;顺序表&#xff09; 什么是线性表顺序表顺序表结构定义初始化顺序表插入表尾插入扩容遍历指定位置插入头插 删除指定位置删除头删尾删 查找和修改 我们今天进入数据结构的学习&#xff0c;今天我们从梦开始的地方&#xff1a;顺序表。 什么是线…

支付宝支付之SpringBoot整合支付宝入门

支付宝支付 对接流程 申请阿里支付官方企业账号配置应用签约产品获取RSAKey&#xff08;非对称加密&#xff09;必须获得两个加密串&#xff1a;一个公钥&#xff0c;一个密钥SDK功能开发业务对接支付回调支付组件 核心所需的参数 APPID商家私钥支付宝公钥支付回调地址网关…

MDC使用手册精讲

MDC 背景&#xff1a; 线上排查问题时&#xff0c;请求在多个微服务之间进行调用&#xff0c;并发量较大的情况下&#xff0c;想跟踪某一个请求的链路&#xff0c;是需要花费一些时间才能梳理出来&#xff0c;而且还依赖于你的业务字段。而我们需要的是快速定位&#xff0c;快…

Qt 实战(2)搭建开发环境 | 2.1、Windows下安装QT

一、Windows下安装QT 1、QT官网 QT官网&#xff1a;https://download.qt.io/&#xff0c;打开官网地址&#xff0c;如下&#xff1a; 目录结构介绍 目录说明snapshots预览版&#xff0c;最新的开发测试中的 Qt 库和开发工具onlineQt 在线安装源official_releases正式发布版&am…

python将日志写入文件(超详细)

python将日志写入文件(超详细) 1、需求 我们在训练模型的时候&#xff0c;有时候需要将训练日志输出到一个文件中&#xff0c;方便随时查看训练日志。 训练模型时候&#xff0c;训练日志在控制台展示&#xff0c;关闭控制台后日志会消失。这时&#xff0c;我们需要将控制台中…