Java语言---PriorityQueue与堆

这篇具有很好参考价值的文章主要介绍了Java语言---PriorityQueue与堆。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一.堆

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     基于二叉树的知识。

Java语言---PriorityQueue与堆
来源于百度

  使用编译器:IDEA

一.堆

1.1堆的概念

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

分为2种:大堆  小堆

Java语言---PriorityQueue与堆

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

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

 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堆的创建

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

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

Java语言---PriorityQueue与堆

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

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. 将最后新插入的节点向上调整,直到满足堆的性质
Java语言---PriorityQueue与堆 代码实现:

//该方法是传递已经添加了新元素的数组,以及末尾元素下标
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;
}
}
}

堆的删除

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

Java语言---PriorityQueue与堆

代码实现:

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 底层通过 数组 来实现元素的存储。

      在集合框架中的联系:

Java语言---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是线程安全的。
 文章来源地址https://www.toymoban.com/news/detail-483140.html

到了这里,关于Java语言---PriorityQueue与堆的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java【优先级队列】详细图解 / 模拟实现 + 【PriorityQueue】常用方法介绍

    📕各位读者好, 我是小陈, 这是我的个人主页 📗小陈还在持续努力学习编程, 努力通过博客输出所学知识 📘如果本篇对你有帮助, 烦请点赞关注支持一波, 感激不尽 📙 希望我的专栏能够帮助到你: JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统

    2024年02月07日
    浏览(49)
  • Java 数据结构篇-实现堆的核心方法与堆的应用(实现 TOP-K 问题:最小 k 个数)

    🔥博客主页: 【 小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍      文章目录         1.0 堆的说明         2.0 堆的成员变量及其构造方法          3.0 实现堆的核心方法         3.1 实现堆的核心方法 - 获取堆顶元素 peek()         3.2 实现堆的核心方法 - 下潜 do

    2024年02月04日
    浏览(54)
  • 【数据结构】详解二叉树与堆与堆排序的关系

    🌇个人主页:平凡的小苏 📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情 🛸C语言专栏:https://blog.csdn.net/vhhhbb/category_12174730.html 🚀数据结构专栏:https://blog.csdn.net/vhhhbb/category_12211053.html         家人们更新不易,你们的👍点赞👍和⭐关注⭐真的对我

    2024年02月02日
    浏览(42)
  • 深入理解PriorityQueue的特性

    Java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的 使用操作: 1.在我们使用优先级队列时,必须导入相应的包 2.PriorityQueue中放置的元素必须要能够比较大小,不能插入无法比较大小的对象,否

    2023年04月27日
    浏览(43)
  • 优先队列PriorityQueue

    前言 PriorityQueue这个队列不知道大家使用过吗,反正我用的很少,主要对它不是很了解,今天我带领大家剖析下PriorityQueue这个优先级队列。 PriorityQueue介绍 顾名思义,PriorityQueue是优先队列的意思。优先队列的作用是能保证每次取出的元素都是队列中权值最小的。这里牵涉到了

    2024年02月08日
    浏览(31)
  • A Guide to PriorityQueue

    原文链接:https://blog.csdn.net/ohwang/article/details/116934308 PriorityQueue是用 数组 实现,数组大小可以动态增加,容量无限。 优先队列采用的是 堆排序 (默认为最小堆)。堆排序只能保证根是最大(最小),整个堆并不是有序的。 1、非线程安全。线程安全可以用 PriorityBlockingQueu

    2024年02月09日
    浏览(41)
  • 二叉树与堆

    目录 一、二叉树 1、二叉树的概念及结构 1.1、树的概念 1.2、二叉树的概念 1.3、二叉树的存储结构 1.3.1、顺序结构存储 1.3.2、链式结构存储 2、二叉树的实现(链式结构) 2.1、二叉树的遍历 2.1.1、前序、中序以及后序遍历 2.1.2、层序遍历 2.2、二叉树链式结构的代码实现 二、

    2024年02月10日
    浏览(34)
  • 排序-选择排序与堆排序

    思想: 将数组第一个元素作为min,然后进行遍历与其他元素对比,找到比min小的数就进行交换,直到最后一个元素就停止,然后再将第二个元素min,再遍历,以此下去直到最后一个数据 流程图: 代码实现: 运行结果: 选择排序优化: 我们可以设置一个min和一个max,将小的

    2024年02月04日
    浏览(29)
  • 数据结构:堆与堆排序

    目录 堆的定义: 堆的实现: 堆的元素插入: 堆元素删除: 堆初始化与销毁: 堆排序: 堆的定义: 堆是一种完全二叉树,完全二叉树定义如下: 一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二

    2024年01月23日
    浏览(36)
  • Python - 优先队列(queue.PriorityQueue & heapq)

    目录 什么是优先队列 为什么需要优先队列? 优先队列是个啥? 优先队列的工作原理 Python实现一个优先队列 Python内置库中的queue.PriorityQueue的使用 基本操作 多条件优先级实现 Python内置库中的heapq heapq的常用操作 基于heapq实现一个优先队列类 为什么需要优先队列? 有一个小

    2024年02月08日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包