一.优先级队列
概念:队列的元素是遵循先进先出的原则,而优先级队列是优先级最高的先出队列
二.堆
概念:
对一个集合元素,堆是按照完全二叉树的顺序存储方式把数据存储到一维数组中
分为大根堆和小根堆
图像:
性质:
堆中某个节点的值总是不大于或不小于其父节点的值;
堆总是一棵完全二叉树。
三.大小堆的模拟实现
可以分为向上和向下过程分为俩种模式
向下过程:
向上过程:
public void shiftUp(int child){
int pre =(child-1)/2;
while (pre >= 0) {
if(elem[pre]<elem[child]){
swap(elem,child,pre);
child=pre;
pre=(child-1)/2;
}else {
break;
}
}
}
四.PriorityQueue的模拟实现
public void offer(int value){
if(isFull()){
grow();
}
elem[size]=value;
shiftUp(size);
size++;
}
public int poll(){
if(isEmpty()){
return -1;
}
int ret =elem[0];
size--;
swap(elem,0,size);
shiftDown(0,size);
return ret;
}
public int peek(){
if (isEmpty()){
return -1;
}
return elem[0];
}
注意:
利用以上的offer方法(向上过程)就可以创建堆
原理:在一个大根堆或小根堆最后一个空间插入,再向上过程(shifup),就形成了大根堆或小根堆
poll方法原理:将0下标和未下标的值交换位置,尾下标向前一位,在对0这棵树进行调整
优点:由于之前为大根堆或小根堆,交换位置后,只要0下标这棵树不是小根堆或大根堆,只需要向下调整0下标这颗大树即可就能转化为小根堆或大根堆
五.向下过程和向上过程创建堆的复杂度
六.堆排序
过程:
1. 建堆
升序:建大堆
降序:建小堆
2. 利用堆删除思想来进行排序
举例:
七.PriorityQueue的方法和使用
1.方法
2.使用
3.默认创建为小根堆的原因和如何创造出大根堆
八.Top-K问题
TOP-K问题:即求数据集合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。
方法1:
public int[] smallestK(int[] arr, int k) {
PriorityQueue<Integer> queue = new PriorityQueue<>();
for(int i=0;i<arr.length;i++){
queue.offer(arr[i]);
}
int[] ret =new int[k];
for(int j=0;j<k;j++){
ret[j]=queue.poll();
}
return ret;
}
时间复杂度为:
class Bigheap implements Comparator<Integer>{
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
}
class Solution {
public int[] smallestK(int[] arr, int k) {
int[] ret =new int[k];
if(arr==null||k==0){
return ret;
}
Bigheap bigheap =new Bigheap();
PriorityQueue<Integer> queue = new PriorityQueue<>(bigheap);
//klogk
for(int i=0;i<k;i++){
queue.offer(arr[i]);
}
//(N-k)logk
for(int j=k;j<arr.length;j++){
int max=queue.peek();
if(max>arr[j]){
queue.poll();
queue.offer(arr[j]);
}
}
//klogk
for(int s =0;s<k;s++){
ret[s]=queue.poll();
}
return ret;
}
}
时间复杂度为:
同过比较第二种方法好一些。