目录
一.堆
了解优先级队列之前要先了解堆这种数据结构,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 |