Java语言---PriorityQueue与堆

news2024/11/28 8:30:13

目录

一.堆

1.1堆的概念

 1.2堆的存储方式

1.3堆的操作

1.3.1堆的创建

1.3.2代码的实现:

           堆的插入元素

           堆的删除

二、PriorityQueue   

2.1概念  

2.2性质 

 2.3PriorityQueue的创建构造

 2.4PriorityQueue的操作方法

总结


😽个人主页:tq02的博客_CSDN博客-C语言,Java,Java数据结构领域博主
 🌈梦的目标:努力学习,向Java进发,拼搏一切,让自己的未来不会有遗憾。
 🎁欢迎各位→点赞👍 + 收藏⭐ + 评论📝+关注
  本章讲解内容:堆与PriorityQueue     基于二叉树的知识。

来源百度
来源于百度

  使用编译器:IDEA

一.堆

1.1堆的概念

,也称优先级队列,是存放元素的集合。而所存放的元素按照 完全二叉树的顺序存储方式。堆中每个结点总是 不大于或不小于 其父结点。

分为2种:大堆  小堆

大堆: 父结点的值 大于 子结点,也就是根结点的值最大。

小堆: 父结点的值 小于 子结点,也就是根结点的值最小。

 1.2堆的存储方式

        虽然堆的存储方式按照完全二叉树,完全二叉树实现有2种方式(链表 或者 数组)。而此时因为堆的性质,使用一维数组的方式存储更为高效。堆中元素层序存储到一维数组。

代码实现:

public class MyHeap{

   public int[] array;
   public int capacity;   //数组容量
   public int index;  //数组大小

    MyHeap(){
    array=new int[10];
    this.capacity=10;
    this.index=0;
}
    MyHeap(int num)
    {
    array=new int[num];
    this.capacity=num;
    this.index=0;
    }
//向下调整结点方法
public void shiftDown(int[] array, int parent);
//插入新元素
public void shiftUp(int[] array,int child);
//删除堆顶元素
public void delectHeap(int[] array);

1.3堆的操作

在使用Java语言操作 堆 之前,我们需要明确几个性质。

1、堆是完全二叉树,除了最后一层,每一层的结点都是满的。

2、当序号为 i 时

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

1.3.1堆的创建

在堆中,我们很明显是需要将一个集合,变成大堆,或者小堆的。

 此刻我们展开一下变大堆的过程:

解析:创建大堆,方法:每个子树变成大堆。

1. 让parent标记最后一个结点的父结点,child标记parent的左孩子(注意:parent如果有孩子一定先是有左孩子)
2. 如果parent的左孩子存在,即:child < size(数组长度),进行以下操作,直到parent的左孩子不存在

  • parent右孩子是否存在,存在找到左右孩子中最大的孩子,让child进行标记
  • 将parent与较大的孩子child比较,如果:

              parent小于较大的孩子child,调整结束

            否则:交换parent与较大的孩子child,交换完成之后,parent中大的元素向下移动,可能                导致子树不满足对的性质,因此需要继续向下调整,即parent = childchild = parent*2+1;               然后继续2.

1.3.2代码的实现:

//向下调整结点方法
public void shiftDown(int[] array, int parent) {
// child先标记parent的左孩子,因为parent可能右左没有右
    int child = 2 * parent + 1;
    int size = array.length;
    while (child < size) {
    // 如果右孩子存在,找到左右孩子中较小的孩子,用child进行标记
    if(child+1 < size && array[child+1] > array[child]){
    child += 1;
    } 
// 如果双亲比其最大的孩子小,说明该结构已经满足堆的特性了
    if (array[parent] >= array[child]) {
    break;
    }else{
    int t = array[parent];   //将双亲与较大的孩子交换
    array[parent] = array[child];
    array[child] = t;
// parent中大的元素往下移动,可能会造成子树不满足堆的性质,因此需要继续向下调整
    parent = child;
    child = parent * 2 + 1;
    }
    }
}

public void heapJust(int[] array)
{
   for(int i=(array.length-1-1)/2;i>=0;i--)
    {
        shiftDown(array,i);
    }
}

堆的插入元素

1. 先将元素放入到数组的最后一位中(二叉树的末端)(注意:空间不够时需要扩容)
2. 将最后新插入的节点向上调整,直到满足堆的性质
 代码实现:

//该方法是传递已经添加了新元素的数组,以及末尾元素下标
public void shiftUp(int[]array,int child) {
// 找到child的双亲
    int parent = (child - 1) / 2;
    while (child > 0) {
// 如果双亲比孩子大,parent满足堆的性质,调整结束
    if (array[parent] > array[child]) {
    break;
    } 
    else{
// 将双亲与孩子节点进行交换
    int t = array[parent];
    array[parent] = array[child];
    array[child] = t;
// 小的元素向下移动,可能到值子树不满足对的性质,因此需要继续向上调增
    child = parent;
    parent = (child - 1) / 1;
}
}
}

堆的删除

