PriorityQueue(优先级队列)的解读与底层实现

2023-05-16

 

目录

1.什么是优先级队列?

2.优先级队列的特性

3. 如何使用优先级队列

4.JDK源码分析

4.1类的继承关系

4.2类的属性

4.3常用的方法

5.自定义优先级队列实现

5.1 优先级队列类定义

5.2 add()方法 

5.3 remove()方法 

5.4 removeAt()方法

5.5 完整代码


1.什么是优先级队列?

普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。

在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出(first in, largest out)的行为特征。通常采用堆数据结构来实现。

根据jdk源码中的描述:

优先级队列表示为平衡二进制堆:队列[n]的两个子级是队列[2*n+1]和队列[2*(n+1)]。

优先级队列由comparator排序,如果comparator为null,则由元素的自然顺序排序:对于堆中的每个节点n和n的每个后代d,n<=d。假设队列不为空,则值最低的元素位于队列[0]中。

2.优先级队列的特性

  • PriorityQueue是非线程安全,PriorityBlockingQueue是线程安全的,基于BlockingQueue接口实现。
  • 优先级队列就相当于有一个任务调度系统 给每一个任务排一个优先级 所有的任务放到优先级队列 执行任务的线程会从队列中选择一个优先级最高的任务执行。
  • PriorityQueue基于优先堆(大根堆/小根堆),在默认情况下使用的是小根堆,这个优先队列可以默认自然排序或者通过提供的Compartor(比较器)在队列实例化的时候进行排序。
  • 不允许null元素 不支持non-comparable元素

3. 如何使用优先级队列

分别创建了一个普通队列和一个优先级队列,优先级队列的排序采用的是Person类中的id大小进行排序的。

class Person{
    private int id;
    private String name;

    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
public class TestDemo7 {
    public static Comparator<Person> idComparator = new Comparator<Person>() {
        @Override
        public int compare(Person o1, Person o2) {
            return o2.getId() - o1.getId();
        }
    };

    public static void main(String[] args) {
        //练习1:
        Queue<Integer> integerPriorityQueue = new PriorityQueue<>();
        for(int i=0; i<10; i++){
            integerPriorityQueue.add(new Integer(new Random().nextInt(100)));
        }
        for(int i=0; i<10; i++){
            Integer in = integerPriorityQueue.remove();
            System.out.println("priority queue: "+in);
        }
        //练习2:
        Queue<Person> personPriorityQueue = new PriorityQueue<>(idComparator);
        for(int i=0; i<10; i++){
            int id=new Random().nextInt(100);
            personPriorityQueue.add(new Person(id, "person"+id));
        }

        for(int i=0; i<10; i++){
            Person per = personPriorityQueue.remove();
            System.out.println("person priority queue: "+per);
        }
    }
}

 

4.JDK源码分析

4.1类的继承关系

  • PriorityQueue基于Queue接口实现,在Queue接口和PriorityQueue具体实现类间提供了一个AbstractQueue抽象类
  • PriorityQueue是一个

4.2类的属性

  • private static final int DEFAULT_INITIAL_CAPACITY = 11;//默认容量
  • transient Object[] queue;//底层实现数组
  • private int size = 0;//有效元素个数
  • private final Comparator<? super E> comparator;//按照比较器对象进行排序
  • transient int modCount = 0;//修改次数

4.3常用的方法

  • add()与offer()

add()和offer()都是向队列中添加一个元素。一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,调用 add() 方法就会抛出一个 unchecked 异常,而调用 offer() 方法会返回 false,因此就可以在程序中进行有效的判断。

  • remove()与poll()

remove() 和 poll() 方法都是从队列中删除第一个元素。如果队列元素为空,调用remove() 的行为与 Collection 接口的版本相似会抛出异常,但是新的 poll() 方法在用空集合调用时只是返回 null,因此新的方法更适合容易出现异常条件的情况。

  • grow()扩容函数,扩的容量为minCapacity

对于这里的扩容,为了让数组的长度为一个素数,从而保证为一个完全二叉树。 

  • element()和peek()

element()peek()的语义完全相同,都是获取但不删除队首元素,也就是队列中权值最小的那个元素,二者唯一的区别是当方法失败时前者抛出异常,后者返回null。根据小顶堆的性质,堆顶那个元素就是全局最小的那个;由于堆用数组表示,根据下标关系,0下标处的那个元素既是堆顶元素。所以直接返回数组0下标处的那个元素即可。

