Java数据结构之优先级队列(堆)

2023-11-06

一、优先级队列

(一)概念

优先级队列:能够添加新的对象并且能够返回一组对象中的最高优先级对象的数据结构

二、优先级队列的模拟实现

JDK1.8中的PriorityQueue底层使用了堆的数据结构,而堆实际就是在完全二叉树的基础上进行了一些元素的调整

(一)堆的概念

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

  • 堆中某个节点的值总是不大于或不小于其父节点的值;
  • 堆总是一棵完全二叉树(堆就是在二叉树那一节所讲的顺序存储结构

大根堆小根堆的逻辑存储和存储结构

(二)堆的存储结构

从堆的概念可知,堆是一棵完全二叉树,因此可以通过层序遍历的规则采用顺序的方式来高效存储
完全二叉树和普通树的逻辑结构区别和顺序存储区别

注意:对于非完全二叉树,则不适合使用顺序方式进行存储,因为为了能够还原二叉树,空间中必须要存储空节点,就会导致空间利用率比较低。
将元素存储到数组中后,可以根据二叉树章节的性质5对树进行还原。假设 i 为节点在数组中的下标,则有:

  • 如果 i 为0,则 i 表示的节点为根节点,否则 i 节点的双亲节点为(i - 1) / 2
  • 如果2 * i + 1小于节点个数,则节点的左孩子下标为2 * i + 1,否则没有左孩子
  • 如果2 * i + 2小于节点个数,则节点 i 的右孩子下标为 2 * i + 2,否则没有右孩子

(三)堆的创建

1.堆的创建和向下调整

举例:将集合{15,2,28,7,4,45,22,6}中的数据,如何将其创建成堆呢?
上面集合的图

向下过程(以创建大根堆为例)
由于对于大根堆来说,每个节点作为头节点时都是大根堆,那么我们选择从下往上逐个比较排序
那么为什么说是向下调整,因为我们在对根节点和自己的孩子节点进行比较时,假如将孩子节点和根节点交换了,那新的孩子节点作为自己的根节点时,是否还是大根堆呢,我们不得而知,因此我们还要继续向下调整,(重要:虽然我们是从最下面开始,但是并不需要从最后一个开始,只需要从最后一个根节点开始就行)如图:
大根堆调整过程

2.堆的创建和向上调整

在第一种方法中,我们用的是向下调整,但是这么做有个前提,即数据已经全部存放在数组中了,后续不再需要插入数据,在之后,我们还会遇到一种常见的建堆方式,即数据还没有保存到数组中,需要我们一个一个手动插入,那么我们就需要在插入的过程中维护堆,保证插入数据后仍然是一个堆,而关于这种堆的创建方式,我们在介绍完堆的插入之后再详细说明

代码示例:

public void createHeap(int[] array) {
    //这里只是添加元素,不理解没关系
    for (int i = 0; i < array.length; i++) {
        if(usedSize == this.elem.length) {
            elem = Arrays.copyOf(elem,elem.length + elem.length>>>1);
        }
        this.elem[i] = array[i];
        usedSize++;
    }
    //这段代码才调用了向下调整方法
    for (int i = (usedSize - 1 - 1) / 2; i >= 0; i--) {
        shiftDown(this.elem,i);
    }
}

//重点:向下调整算法
public void shiftDown(int[] array,int parent) {
    while(parent * 2 + 1 < usedSize) {
        int child = parent * 2 + 1;
        if (child + 1 < usedSize && array[child] < array[child + 1]) {
            child += 1;
        }
        if (array[parent] < array[child]) {
            int tmp = array[child];
            array[child] = array[parent];
            array[parent] = tmp;
        }else {
            break;
        }
        parent = child;
    }
}

注意:在调整以parent为根的二叉树时,必须要满足parent的左子树和右子树已经是堆了才可以向下调整

  • 向下调整时间复杂度分析:
    最坏的情况就是从根节点一路替换到叶子节点,那么比较的次数就是完全二叉树的高度,即时间复杂度为O(logN)
  • 向下调整建堆的时间复杂度为O(N) ,具体推导过程如下:
    通过向下调整建立的大根堆

(四)堆的插入和删除

1.堆的插入

堆的插入需要两个步骤:

  • 将需要插入的元素放到最后
  • 利用向上调整将堆恢复为大根堆(小根堆)

向上调整

代码示例:

private void shiftUp(int child) {
    int parent = (child - 1) / 2;
    while(parent >= 0) {
        if(this.elem[parent] < this.elem[child]) {
            int tmp = elem[child];
            elem[child] = elem[parent];
            elem[parent] = tmp;
            child = parent;
            parent = (child - 1) / 2;
        }else {
            break;
        }
    }
}

堆的创建和向上调整(续)

单纯的插入操作我们已经知道了,而这种堆的创建方式不过就是不断的插入过程而已

在不断的插入中,假如数据量极大,就会有一半的数据都会集中在底层,最坏情况下每次向上调整的时间复杂度为O(logN),有N/2的数据时间复杂度基本都是如此,那么整个创建过程的时间复杂度就是O(N * logN)

2.堆的删除

注意:堆的删除一定删除的是堆顶元素。删除过程:

  1. 将堆顶元素和堆中最后一个元素交换
  2. 将堆中有效个数减少一个,即usedSize–;
  3. 对堆顶元素进行向下调整
    堆的删除

代码示例:

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

private void shiftDown(int root,int len) {
    int child = root * 2 + 1;
    while(child < len) {
        if (child + 1 < len && elem[child] < elem[child + 1]) {
            child++;
        }
        if (elem[root] < elem[child]) {
            int tmp = elem[child];
            elem[child] = elem[root];
            elem[root] = tmp;
            root = child;
            child = root * 2 + 1;
        } else {
            break;
        }
    }
}

(五)用堆模拟实现优先级队列

代码示例:

public class PriorityQueue {
    public int[] elem;
    public int usedSize;
    private static final int DEFAULT_SIZE = 10;
 
    public PriorityQueue(int k, Comparator<Integer> comparator) {
        this.elem = new int[DEFAULT_SIZE];
    }
 
    /**
     * 建堆的时间复杂度:O(N)
     *
     * @param array
     */
    public void createHeap(int[] array) {
        for (int i = 0; i < array.length; i++) {
            if(isFull()) {
                elem = Arrays.copyOf(elem,elem.length + elem.length>>>1);
            }
            this.elem[i] = array[i];
            usedSize++;
        }
        //调整每个根节点
        for (int i = (usedSize - 1 - 1) / 2; i >= 0; i--) {
            shiftDown(i,usedSize);
        }
    }
 
    /**
     *
     * @param root 是每棵子树的根节点的下标
     * @param len  是每棵子树调整结束的结束条件
     * 向下调整的时间复杂度:O(logn)
     */
    private void shiftDown(int root,int len) {
        int child = root * 2 + 1;
        while(child < len) {
            if (child + 1 < len && elem[child] < elem[child + 1]) {
                child++;
            }
            if (elem[root] < elem[child]) {
                int tmp = elem[child];
                elem[child] = elem[root];
                elem[root] = tmp;
                root = child;
                child = root * 2 + 1;
            } else {
                break;
            }
        }
    }
 
 
    /**
     * 入队:仍然要保持是大根堆
     * @param val
     */
    public void push(int val) {
        if(isFull()) {
            elem = Arrays.copyOf(elem,elem.length + elem.length>>>1);
        }
        this.elem[usedSize] = val;
        usedSize++;
        shiftUp(usedSize - 1);
    }
 
    private void shiftUp(int child) {
        int parent = (child - 1) / 2;
        while(parent >= 0) {
            if(this.elem[parent] < this.elem[child]) {
                int tmp = elem[child];
                elem[child] = elem[parent];
                elem[parent] = tmp;
                child = parent;
                parent = (child - 1) / 2;
            }else {
                break;
            }
        }
    }
 
    public boolean isFull() {
        return usedSize == this.elem.length;
    }
 
    /**
     * 出队【删除】:每次删除的都是优先级高的元素
     * 仍然要保持是大根堆
     */
    public int pollHeap() {
        if(isEmpty()) {
            throw(new NullPointerException());
        }
        int tmp = this.elem[usedSize];
        this.elem[usedSize] = this.elem[0];
        this.elem[0] = tmp;
        usedSize--;
        shiftDown(0,usedSize);
        return this.elem[usedSize];
    }
 
    public boolean isEmpty() {
        return this.usedSize == 0;
    }
 
    /**
     * 获取堆顶元素
     * @return
     */
    public int peekHeap() {
        if(isEmpty()) {
            throw(new NullPointerException());
        }
        return this.elem[0];
    }
}

三、常用接口介绍

(一)PriorityQueue的特性

Java集合框架中提供了PriorityQueuePriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的,本文主要介绍PriorityQueue

集合关系

关于PriorityQueue的使用要注意:

  1. 使用时必须导入Priority所在的包,即:
import java.util.PriorityQueue;
  1. PriorityQueue中放置的元素必须能够比较大小,不能插入无法比较大小的对象,否则会抛出ClassCastException异常
  2. 不能插入null对象,否则会抛出ClassCastException异常
  3. 没有容量限制,可以插入任意多个元素,其内部可以自动扩容
  4. 插入和删除元素的时间复杂度为O(logN)
  5. PriorityQueue底层使用了堆数据结构
  6. PriorityQueue默认情况下是小堆—即每次获取到的元素都是最小的元素

(二)PriorityQueue常用接口介绍

1.优先级队列的构造

此处只是列出了PriorityQueue中常见的几种构造方式

构造器 功能介绍
PriorityQueue() 创建一个空的优先级队列,默认容量是11
PriorityQueue(int initialCapacity) 创建一个初始容量为initialCapacity的优先级队列,注意:initialCapacity不能小于1,否则会抛IllegalArgumentException异常
PriorityQueue(Collection<? extends E> c) 用一个集合来创建优先级队列

注意:默认情况下,PriorityQueue队列是小堆,如果想设为大堆需要用户提供比较器
代码示例:


2. 插入/删除/获取优先级最高的元素

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

注意:以下是JDK1.8中,PriorityQueue的扩容方式:


优先级队列的扩容说明:

  1. 如果容量小于64时,是按照oldCapacity的二倍方式扩容的
  2. 如果容量大于等于64,是按照oldCapacity的1.5倍方式扩容的
  3. 如果容量超过MAX_ARRAY_SIZE,按照MAX_ARRAY_SIZE来进行扩容

四、堆的应用

(一)PriorityQueue的实现

用堆作为底层结构封装优先级队列

(二)堆排序

堆排序即利用堆的思想来进行排序,总共分为两个步骤:

  1. 建堆
  • 升序:建大堆
  • 降序:建小堆
  1. 利用堆删除思想进行排序
    建堆和堆删除中都用到了向下调整,因此掌握了向下调整,就可以完成堆排序

代码示例:

//交换方法
private static void swap(int[] array,int i,int j) {
    int tmp = array[i];
    array[i] = array[j];
    array[j] = tmp;
}

//向下调整
private static void shiftDown(int[] array, int root, int len) {
    int child = root * 2 + 1;
    while(child < len) {
        if(child + 1 < len && array[child] < array[child + 1]) {
            child++;
        }
        if(array[root] < array[child]) {
            swap(array,root,child);
        }else {
            break;
        }
        root = child;
        child = root * 2 + 1;
    }
}

//创建大根堆
public static void creatHeap(int[] array) {
    int len = array.length;
    for(int i = (len - 2) / 2; i >= 0; i--) {
        shiftDown(array,i,len);
    }
}
// 堆升序排序
public static void heapSort(int[] array){
    // write code  here
    creatHeap(array);
    int len = array.length;
    while(len > 1) {
        swap(array,0,len - 1);
        len--;
        shiftDown(array,0,len);
    }
}

(三)Top-k问题

TOP-K问题:即求数据集合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大
比如:专业前十名,游戏前十名等
我们利用堆可以解决这个问题,如果还要求对前K个数进行排序,那也可以在先找到这K个元素之后再进行排序,时间复杂度会大大缩减,基本思路如下:

  1. 用数据集合中前K个元素来建堆
  • 前k个最大的元素,则建小根堆
  • 前k个最小的元素,则建大根堆
  1. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素并对堆进行恢复(我理解为末位淘汰机制)
    将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或最大的元素

图示:

实现代码:

/**
 * 著名的TopK问题:得到前 k 个小的值,顺序无所谓
 * @param arr 传入的数组
 * @param k 具体前 K 个小的元素
 * @return 前 k 个小的值的数组
 */
public int[] smallestK(int[] arr, int k) {
    //当arr == null 或者 K是0的时候,需要直接返回
    if(arr == null || k == 0) {
        return new int[0];
    }
    //创建一个大根堆
    PriorityQueue<Integer> pq = new PriorityQueue<>(k,new Comparator<Integer>(){
        @Override
        public int compare(Integer o1, Integer o2) {
            return o2.compareTo(o1);
        }
    });
    for(int i = 0; i < k; i++) {
        pq.offer(arr[i]);
    }
    for(int i = k; i < arr.length; i++) {
        int tmp = pq.peek();
        if(arr[i] < tmp) {
            pq.poll();
            pq.offer(arr[i]);
        }
    }
    int[] nums = new int[k];
    for(int i = 0; i < k; i++) {
        nums[i] = pq.poll();
    }
    return nums;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java数据结构之优先级队列(堆) 的相关文章

  • Hibernate注解放置问题

    我有一个我认为很简单的问题 我见过两种方式的例子 问题是 为什么我不能将注释放在字段上 让我举一个例子 Entity Table name widget public class Widget private Integer id Id G
  • 在文本文件中写入多行(java)

    下面的代码是运行命令cmd并使用命令行的输出生成一个文本文件 下面的代码在 Eclipse 的输出窗口中显示了正确的信息 但在文本文件中只打印了最后一行 谁能帮我这个 import java io public class TextFile
  • OpenCV 中的 Gabor 内核参数

    我必须在我的应用程序中使用 Gabor 过滤器 但我不知道这个 OpenCV 方法参数值 我想对虹膜进行编码 启动 Gabor 过滤器并获取特征 我想对 12 组 Gabor 参数值执行此操作 然后我想计算 Hamming Dystans
  • Java AES 128 加密方式与 openssl 不同

    我们遇到了一种奇怪的情况 即我们在 Java 中使用的加密方法会向 openssl 生成不同的输出 尽管它们在配置上看起来相同 使用相同的键和 IV 文本 敏捷的棕色狐狸跳过了懒狗 加密为 Base64 字符串 openssl A8cMRI
  • Cassandra java驱动程序协议版本和连接限制不匹配

    我使用的java驱动程序版本 2 1 4卡桑德拉版本 dsc cassandra 2 1 10cql 的输出给出以下内容 cqlsh 5 0 1 Cassandra 2 1 10 CQL spec 3 2 1 Native protocol
  • Java 文件上传速度非常慢

    我构建了一个小型服务 它从 Android 设备接收图像并将其保存到 Amazon S3 存储桶中 代码非常简单 但是速度非常慢 事情是这样的 public synchronized static Response postCommentP
  • 画透明圆,外面填充

    我有一个地图视图 我想在其上画一个圆圈以聚焦于给定区域 但我希望圆圈倒转 也就是说 圆的内部不是被填充 而是透明的 其他所有部分都被填充 请参阅这张图片了解我的意思 http i imgur com zxIMZ png 上半部分显示了我可以
  • hibernate锁等待超时超时;

    我正在使用 Hibernate 尝试模拟对数据库中同一行的 2 个并发更新 编辑 我将 em1 getTransaction commit 移至 em1 flush 之后我没有收到任何 StaleObjectException 两个事务已成
  • 很好地处理数据库约束错误

    再一次 它应该很简单 我的任务是在我们的应用程序的域对象中放置一个具有唯一约束的特定字段 这本身并不是一个很大的挑战 我刚刚做了以下事情 public class Location more fields Column unique tru
  • 编辑文件名在 JComboBox 中的显示方式,同时保持对文件的访问

    我对 Java 很陌生 对堆栈溢出也很陌生 我正在尝试利用 JMF API 创建一个用 Java 编码的简单媒体播放器 到目前为止 我已经能够设置一个简单的队列 播放列表来使用JComboBox called playListHolder
  • 有没有一种快速方法可以从 Jar/war 中删除文件,而无需提取 jar 并重新创建它?

    所以我需要从 jar war 文件中删除一个文件 我希望有类似 jar d myjar jar file I donot need txt 的内容 但现在我能看到从 Linux 命令行执行此操作的唯一方法 不使用 WinRAR Winzip
  • 欧洲中部时间 14 日 3 月 30 日星期五 00:00:00 至 日/月/年

    我尝试解析格式日期Fri Mar 30 00 00 00 CET 14至 日 月 年 这是我的代码 SimpleDateFormat formatter new SimpleDateFormat dd MM yyyy System out
  • 如何知道抛出了哪个异常

    我正在对我们的代码库进行审查 有很多这样的陈述 try doSomething catch Exception e 但我想要一种方法来知道 doSomething 抛出了哪个异常 在 doSomething 的实现中没有 throw 语句
  • Struts 2 + Sitemesh 3 集成 - FreemarkerDecoratorServlet 中的 NPE

    我将 Struts 2 版本 2 3 14 3 与 Sitemesh 3 版本 3 0 alpha 2 一起使用 并且在某些情况下遇到 NullPointerException 首先 这是我的 web xml 中的 struts2 site
  • 在 Spring 中重构这个的最佳方法?

    private final ExecutorService executorParsers Executors newFixedThreadPool 10 public void parse List
  • 如何在JSTL中调​​用java方法? [复制]

    这个问题在这里已经有答案了 这可能是重复的问题 我只想调用不是 getter 或 setter 方法的方法例如 xyz 类的 makeCall someObj stringvalue Java类 Class XYZ public Strin
  • spring中如何使用jackson代替JdkSerializationRedisSerializer

    我在我的一个 Java 应用程序中使用 Redis 并且正在序列化要存储在 Redis 中的对象列表 但是 我注意到使用 RedisTemplate 会使用 JdkSerializationRedisSerializer 相反 我想使用 J
  • javafx android 中的文本字段和组合框问题

    我在简单的 javafx android 应用程序中遇到问题 问题是我使用 gradle javafxmobile plugin 在 netbeans ide 中构建了非常简单的应用程序 其中包含一些文本字段和组合框 我在 android
  • ServletContainer 类未找到异常

    我无法再编译我的球衣项目 并且出现以下异常 GRAVE Servlet Project API threw load exception java lang ClassNotFoundException com sun jersey spi
  • GUI Java 程序 - 绘图程序

    我一直试图找出我的代码有什么问题 这个想法是创建一个小的 Paint 程序并具有红色 绿色 蓝色和透明按钮 我拥有我能想到的让它工作的一切 但无法弄清楚代码有什么问题 该程序打开 然后立即关闭 import java awt import

随机推荐

  • SSM框架之SpringMVC

    文章目录 SpringMVC MVC设计模式 springmvc框架 入门程序 配置前端控制器和处理器适配器 开发Handler 映射器和适配器 非注解的处理器映射器 非注解的处理器适配器 注解的处理器映射器和适配器 重点 源码分析 spr
  • 长短时记忆网络(LSTM)负荷预测项目(matlab)

    目录 1 LSTM介绍 2 数据集准备及预处理 3 LSTM模型搭建与训练 4 预测模型测试 1 LSTM介绍 长短期记忆网络 LSTM long short term memory 是 RNN 的一种变体 其核心概念在于细胞状态以及 门
  • 微信小程序宠物用品服务商城SSM-JAVA【数据库设计、论文、源码、开题报告】

    功能介绍 操作角色为管理员和用户 商家 管理员的功能为用户管理 商家管理 宠物分类管理 宠物信息管理 商品分类管理 宠物用品管理 项目类型管理 服务项目管理 宠物日志管理 订单管理等 用户的功能为购买宠物 商品 预约服务发表日志管理订单等
  • 美团西安美食部分爬虫(修改版)(python)

    美团美食 coding UTF 8 import requests import time from bs4 import BeautifulSoup import json import csv import random with op
  • 区块链100篇之fabric的网络搭建(一)

    好久没写博客了 今天开始写关于fabric相关的博客 包括网络的搭建 链码的编写以及sdk的封装 搭建网络 网络的搭建想分为三篇来写 第一篇写网络的搭建 这里是官方fabric samples的简化版 第二篇是关于yaml文件的编写 第三篇
  • 【数据科学】肯德尔等级相关系数( Kendall's tau coefficient )

    在统计学中 Kendall等级相关系数 通常称为Kendall的tau系数 在希腊字母 之后 是用于测量两个测量量之间的序数关联的统计量 甲tau蛋白测试是一种非参数假设检验用于基于所述tau蛋白系数统计依赖性 它是衡量等级相关 数据的排序
  • java 版本企业招标投标管理系统源码+功能描述+tbms+及时准确+全程电子化

    功能描述 1 门户管理 所有用户可在门户页面查看所有的公告信息及相关的通知信息 主要板块包含 招标公告 非招标公告 系统通知 政策法规 2 立项管理 企业用户可对需要采购的项目进行立项申请 并提交审批 查看所有的立项信息 主要功能包含 招标
  • 第五章 Maven结合Junit实现单元测试

    maven的重要职责之一就是自动运行单元测试 它通过maven surefire plugin与主流的单元测试框架junit和testng集成 并且能够自动生成丰富的结果报表 maven并不是一个单元测试框架 他只是在构建执行打特定的生命周
  • RobotFramework介绍

    Robot Framework 1 入门介绍 小菠萝测试笔记 博客园 cnblogs com
  • C++——初始化列表

    初始化列表 在构造函数执行时 先执行初始化列表 实现变量的初始化 然后再执行函数内部的语句 构造函数体赋值 在创建对象时 编译器通过调用构造函数 给对象中各个成员变量一个合适的初始值 class Date public Date int y
  • css中nth-child的属性

    参数为整数 nth child 1 它表示要选择父元素中索引为该数值的子元素 此时的索引值从1开始 参数是奇数偶数 nth child odd odd表示选择奇数项的子元素 nth child even even表示选择偶数项的子元素 参数
  • Tkinter 组件详解(一):Label

    Tkinter 组件详解之Label Label 标签 组件用于在屏幕上显示文本或图像 Label 组件仅能显示单一字体的文本 但文本可以跨越多行 另外 还可以为其中的个别字符加上下划线 例如用于表示键盘快捷键 何时使用 Label 组件
  • Linux驱动之input输入子系统

    目录 前言 介绍 input dev结构体 输入子系统的使用流程 实例测试 前言 输入子系统用于实现Linux系统输入设备 鼠标 键盘 触摸屏 游戏杆 驱动的一种框架 Linux内核将其中的固定部分放入内核 驱动开发时只需要实现其中的不固定
  • Web自动化测试从基础到项目实战之一启动不同的浏览器及配置

    在web自动化中目前selenium作为底层的自动化测试是目前运用最广的 但是各个公司都会在这个基础之上进行修改 首先当我们测试环境有了之后我们需要做得就是去配置我们的driver 这里的driver你可以理解为就是我们脚本和浏览器之间的桥
  • inuxCentos7.5安装jdk1.8(勿继续踩坑)

    LinuxCentos7 5安装jdk1 8 场景 错误出现 下面到了安装步骤 场景 首先我是一名后端 其实这种工作并不应该由我来干 先甩一下锅哈哈 由于我们公司没有真正的运维 所以什么事都需要我们后端来亲力亲为 一次偶然的机遇就把我派到了
  • Vue 代码检测(ESLint)

    每个人编码的习惯不一样 或美观或不美观 或者在编码的过程中会有些疏漏未曾发现 为提高代码美观度 提高代码审阅效率 使得多人协作时代码风格统一 规定一套编码规则并在编写的过程中遵守该规则变得很有必要 在一些比较正式的大公司 公司也会有一套自己
  • SSR是什么?Vue中怎么实现?

    一 是什么 Server Side Rendering 称其为SSR 意为服务端渲染 指由服务侧完成页面的 HTML 结构拼接的页面处理技术 发送到浏览器 然后为其绑定状态与事件 成为完全可交互页面的过程 先来看看Web3个阶段的发展史 传
  • SpringBoot--将微服务注册到Eureka Server上

    这节课我们一起来学习一下如何将微服务注册到Eureka Server上 关于如何操作Eureka 我们可以参考spring cloud的官方文档 我们先访问spring cloud的官网主页 如下图所示 目前官网Spring Cloud的最
  • pycharm专业版安装方法

    1 去官网下载安装包 有专业版 有社区版 专业版需要破解 社区版不要破解 2 打开pycharm应用程序安装64 bit 需要等待几秒 3 记住安装包解压位置 打开jetbrains 找到bin文件夹 D Program Files Jet
  • Java数据结构之优先级队列(堆)

    文章目录 一 优先级队列 一 概念 二 优先级队列的模拟实现 一 堆的概念 二 堆的存储结构 三 堆的创建 1 堆的创建和向下调整 2 堆的创建和向上调整 四 堆的插入和删除 1 堆的插入 堆的创建和向上调整 续 2 堆的删除 五 用堆模拟