        删除的是堆顶元素,将堆顶元素与最后一位交换,将堆中有效数据个数减少一位,再进行向下调整。

代码实现:

public void delectHeap(MyHeap t)
{
 int[] array1=t.array;       
 int i=array1.length-1;
//swap方法,是交换数组元素
     swap(array1,i,0);
//删除末尾元素
    array1[index]=0;
    t.index--;
//堆顶元素再向下调整
    shiftDown(array1,0);
}



二、PriorityQueue   

2.1概念  

     1、 PriorityQueue的类型是优先级队列,优先队列的作用是保证每次取出的元素都是队列中权值最小/最大

     2、 PriorityQueue 是采用 树形结构 来描述元素的存储,具体说是通过完全二叉树实现一个小顶堆,在物理存储方面,PriorityQueue 底层通过 数组 来实现元素的存储。

      在集合框架中的联系:

2.2性质 

      1、底层运用了 堆 数据结构,并且默认情况下,为小堆。 

      2、默认情况下容量为11,无容量限制,内部可自动扩容。

      3、不可以插入无法比较的对象,会抛出异常。

      4、不可以插入null对象。

注:因为默认情况为小堆,所以需要大堆时,需要用户提供比较器

 2.3PriorityQueue的创建构造

 三种构造方法:

构造器
PriorityQueue()创建一个空的优先级队列,默认容量:11
PriorityQueue( int capacity)创建一个初始容量为capacity的优先级队列
PriorityQueue(Collection<? extends E> c)用一个集合创建优先级队列

代码实例:

public void TestPriorityQueue(){
// 创建一个空的优先级队列,底层默认容量是11
PriorityQueue<Integer> q1 = new PriorityQueue<>();

// 创建一个空的优先级队列,底层的容量为initialCapacity
PriorityQueue<Integer> q2 = new PriorityQueue<>(100);


// 用ArrayList对象来构造一个优先级队列的对象
// q3中已经包含了三个元素
ArrayList<Integer> list = new ArrayList<>();
list.add(4);
list.add(3);
list.add(2);
list.add(1);

PriorityQueue<Integer> q3 = new PriorityQueue<>(list);
System.out.println(q3.size());
System.out.println(q3.peek());

 2.4PriorityQueue的操作方法

常用的方法:插入、删除、获取优先级最高(堆顶元素)

函数名        功能介绍
boolean offer(E e)插入元素e,插入成功返回true,如果e对象为空,抛出NullPointerException异常,时间复杂度 ,注意:空间不够时候会自主扩容
E peek()获取优先级最高(堆顶)的元素,如果为空,返回null
E pool()移除优先级最高的元素并返回,如果为空,返回null。
int size()获取有效元素个数
void clear()清空
Boolean isEmpty()检测堆是否为空,空返回true

注:如果容量小于64,按照原来的空间*2扩容

       如果容量等于64,则按照原来空间*1.5扩容

       如果容量超过MAX_ARRAY_SIZE,按照MAX_ARRAY_SIZE来扩容(不需要深究)

 代码实现:

public void TestPriorityQueue2(){
    int[] arr = {4,1,9,2,8,0,7,3,6,5};
// 一般在创建优先级队列对象时,如果知道元素个数,建议就直接将底层容量给好
// 否则在插入时需要不多的扩容
// 扩容机制:开辟更大的空间,拷贝元素,这样效率会比较低
    PriorityQueue<Integer> q = new PriorityQueue<>(arr.length);
    for (int e: arr) {
      q.offer(e);
    } 
   System.out.println(q.size()); // 打印优先级队列中有效元素个数
   System.out.println(q.peek()); // 获取优先级最高的元素
// 从优先级队列中删除两个元素之和,再次获取优先级最高的元素
        q.poll();
        q.poll();
    System.out.println(q.size()); // 打印优先级队列中有效元素个数
    System.out.println(q.peek()); // 获取优先级最高的元素
        q.offer(0);
    System.out.println(q.peek()); // 获取优先级最高的元素
// 将优先级队列中的有效元素删除掉,检测其是否为空
    q.clear();
    if(q.isEmpty()){
    System.out.println("优先级队列已经为空!!!");
    } 
   else{
    System.out.println("优先级队列不为空");
    }
}

总结

        我们先得明白堆是什么?堆是一种优先级队列,可采用二叉树的形式来表达存储方式。在Java程序中,以及写好相关的类(PriorityQueue),可以使用。

      值得一提的是:Java的集合框架中提供了2种类型的优先级队列:PriorityQueue和PriorityBlockingQueue。但由于PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的。
 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

堆的应用:Top-K问题

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下堆的应用--Top-K问题的相关知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; 数据结构与算法专栏&#xff1a;数据结构与算法 个…

基于Web智慧油库三维可视化管理系统

油库是协调原油生产、原油加工、成品油供应及运输的纽带&#xff0c;是国家石油储备和供应的基地&#xff0c;它对于保障国防和促进国民经济高速发展具有相当重要的意义。 建设背景 石油作为重要的战略资源&#xff0c;关系着国家安全和人民生活。油库是石油能源供应链中的关…

俞浩“死磕”抖音,追觅科技618面临三变数

​文 | 智能相对论 作者 | 渡过 智能清洁“新秀”追觅科技来势汹汹。 创始人俞浩曾向媒体表示&#xff0c;“追觅科技……2023年做到行业技术第一&#xff0c;2024年做到行业市占率第一&#xff0c;2025年做到行业利润第一。” 具体到市场上&#xff0c;能拱火热度的电商节…

linux实践php8.2加laravel-cotane和roadrunner服务器

php8.2 composer -v 报错&#xff1a; Deprecation Notice: strlen(): Passing null to parameter #1 ($string) of type string is deprecated in phar:///usr/bin/composer/vendor/symfony/console/Descriptor/TextDescriptor.php:290 解决方法可以升级下composer&#xff1…

像写 Rust 一样写 Python!

几年前&#xff0c;开始使用Rust编程&#xff0c;它逐渐改变了我使用其他编程语言&#xff08;尤其是Python&#xff09;设计程序的方式。在我开始使用Rust之前&#xff0c;我通常以一种非常动态和类型松散的方式编写Python代码&#xff0c;没有类型提示&#xff0c;到处传递和…

2023年江西省大学生程序设计竞赛vp赛后补题

Problem - B - Codeforces 思路&#xff1a; 显然难以讨论<的情况&#xff0c;正难则反&#xff0c;我们尝试计算>的情况以为每次a&#xff0c;他的实际贡献给b的是a%m&#xff0c;x也一样&#xff0c;所以他们先取mod我们能够大于成立&#xff0c;要求a[i]sum>mod,…

常用的表格检测识别方法——表格结构识别方法 (下)

常用的表格检测识别方法——表格结构识别方法&#xff08;下&#xff09; 3.2表格结构识别方法 表格结构识别是表格区域检测之后的任务&#xff0c;其目标是识别出表格的布局结构、层次结构等&#xff0c;将表格视觉信息转换成可重建表格的结构描述信息。这些表格结构描述信息…

深度剖析数据在内存中的存储(超详细版)

&#x1f495;"痛苦难以避免&#xff0c;而磨难可以选择。"-->村上春树&#x1f495; 作者&#xff1a;Mylvzi ​​​​​​​ 文章主要内容&#xff1a;数据在内存中的存储 目录 前言&#xff1a;数据在计算机中的存储 正文&#xff1a; 1.详解数据类型 2.整…

2023-05-31 Git将已存在的项目上传到仓库

背景 正常情况下我们是在GitHub(Gitee是一样的&#xff0c;还不卡&#xff0c;因此下文将在Gitee仓库操作)创建一个代码仓库&#xff0c;然后将仓库拉到本地&#xff0c;在本地会生成一个和仓库名称一样的文件夹&#xff0c;然后在文件夹内写代码&#xff0c;最后使用git命令将…

9 概率图模型【手写笔记】

文章目录 9 概率图模型【手写笔记】9.1 背景介绍9.2 贝叶斯网络&#xff08;Bayesian Network&#xff09;——有向图网络9.3 马尔可夫网络&#xff08;Markov Network&#xff09;——无向图网络9.4 Inferce&#xff08;推断&#xff09;——求解后验9.5 更多的图的概念 9 概率…

2023年DAMA-CDGA/CDGP数据治理认证考试形式、含金量

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…

表的约束.

目录 表的约束空属性默认值列描述zerofill主键自增长唯一键外键综合案例 表的约束 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&#xff0c;需要有一些额外的约束&#xff0c;更好的保证数据的合法性&#xff0c;从业务逻辑角度保证数据的正确性。比如有一个…

一文带你了解MySQL之undo日志

目录 一、事务回滚的需求二、事务id2.1 给事务分配id的时机2.2 事务id是怎么生成的2.3 trx_id隐藏列 三、undo日志的格式3.1 INSERT操作对应的undo日志3.2 DELETE操作对应的undo日志3.3 UPDATE操作对应的undo日志3.3.1 不更新主键的情况3.3.2 更新主键的情况 四、通用链表结构五…

法国ESC高等商学院DBA申请

申请法国ESC高等商学院DBA&#xff0c;你需要了解这些&#xff01;什么是法国ESC高等商学院DBA&#xff1f;法国ESC高等商学院DBA是法国商学院中的顶尖学位&#xff0c;也是全球最优秀的商学博士学位之一。该学位旨在为商业领袖、企业家和高级管理人员提供高水平的商业教育和研…

优秀的工具=生产力!15款高效原型设计软件种草

一个优秀产品的诞生&#xff0c;必定离不开原型设计。产品原型是概念到现实的桥梁&#xff0c;是产品成功的关键&#xff01; 为什么产品原型如此重要&#xff1f;产品原型可以帮助团队更高效地测试产品可行性、理解和评估用户需求并不断优化迭代产品的最终方案。它决定了最终…

windows10系统mysql官方绿色版安装

1.下载 1&#xff09;下载页面&#xff1a;MySQL :: Download MySQL Community Server 2&#xff09;点击 Download 按钮下载zip包到本地&#xff0c;解压&#xff08;我的本地解压到了D:\Programs\mysql-8.0.33-winx64&#xff09; 2.环境配置 1&#xff09;环境变量配置&a…

柜体内形成电弧的四个阶段及弧光保护装置的设计

安科瑞虞佳豪 什么是弧光保护 弧光保护是指电力系统由于各种的短路原因可引起弧光&#xff0c;弧光会以300m/s的速度爆发&#xff0c;摧毁途中的任何物质。只要系统中不断电&#xff0c;弧光就会一直存在。要想最大限度的减少弧光的危害&#xff0c;我们需要安全、迅速地切断…

Java开发手册中为什么禁止使用BigDecimal的equals方法做等值比较已经为什么禁止使用double直接构造BigDecimal

场景 阿里Java开发手册嵩山版中明确指出&#xff1a; 1、BigDecimal的等值比较应使用compareTo()方法&#xff0c;而不是equals()方法 equals()方法会比较值和精度&#xff08;1.0与1.00返回结果为false&#xff09;,而compareTo()则会忽略精度 2、禁止使用构造方法BigDeci…

FAQ是什么?如何打造一个高效的FAQ页面?

FAQ是英文Frequently Asked Questions的缩写&#xff0c;即“常见问题解答”。FAQ系统是一个集中管理和展示常见问题和答案的工具。 FAQ页面一般放在网站的主菜单或底部导航栏中&#xff0c;通常与“联系我们”、“关于我们”等页面并列。有些网站还会在页面上方或右侧设置“常…

android开发之NDK配置开发

1、打开项目后&#xff0c;一次点击Tools>SDK Manager 2、点击SDK Tools标签页 3、选中NDK&#xff08;Side by Side&#xff09;和CMake复选框 4、点击OK 此时系统会显示一个对话框&#xff0c;告诉你NDK软件包占用了多少磁盘空间 5、点击OK 6、安装完成后&#xff0c;点击…