  • siftDownUsingComparator()

k为根节点,用c保存左孩子,左孩子k*2+1,右孩子k*2+2,如果右孩子存在并且右孩子要比左孩子小,将右孩子赋给c,并进行下标更新,之后与x进行比较,如果x还小就break不用进行调整,否则就将c给k位置,然后进行位置更新,最后将x赋值给k位置。

 

5.自定义优先级队列实现

5.1 优先级队列类定义

优先级队列基于数据结构堆(默认小根堆)去实现,而堆常用数组实现,因此在类中定义一个泛型数组,size为有效元素个数,初始容量设为5。

public class MyPriorityQueue<E extends Comparable<E>> {
    private E[] queue;
    private int size;
    private static final int initalCapacity = 5;
    public MyPriorityQueue(){
        this(initalCapacity);
    }

    public MyPriorityQueue(int initalCapacity){
        queue = (E[])new Comparable[initalCapacity];
    }
}

5.2 add()方法 

该方法用于向优先级队列中添加元素。

1).在进行添加元素的时候,首先要判断当前容量是否已满,如果满了需要进行扩容。

2).当队列为空时,直接赋值给首位元素,szie自增

3). 正常情况下,添加元素后,可能会导致堆不是小根堆,因此利用adjustUP()进行向上调整。

因为底层基于数组,0号元素就是顶点,size-1为最后一个节点。

由子节点下标推父节点下标,当子节点下标为index时,父节点为(index-1)/2.

利用while循环对当前位置节点与其父节点依次进行比较,若父节点大于当前value,将父节点值给当前位置,然后记录父节点下标继续判断,若父节点不大于当前节点值,则现在已经是小根堆,不必调整了,循环结束后将value赋值给index位置。

public void add(E value){
        //容量不足扩容
        if(size == queue.length){
            queue = Arrays.copyOf(queue, queue.length<<1);
        }
        //队列为空
        if(size == 0){
            queue[0] = value;
            size++;
        }
        else{
            adjustUP(size, value);
            size++;
        }
    }


    public void adjustUP(int index, E value){
        //向上调整
        while(index > 0){
            //由子节点推父节点下标
            int parentIndex = (index-1)/2;
            //若父节点大于当前value,将父节点值给当前位置,然后记录父节点下标继续判断
            if(queue[parentIndex].compareTo(value) > 0){
                queue[index] = queue[parentIndex];
                index = parentIndex;
            }
            //若父节点不大于当前节点值,则现在已经是小根堆,不必调整了
            else{
                break;
            }
        }
        //将value赋给index位置
        queue[index] = value;
    }

5.3 remove()方法 

该方法用于删除根节点,同add方法类似,首先对队列进行判空,然后考虑队列只有一个元素的情况。

在正常情况下,要保证底层维护的是一个小根堆,删除的是0号位置元素,因此要把最后一个节点放到0号位置。

首先将0号位置置空,然后进行向下调整。

在向下调整的过程中,由于并不知道根节点的左右孩子哪个值较小,因此要进行判断,并分别用minIndex和minValue记录较小值的下标和值,然后将value与这个较小值进行比较,如果根节点小于minValue直接break,不用调整了,本身就还是小根堆,否则就将minValue赋值给index位置,然后进行下标更新。循环结束后将value赋值给queue[index]。

public boolean remove(){
        //删除根节点元素
        //判空
        if(size == 0){
            return false;
        }
        //当前队列只有一个元素
        if(size == 1){
            queue[size-1] = null;
            return true;
        }
        //正常情况,保证底层维护的是一个小根堆,删除的是0号位置元素,把最后一个节点放到0号位置
        queue[0] = null;
        adjustDown(0,queue[--size]);
        return true;
    }

    public void adjustDown(int index, E value){
        //向下调整
        while (index < (size>>1)){
            int leftChild = index*2 + 1;
            int rightChild = index*2 + 2;
            //保存两个孩子中最小孩子的下标
            int minIndex = 0;
            //保存当前的最小值
            E minValue = null;
            //找左右孩子的最小值
            if(rightChild < size && queue[leftChild].compareTo(queue[rightChild]) >= 0){
                minValue = queue[rightChild];
                minIndex = rightChild;
            }
            if(value.compareTo(minValue) < 0){
                break;
            }
            queue[index] = minValue;
            index = minIndex;
        }
        queue[index] = value;
    }

