Java优先队列(PriorityQueue)

目录

一.堆

1.堆的概念

2.堆的存储

3.堆的创建

3.1 向下调整

3.2 向上调整

4.堆的删除

5.堆的插入

二.优先级队列介绍

1.构建

2.方法

一.堆

了解优先级队列之前要先了解堆这种数据结构,PriorityQueue的底层也是用堆实现的。

1.堆的概念

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

注意:堆中某个节点的值总是不大于或不小于其父节点的值;堆总是一棵完全二叉树

2.堆的存储

堆我们可以使用顺序表模拟,即用数组模拟堆。

首先定义一个数组来存储值,其次定义一个usedSize来存储我们用过的数组大小。

    public int[] elem;
    public int usedSize;

3.堆的创建

分为两种创建方式,向下调整和向上调整。

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

3.1 向下调整

一个根节点跟其左右子节点的较大值(这里用到是构建大根堆的例子)比较,如果根节点比子节点小,那么就交换两者。如果这样,根节点移动了,它有可能比移动后位置的子节点还小,所以要继续移动,不断向下,因此叫向下调整。

整理上方描述:

1.找出左右子节点的最值;

2.让左右最值与根节点相比;

3.如果根节点小于(大于)左右节点,交换位置;如果不是,退出循环。

    public void down(int[] arr ,int parent){
        int child=parent*2+1;   //如果根有孩子,一定有左孩子的
        int size=arr.length;

        while(child<size){
            //去左右孩子的最大那个
            if(child+1<size && arr[child+1]>arr[child]){
                child=child+1;
            }
            //取出后与父节点值比较
            if(arr[child]>arr[parent]){
                //交换值并继续往下换
                swap(arr,child,parent);
                parent=child;
                child=parent*2+1;
            }else{
                break;
            }
        }
    }

3.2 向上调整

思路一样,也是找最值交换。

 public void up(int[] arr,int child){
        int parent=(child-1)/2;

        while(parent>=0){
            if(arr[child]>arr[parent]){
                swap(arr,child,parent);
                child=parent;
                parent=(child-1)/2;
            }else{
                break;
            }
        }
    }

4.堆的删除

这里的删除是指删除堆顶元素,不是随便删堆里的某一个元素。

思路:将堆顶与堆最后一个元素交换,然后将最后一个元素删掉即可,并且将堆顶元素向下调整。

可行性:我们有一个usedSize一直记录最后一个元素的位置,当时候直接 - - 即可。

public int poll(){
        if(usedSize==0){
            return -1;
        }

        swap(elem,0,usedSize-1);
        int tem=elem[usedSize-1];
        usedSize--;
        down(elem,0);
        return tem;
    }

5.堆的插入

先判满,如果满了要扩容。

直接利用我们定义的usedSize在数组的后面加入一个元素即可。

public void add(int x){
        if(ifFull()){
            elem= Arrays.copyOf(elem,elem.length*2);
        }

        elem[usedSize]=x;
        up(elem,usedSize);
        usedSize++;
    }

二.优先级队列介绍

使用优先级队列必须先导入包:

import java.util.PriorityQueue;

优先级队列默认是小根堆。

1.构建

PriorityQueue<Integer> q = new PriorityQueue<>();

这里默认的容量是11

PriorityQueue<Integer> q = new PriorityQueue<>(100);

可以自己定义大小

大根堆的构建:

import java.util.Comparator;
import java.util.PriorityQueue;

class IntCmp implements Comparator<Integer> {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2-o1;
    }
}


public class Main {
    public static void main(String[] args) {
        PriorityQueue<Integer> p = new PriorityQueue<>(new IntCmp());
    }
}

2.方法

方法功能
boolean offer(E e)插入元素e,插入成功返回true,如果e对象为空,抛出NullPointerException异常,时 间复杂度 ,注意:空间不够时候会进行扩容
E peek()获取优先级最高的元素,如果优先级队列为空,返回null
E poll()移除优先级最高的元素并返回,如果优先级队列为空,返回null
int size()获取有效元素的个数
void clear()清空
boolean isEmpty()检测优先级队列是否为空,空返回true

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值