优先级队列(堆)

目录

一、堆的创建:

二、堆的插入(以大根堆进行调整):

三、堆的删除(最大堆):

四、top-k问题(最小的k个数):

五、优化top-k问题:


一、堆的创建:

默认是以最小堆创建,如果要创建大根堆,那么使用如下:

java 复制代码
//创建大根堆
PriorityQueue<Integer> queue=new PriorityQueue<>(Collections.reverseOrder());
//Collections.reverseOrder()类似于反转


//默认小根堆创建
PriorityQueue<Integer> queue=new PriorityQueue<>();

二、堆的插入(以大根堆进行调整):

思路:

1.先判满,满的话就扩容,用Arrays.Copy(elem,2*elem.length)扩容。

2.向上调整

3.定义parent变量,是最后一个子树的父节点,child是最后一个节点

4.进行比较,如果elemparent<elemchild就交换,循环前提是parent>=0;

java 复制代码
    public void push(int val) {
            if(isFull()){
                elem=Arrays.copyOf(elem,2*elem.length);
            }else{
                elem[usedSize]=val;
                usedSize++;
                shiftUp(usedSize-1);
            }
    }
    //判满
    public boolean isFull() {
            return this.usedSize==elem.length;
    }
    //向上调整
    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;
            }
        }
    }

三、堆的删除(最大堆):

思路:

1.先判空,如果是空的就抛异常

2.把堆头元素和最后一个元素进行交换,然后usedsize--,这样就会减少一个元素然后向下调整

3.循环判断child<len

4.进入循环之后,还要判断右子树是否存在,如果存在,那么说明child+1<len

5.如果elemparent<elemchild就交换

java 复制代码
/**
     * 出队【删除】:每次删除的都是优先级高的元素
     * 仍然要保持是大根堆
     */
    public void pollHeap() {
        if(isEmpty()){
            throw new RuntimeException();
        }
        int tmp=elem[0];
        elem[0]=elem[usedSize-1];
        elem[usedSize-1]=tmp;
        usedSize--;
        shiftDown(0,usedSize);
    }

    /**
     *
     * @param root 是每棵子树的根节点的下标
     * @param len  是每棵子树调整结束的结束条件
     * 向下调整的时间复杂度:O(logn)
     */
    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++;
            }
            if(elem[root]<elem[child]){
                int tmp=elem[root];
                elem[root]=elem[child];
                elem[child]=tmp;
                root=child;
                child=2*root+1;
            }else{
                break;
            }
        }
    }
    public boolean isEmpty() {
        return usedSize==0;
    }

四、top-k问题(最小的k个数):

思路:

1.先创建堆

2.把元素依次放入堆中

3.遍历前k个并打印

java 复制代码
class Solution {
    public int[] smallestK(int[] arr, int k) {
        PriorityQueue<Integer> queue=new PriorityQueue<>(Collections.reverseOrder());
        for(int i=0;i< arr.length;i++){
            queue.offer(arr[i]);
        }
        int[] my_arr=new int[k];
        for(int i=0;i<k;i++){
            my_arr[i]=queue.poll();
        }
        return my_arr;
    }
}

五、优化top-k问题:

思路:

1.如果是求前k个最小,那么就要创建大根堆,如果求前k个最大,那么就创建小根堆

2.创建大小为k的大根堆,把前k个元素放入堆中

3.从k下标开始遍历,先得到堆头元素,拿去跟当前下标k的数组的元素进行比较,如果堆头元素大于当前数组下标k的值,那么就要弹出堆头元素,把数组当前下标k的值入堆。直到遍历结束,这时候堆就会得到最小的k个数。

java 复制代码
class Solution {
    public int[] smallestK(int[] arr, int k) {
        int[] tmp=new int[k];
        if(k==0){
            return tmp;
        }
        PriorityQueue<Integer> queue=new PriorityQueue<>(Collections.reverseOrder());
        for(int i=0;i<k;i++){
            queue.offer(arr[i]);
        }
        for(int i=k;i<arr.length;i++){
            int val=queue.peek();
            if(val>arr[i]){
                queue.poll();
                queue.offer(arr[i]);
            }
        }
        for(int i=0;i<k;i++){
            tmp[i]=queue.poll();
        }
        return tmp;
    }
}
相关推荐
code bean6 分钟前
【C#】 `Channel<T>` 深度解析:生产者-消费者模式的现代解法
数据结构·c#
storyseek1 小时前
前缀和实现Kogge-Stone算法
数据结构·算法
元Y亨H1 小时前
深度解构:数据结构与算法的理论基石与工程演进
数据结构·算法
元Y亨H2 小时前
数据结构与算法的通俗指南
数据结构·算法
2301_764441332 小时前
用动力学系统(微分方程)为 Kernberg 的客体关系单元提供数学化的操作定义,把“自体—客体“这对心理结构建模成一个二维耦合系统
数据结构·python·算法·数学建模
captain3762 小时前
多线程线程安全问题
java·java-ee
CoderYanger2 小时前
A.每日一题:1979. 找出数组的最大公约数
java·程序人生·算法·leetcode·面试·职场和发展·学习方法
灵极海2 小时前
LangChain4j RAG 实战完整指南:从入门到踩坑
java·langchain
yaoxin5211232 小时前
476. Java 反射 - 调用方法
java·开发语言
Ivanqhz3 小时前
Rust Lazy浅析
java·javascript·rust