5.4 removeAt()方法

   public boolean remove(E target){
        //删除指定元素
        int index = -1;
        //找到target所在的位置点
        for (int i = 0; i < size; i++) {
            if(target.equals(queue[i])){
                index = i;
                break;
            }
        }
        //保证队列中有这样的位置点
        if(index == -1){
            return false;
        }
        //特殊情况,删除的是最后一个元素
        if(size-1 == index){
            queue[--size] = null;
            return true;
        }
        //正常情况下
        else {
            queue[index] = null;
            adjustDown(index, queue[size - 1]);
            //特殊情况
            if (queue[index] == queue[size - 1]) {
                adjustDown(index, queue[size - 1]);
            }
            queue[--size] = null;
            return true;
        }
    }

5.5 完整代码

package sefl.January;

import java.util.Arrays;

/**
 * Description :
 * Created by Resumebb
 * Date :2021/1/7
 */
public class MyPriorityQueue<E extends Comparable<E>> {
    private E[] queue;
    private int size;
    private static final int initalCapacity = 5;
    public MyPriorityQueue(){
        this(initalCapacity);
    }

    public MyPriorityQueue(int initalCapacity){
        queue = (E[])new Comparable[initalCapacity];
    }

    public void add(E value){
        if(size == queue.length){
            queue = Arrays.copyOf(queue, queue.length<<1);
        }
        if(size == 0){
            queue[0] = value;
            size++;
        }
        else{
            adjustUP(size, value);
            size++;
        }
    }


    public void adjustUP(int index, E value){
        //向上调整
        while(index > 0){
            //由子节点推父节点下标
            int parentIndex = (index-1)/2;
            //若父节点大于当前value,将父节点值给当前位置,然后记录父节点下标继续判断
            if(queue[parentIndex].compareTo(value) > 0){
                queue[index] = queue[parentIndex];
                index = parentIndex;
            }
            //若父节点不大于当前节点值,则现在已经是小根堆,不必调整了
            else{
                break;
            }
        }
        //将value赋给index位置
        queue[index] = value;
    }

    public boolean remove(){
        //删除根节点元素
        //判空
        if(size == 0){
            return false;
        }
        //当前队列只有一个元素
        if(size == 1){
            queue[size-1] = null;
            return true;
        }
        //正常情况,保证底层维护的是一个小根堆,删除的是0号位置元素,把最后一个节点放到0号位置
        queue[0] = null;
        adjustDown(0,queue[--size]);
        return true;
    }

    public void adjustDown(int index, E value){
        //向下调整
        while (index < (size>>1)){
            int leftChild = index*2 + 1;
            int rightChild = index*2 + 2;
            //保存两个孩子中最小孩子的下标
            int minIndex = 0;
            //保存当前的最小值
            E minValue = null;
            //找左右孩子的最小值
            if(rightChild < size && queue[leftChild].compareTo(queue[rightChild]) >= 0){
                minValue = queue[rightChild];
                minIndex = rightChild;
            }
            if(value.compareTo(minValue) < 0){
                break;
            }
            queue[index] = minValue;
            index = minIndex;
        }
        queue[index] = value;
    }

    public boolean removeAt(E target){
        //删除指定元素
        int index = -1;
        //找到target所在的位置点
        for (int i = 0; i < size; i++) {
            if(target.equals(queue[i])){
                index = i;
                break;
            }
        }
        //保证队列中有这样的位置点
        if(index == -1){
            return false;
        }
        //特殊情况,删除的是最后一个元素
        if(size-1 == index){
            queue[--size] = null;
            return true;
        }
        //正常情况下
        else {
            queue[index] = null;
            adjustDown(index, queue[size - 1]);
            //特殊情况
            if (queue[index] == queue[size - 1]) {
                adjustDown(index, queue[size - 1]);
            }
            queue[--size] = null;
            return true;
        }
    }

