数据结构(Java):优先级队列(堆)&堆的模拟实现&PriorityQueue集合

目录

1、优先级队列

1.1 概念

1.2 PriorityQueue底层结构

2、 堆

2.1 堆的概念

 2.2 堆的存储结构

3、优先级队列(堆)的模拟实现

3.1 堆的创建

3.1.1 向下调整算法建完整堆

3.2 堆的插入 

3.2.1 向上调整算法

 3.3 堆的删除

3.4 堆排序

4、PriorityQueue集合

 4.1 PriorityQueue的特点

4.2  PriorityQueue的方法

 4.3 PriorityQueue源码分析

4.3.1 成员变量

 4.3.2 构造方法

4.3.3 插入方法(offer)

 4.3.4 扩容方法(扩容机制)

 4.4 TOP-K问题 

4.4.1 TOP-K问题 力扣OJ题 


1、优先级队列

1.1 概念

对于队列而言,数据只能从队尾进,队头出,遵循着固定的先进先出原则。

而在某些特殊场景需求下,要求优先级高的元素先出队列,

在这种情况下,数据结构应该提供两个最基本的操作:

  • ①:不仅能添加新对象
  • ②:还能返回最高优先级对象。

这种数据结构就是优先级队列,Java也提供了PriorityQueue集合。 

1.2 PriorityQueue底层结构

PriorityQueue底层是堆这种数据结构,而堆实际就是在完全二叉树的基础上进行了一些调整,接下来,让我们来聊一聊堆到底是什么。


2、 堆

2.1 堆的概念

 所有元素按完全二叉树的顺序存储方式存储在一个一维数组中。

堆分为 大根堆与小根堆。

大根堆:每个节点都大于或等于其子节点。

小根堆:每个节点都小于或等于其子节点。


 2.2 堆的存储结构

我们已知堆为一棵完全二叉树,故采用顺序的方式存储在数组中。

而对于我们之前所学的二叉树,为什么没有采用顺序存储而是采用链式存储呢?

因为二叉树并非都为完全二叉树,若采用顺序存储会造成空间浪费:

因为堆采用顺序的方式进行存储,且为完全二叉树,故具有以下性质:

  1. 孩子节点下标为i,则其父亲节点下标为(i - 1)/2
  2. 父亲下标为i,则其左孩子下标为2i+1(2i+1<节点总数的情况下,否则无左孩子)
  3. 父亲下标为i,则其右孩子下标为2i+2(2i+2<节点总数的情况下,否则无右孩子)

3、优先级队列(堆)的模拟实现

3.1 堆的创建

 向下调整算法

向下调整算法:选出其左右孩子中值较小值元素(建大堆就选较大元素,建小堆就选较小元素,这里以建小堆为例),将这个元素和根节点进行比较,若比根节点还小,就和根节点交换,交换后可能导致子树不满足堆的性质,因此需要继续向下调整。

注意:向下调整算法的使用,必须要求其左右子树必须为大根堆或者小根堆!!!

向下调整算法的时间复杂度为:O(logN),因为最坏情况是从根一路比较到叶子,比较的次数即为完全二叉树的高度次。

3.1.1 向下调整算法建完整堆

我们给出一组数据:{ 27,15,19,18,28,34,65,49,25,37 },要想将这组数据建成堆,我们可以使用向下调整法建堆。

而一组乱序数据其左右子树是不为堆的,那就需要通过向下调整算法从倒数第一个非叶子节点(下标为(数组.length-1-1)/2 )开始建堆,直到将整棵树建成堆。

建堆的时间复杂度为:O(N)!!!,

什么不是O(N*logN)呢?这里给出解释:

注:下文中代码实现的为大堆

向下调整整体建堆代码:

/**
     * 建堆整体时间复杂度:O(N)
     */
    public void createHeap() {
        //从倒数第一个飞非叶子节点开始建堆
        int parent = (this.usedSize - 1 - 1)/2;
        while (paren
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值