PriorityQueue

优先级队列是一种特殊的数据结构,基于堆实现,常用于需要高效获取最大或最小元素的场景。堆是一种完全二叉树,分为大根堆和小根堆,保持父节点大于或小于子节点的特性。文章介绍了堆的创建、插入、删除等操作,并提供了Java代码示例,同时提到了PriorityQueue在Java中的使用注意事项和常用接口。
摘要由CSDN通过智能技术生成

优先级队列

概念: 数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)。
模拟实现: PriorityQueue底层使用了堆这种数据结构 ,而堆实际就是在完全二叉树的基础上进行    了一些调整。

概念: 如果有一个关键码的集合K = {k0 k1 k2 kn-1} ,把它的所有元素按完全二叉树的顺序存储方式存储 在一 个一维数组中,并满足: Ki <= K2i+1 Ki<= K2i+2 (Ki >= K2i+1 Ki >= K2i+2) i = 0 1 2… ,则 称为 小堆 (或大 ) 。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
性质:
(1)堆中某个节点的值总是不大于或不小于其父节点的值;
(2)堆总是一棵完全二叉树。
存储方式: 堆是一棵完全二叉树,因此可以层序的规则采用顺序的方式来高效存储。
        注意:对于非完全二叉树,则不适合使用顺序方式进行存储 ,因为为了能够还原二叉树, 空间中必须要存储空节点 ,就会导致空间利用率比较低。
创建: 默认情况下是小根堆,即每次获得的元素是最小元素
   public void createHeap(int[] array) {
        for(int i = 0;i < array.length;i++){
            elem[i] = array[i];
            usedSize++;
        }
        for (int parent = (usedSize-1-1)/2; parent >= 0 ; parent--) {
            shiftDown(parent,usedSize);
        }
    }

向下调整:

    private void shiftDown(int root,int len) {
        int child = 2 * root + 1;
        while (child < len){
            //一定不会越界
            if (child + 1 < len && elem[child] < elem[child + 1]){
                child = child + 1;
            }
            if (elem[child] > elem[root]){
                int tmp = elem[child];
                elem[child] = elem[root];
                elem[root] = tmp;
                root = child;
                child = 2 * root + 1;
            }
        }
    }

堆的插入:

堆的插入总共需要两个步骤:
1. 先将元素放入到底层空间中 ( 注意:空间不够时需要扩容 )
2. 将最后新插入的节点向上调整,直到满足堆的性质
    public void push(int val) {
        //检查满
        if (isFull()){
            elem = Arrays.copyOf(elem,2*elem.length);
        }
        //存数据
        elem[usedSize] = val;
        usedSize++;
        shiftUp(usedSize-1);
    }

向上调整:

    private void shiftUp(int child) {
        int parent = (child - 1) / 2;
        while (parent > 0){
            if (elem[child] > elem[parent]){
                int tmp = elem[child];
                elem[child] = elem[parent];
                elem[parent] = tmp;
                child = parent;
                parent = (child - 1) / 2;
            }else{
                break;
            }
        }
    }

判断满:

    public boolean isFull() {
        return usedSize == elem.length;
    }

堆的删除:

注意:堆的删除一定删除的是堆顶元素
具体如下:
1. 将堆顶元素对堆中最后一个元素交换
2. 将堆中有效数据个数减少一个
3. 对堆顶元素进行向下调整
    public void pollHeap() {
        if (isEmpty()){
            throw new HeapEmptyException("优先级队列为空!");
        }
        int tmp = elem[0];
        elem[0] = elem[usedSize-1];
        elem[usedSize-1] = tmp;
        usedSize--;
        shiftDown(0,usedSize);
    }

判断空:

    public boolean isEmpty() {
        return usedSize == 0;
    }

堆顶元素:

    public int peekHeap() {
        if (isEmpty()){
            throw new HeapEmptyException("优先级队列为空!");
        }
        return elem[0];
    }
关于PriorityQueue的使用要注意:
  1. 使用时必须导入 PriorityQueue所在的包,即:
import java.util.PriorityQueue;
2. PriorityQueue中放置的元素必须要能够比较大小,不能插入无法比较大小的对象,否则会抛出
  ClassCastException异常
3. 不能 插入 null 对象,否则会抛出NullPointerException
4. 没有容量限制,可以插入任意多个元素,其内部可以自动扩容
5. 插入和删除元素的时间复杂度为
6. PriorityQueue底层使用了堆数据结构
7. PriorityQueue 默认情况下是小堆 ---即每次获取到的元素都是最小的元素    

PriorityQueue常用接口

1.优先级队列的构造
构造器功能介绍
PriorityQueue()
创建一个空的优先级队列,默认容量是 11
PriorityQueue(int
initialCapacity)
创建一个初始容量为 initialCapacity 的优先级队列,注意:
initialCapacity 不能小于 1 ,否则会抛 IllegalArgumentException 异常
PriorityQueue(Collection<?
extends E> c)
用一个集合来创建优先级队列
2. 插入 / 删除 / 获取优先级最高的元素
函数名
功能介绍
boolean offffer(E e)
插入元素 e ,插入成功返回 true ,如果 e 对象为空,抛出 NullPointerException 异常,时间复杂度O(logN)(以2为底),注意:空间不够时候会进行扩容
E peek()
获取优先级最高的元素,如果优先级队列为空,返回 null
E poll()
移除优先级最高的元素并返回,如果优先级队列为空,返回 null
int size()
获取有效元素的个数
void clear()
清空
boolean isEmpty()
检测优先级队列是否为空,空返回true

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值