    public String toString(){
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < size; i++) {
            stringBuilder.append(queue[i] +" ");
        }
        return stringBuilder.toString();
    }

    public static void main(String[] args) {
        MyPriorityQueue<Integer> queue = new MyPriorityQueue<>();
        queue.add(3);
        queue.add(5);
        queue.add(7);
        queue.add(2);
        queue.add(4);
        queue.add(1);
        System.out.println(queue.toString());
        queue.remove();
        System.out.println(queue.toString());
        queue.removeAt(5);
        System.out.println(queue.toString());
    }
}

测试: 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PriorityQueue(优先级队列)的解读与底层实现 的相关文章

  • PriorityQueue(优先级队列)的解读与底层实现

    目录 1 什么是优先级队列 xff1f 2 优先级队列的特性 3 如何使用优先级队列 4 JDK源码分析 4 1类的继承关系 4 2类的属性 4 3常用的方法 5 自定义优先级队列实现 5 1 优先级队列类定义 5 2 add 方法 5 3
  • priority_queue元素为指针时,重载运算符失效

    使用priority queue构造最大最小堆时 发现priority queue中元素为指针时 std greater std less函数并不能调用到自定义数据的重载运算符 排序结果是根据指针地址大小计算的 从而导致最大最小堆失效 in
  • java中整数数组的优先级队列

    我想按数组 0 30 5 10 15 20 的第二个元素进行比较 PriorityQueue
  • 是否有具有固定容量和自定义比较器的 PriorityQueue 实现?

    相关问题 具有固定大小的 Java PriorityQueue 如何使用优先队列 获取数组中 n 个最小元素的索引 Scala 有没有办法像在 Java 中一样使用 PriorityQueue 我有一个非常大的数据集 超过 500 万件商品
  • 为什么我的 Java 中的 PriorityBlockingQueue 无法正确排序?

    由于某种原因 当我添加到优先级队列时 它不会完全按字母顺序对我的字符串进行排序 我不明白为什么 这是添加到 PriorityBlockingQueue 的代码 String toAdd String format s s directory
  • 用于在 Python 中构建 PriorityQueue 的自定义比较器

    我试图在Python中使用 PriorityQueue 构建一个优先级队列 但我希望它在将元素传递给函数后使用函数的返回值 而不是考虑进行优先级比较的元素 类似于sorted mtlist key myfun 有没有办法实现这一点 不要将元
  • 在android中安排多个异步任务

    我想安排或排队在后台执行多个 AsyncTask 我有一个在服务中运行的用于 HTTP post 请求的 AsyncTask 同时我在 AsyncTask 的 UI 线程中又发出了一个 HTTP 请求 UI 线程执行时间过长 因为已经有一个
  • STLpriority_queue的效率

    我有一个应用程序 C 我认为 STL 可以很好地服务它priority queue 文档 http www sgi com tech stl priority queue html says Priority queue 是一个容器适配器
  • 如何在优先级队列中使用pair,然后使用键作为优先级返回值

    所以我想使用最小的键作为优先级 然后返回相应键的 VALUE import javafx util Pair import java util PriorityQueue public class Test public static vo
  • C++自由实现“有界优先级队列”

    我正在寻找一个免费软件实现有界优先级队列C 中的抽象 基本上 我需要一个数据结构 其行为就像std priority queue但始终保持着 最好的 n最多元素 Example std vector
  • 具有两个优先级值的优先级队列

    众所周知 插入优先级队列的元素具有确定其优先级的值 例如 如果我有五个元素A B C D E具有优先级 我们称之为优先级值priorityI A 10 B 5 C 1 D 3 E 2 但是我如何编写一个可以定义两个优先级值的优先级队列 我的
  • 创建 python 优先级队列

    我想在 python 中构建一个优先级队列 其中队列包含不同的字典及其优先级编号 因此 当调用 get函数 时 优先级最高 编号最低 的字典将从队列中拉出 而当调用 add函数 时 新字典将被添加到队列中并根据其排序优先号码 请大家帮忙 提
  • 堆被视为抽象数据类型吗?

    我正在学习数据结构课程 并对什么被认为是 ADT 抽象数据类型 和什么不是 如果它不是 ADT 那么它一定是实现 感到有点困惑 具体来说 我说的是堆 我在维基百科上读到 堆是一种专门的基于树的数据结构 这是否意味着它是一个ADT 如果是这样
  • 实现Java优先级队列

    public class PriorityQueue
  • 近似保序霍夫曼码

    我正在做算法和数据结构课程的作业 我无法理解给出的说明 我会尽力解释这个问题 我给出的输入是一个正整数n其次是n正整数 表示有序字符集中符号的频率 或权重 第一个目标是构造一棵树 为有序字符集中的每个字符提供近似的保序霍夫曼代码 我们要通过
  • .Net中的优先级队列[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找优先级队列或堆数据结构的 NET 实现 优先级队列是比简单排序提供更多灵活性的数据结构 因为
  • 如何从priority_queue中删除不在顶部的元素?

    在我的程序中 我需要从优先级队列中删除不在顶部的元素 可以吗 如果没有 请建议一种除了创建自己的堆之外的方法 标准priority queue
  • 如何将 PriorityQueue 恢复到方法调用之前的初始状态?

    我正在做一道练习题 这个问题基本上是你传入一个 PriorityQueue 和某个 k 并且你要返回该 PriorityQueue 中的第 k 个最小值 您还可以将 PriorityQueue 恢复到其初始状态 并可以使用一个堆栈或队列作为
  • java有索引的最小优先级队列吗?

    我需要它来实现 Dijkstra 算法 并且我确实有自己的实现 但是使用 java 自己的类记录我的代码会更容易 不 Java标准库没有这样的数据结构 我想大多数人都用这个 http algs4 cs princeton edu 24pq
  • 如何自定义 PriorityQueue.stream().foreach 按优先级顺序迭代

    我有一个类 里面有 PriorityQueue 字段 public class MyClass

随机推荐

  • 视觉SLAM-Eigen学习实践

    1 Eigen库介绍 Eigen 是一个 C 43 43 开源线性代数库 它提供了快速的有关矩阵的线性代数运算 xff0c 还包括解方程等功能 可以通过sudo apt install libeigen3 dev命令进行安装 xff0c 也
  • 苹果手机存储空间(或称为内存)满了导致黑屏转圈白苹果

    没刷机 xff0c 啥也没干 xff0c 发现把SIM卡拔了再开机就好了 xff0c 然后赶紧去卸载一些软件腾出空间
  • Arrays的toString方法和deepToString方法比较

    因为打印二维数组时用错了方法 xff0c 一般是用Arrays deppToString或者遍历使用toString xff0c 我直接用Arrays toString去打印了二维数组 xff0c 没有打印出正常二维数组的内容 xff0c
  • JavaSE-类与对象+单例模式

    1 类与对象的引用 概念 xff1a 如果一个变量的类型是类类型 xff0c 而非基本类型 xff0c 那么该变量又叫做引用 new testClass 该操作表示创建了一个testClass对象 xff0c 但没有办法访问这个对象 tes
  • JavaSE-类与对象-ATM自主操作系统实现

    学完类与对象的练习小作业 xff0c 主要有三个类 xff1a 银行卡类包含银行卡的相关信息如卡号 xff0c 密码 xff0c 姓名 xff0c 余额 xff1b 银行类中主要定义了一个银行卡数组 xff0c 用来存储当前用户的银行卡信息
  • JavaSE-基于回溯法用类+栈实现迷宫问题

    目录 1 问题描述 2 自定义类栈 3 结点类 4 操作类 5 函数讲解 6 测试类及结果 1 问题描述 输入迷宫大小 xff0c 以及路径 xff0c 0表示可走路径 xff0c 1表示死路 xff0c 从输入矩阵的左上角起点到右下角终口
  • Leetcode-234,844,19

    234 回文链表 请判断一个链表是否为回文链表 示例 1 输入 1 gt 2 输出 false 示例 2 输入 1 gt 2 gt 2 gt 1 输出 true 思路 xff1a 本想将链表逆置然后进行比较 xff0c 后来想了想用栈去做更
  • JavaSE-回溯+自定义类栈实现Puzzle问题

    Puzzle问题描述 如图有一个一维数组 xff0c 上面的数字表示可以移动的步数 xff0c 每个结点都有左右两个方向可以移动 xff0c 例如第一个结点4 xff0c 它只能往右移动4格到3的位置 xff0c 而3左右都可以移动 xff
  • JavaSE-泛型类、接口、方法、擦除机制

    1 泛型定义 泛型是JavaSE 1 5的新特性 xff0c 本质是参数化类型 xff0c 也就是所操作的数据类型被指定为一个参数 xff0c 将类型由原来的具体的参数类型化 xff0c 类似于方法中的变量参数 xff0c 此时类型也定义成
  • JavaSE-十分钟写个五子棋

    1 设计说明 1 1 简介 其实很久之前就写过五子棋 xff0c 当时拿AWT写的界面 xff0c 后面通过socket通信实现了联机对战操作 xff0c 当时写五子棋写的可费劲了 xff0c 现在又要写一次五子棋 xff0c 不过是简单版
  • JavaSE-类加载过程及反射

    目录 一 类加载过程 1 装载阶段 1 1执行过程 1 2 类加载器 1 3 双亲委派模型 1 4 类加载时机 2 链接阶段 2 1验证阶段 2 2准备阶段 2 3解析阶段 3 初始化阶段 二 反射 1 定义 2 用途 3 步骤 4 代码实
  • STM32F407-基于AD7606进行多路数据采集

    1 原理图 2 管脚定义 2 1 OS2 OS1 OS0 查阅数据手册 这三个管脚组合控制过采样模式 000 表示无过采样 xff0c 最大 200Ksps 采样速率 001 表示 2 倍过采样 xff0c 也就是硬件内部采集 2 个样本求
  • caffeine 与 reactor mono 一起使用产生的缓存错误问题

    现象 与reactor mono一起使用 xff0c 发现get key时 xff0c 返回的一直都是抛出的错误信息 xff0c 没有预期中的如果cache loader 返回null 或 错误时 xff0c caffeine自动剔除key
  • EBYTE E103-W02 WIFI模块配置总结(TCP+UDP+HTTP+云透传)

    目录 1 硬件配置 1 1 原理图 1 2 管脚配置 2 AT指令集 3 AP模式配置 3 1AP介绍 3 2 AP配置TCP通信 3 3 AP配置UDP通信 4 STA模式配置 4 1STA介绍 4 2配置过程 4 3网页配置 5 基于亿
  • JavaSE-自定义单链表

    目录 1 自定义链表实现 2 基础操作 2 1 链表打印操作 2 2 链表逆序打印 2 3 链表逆置 3 进阶操作 3 1查找倒数第K个结点 3 2 不允许遍历链表 xff0c 在pos结点之前插入 3 3两个链表相交 xff0c 输出相交
  • SRGAN实现超分辨率图像重建之模型复现

    1 论文介绍 1 1简介 论文名称 Photo Realistic Single Image Super Resolution Using a Generative Adversarial Ledig C Theis L Huszar F
  • JavaSE-自定义队列+两栈实现队列+两队列实现栈

    1 顺序队列实现 与栈一样 xff0c 队列也是一种操作受限制的线性表 xff0c 但与栈不同的是 xff0c 栈是后进先出 xff0c 队列的特点是先进先出 实现与栈类似 xff0c 队列有一个队头指针和一个队尾指针 xff0c 入队的时
  • JavaSE-八大经典排序算法及优化算法思路与实现

    目录 1 冒泡排序 1 1算法思想 1 2 算法实现 1 3 算法优化 1 4 算法分析 2 简单选择排序 2 1 算法思想 2 2 算法实现 2 3 算法优化 2 4 算法分析 3 直接插入排序 3 1 算法思想 3 2 算法实现 3 3
  • 快速超分辨率重建卷积网络-FSRCNN

    1 网路结构图 2 改进点 SRCNN缺点 xff1a SRCNN将LR送入网络前进行了双三次插值上采样 xff0c 产生于真实图像大小一致的图像 xff0c 会增加计算复杂度 xff0c 因为插值后图像更大 xff0c 输入网络后各个卷积
  • PriorityQueue(优先级队列)的解读与底层实现

    目录 1 什么是优先级队列 xff1f 2 优先级队列的特性 3 如何使用优先级队列 4 JDK源码分析 4 1类的继承关系 4 2类的属性 4 3常用的方法 5 自定义优先级队列实现 5 1 优先级队列类定义 5 2 add 方法 5 3