【数据结构Java版】二叉树堆与优先级队列PriorityQueue

news2024/9/24 11:28:58

 目录

一、优先级队列

(1)优先级队列的概念

(2)优先级队列的模拟实现

二、堆

(1)堆的概念

(2)堆的存储方式

(3)堆的创建

1.堆的向下调整

2.堆的创建

3.建堆的时间复杂度

(4)堆的操作

1.堆的插入

2.堆的删除

(5)堆的应用

1.优先级队列(PriorityQueue)的实现

2.Top-k问题

三、PriorityQueue接口

(1)PriorityQueue的特性

(2)PriorityQueue常用接口介绍

1. 优先级队列的构造

2. 优先级队列常用功能

3.优先级队列扩容方式

四、相关oj练习题


一、优先级队列

(1)优先级队列的概念

队列是一种先进先出(FIFO)的数据结构,但有些情况下,操作的数据可能带有优先级,一般出队
列时,可能需要优先级高的元素先出队列,该中场景下,使用队列显然不合适,比如:在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话;初中那会班主任排座位时可能会让成绩好的同学先挑座位。
在这种情况下,数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)。

(2)优先级队列的模拟实现

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

二、堆

(1)堆的概念

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

堆中某个节点的值总是不大于或不小于其父节点的值。
堆逻辑上是一棵完全二叉树。采用顺序结构进行组织,物理存储上表现为一个数组。(不需要按照链式结构进行组织,所以没有结点概念)

(2)堆的存储方式

堆是一棵完全二叉树,因此可以层序的规则采用顺序的方式来高效存储。

注意:对于非完全二叉树,则不适合使用顺序方式进行存储,因为为了能够还原二叉树,空间中必须要存储空节点,就会导致空间利用率比较低。

将元素存储到数组中后,可以根据二叉树的性质对树进行还原。

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

假设有一个顺序结构维护的完全二叉树:

long[] array={...}  int size=...;

 问题:

1.[i]下标是否一个合法下标:

0<=i<size

2.[i]是一个合法的下标,问孩子下标是否是一个合法下标:

左孩子:0<=2*i+1<size  右孩子:0<=2*i+2<size

3.已知[i]下标所在元素,判断是否有右孩子:

0<=2*i+2<size

4.已知[i]下标所在元素,判断是否是叶子:

因为是完全二叉树,所以只需要判断该结点是否有左孩子,没有左孩子即代表也没有右孩子,判断方式就是大于数组长度。

2*i+2>=size

(3)堆的创建

1.堆的向下调整

对于集合{ 27,15,19,18,28,34,65,49,25,37 }中的数据。根节点的左右子树已经完全满足堆的性质,因此只需将根节点向下调整好即可。
向下过程(以小堆为例):

1. 让parent标记需要调整的节点,child标记parent的左孩子(注意:parent如果有孩子一定先是有左孩子)
2. 如果parent的左孩子存在,即:child < size, 进行以下操作,直到parent的左孩子不存在
parent右孩子是否存在,存在找到左右孩子中最小的孩子,让child进行标
将parent与较小的孩子child比较,如果:
parent小于较小的孩子child,调整结束
否则:交换parent与较小的孩子child,交换完成之后,parent中大的元素向下移动,可能导致子
树不满足对的性质,因此需要继续向下调整,即parent = child;child = parent*2+1; 然后继续2。

 注意前提:

待调整的元素不是叶子即代表有孩子。除了待调整的元素,其他部分均已经满足大堆或者小堆。

在调整以parent为根的二叉树时,必须要满足parent的左子树和右子树已经是堆了才可以向下调整。
时间复杂度分析:
最坏的情况即图示的情况,从根一路比较到叶子,比较的次数为完全二叉树的高度,即时间复杂度为O(log_{2}n)

向下调整的代码:

(这里就把数组长度array.length当做堆的大小size,实际上数组长度可以更大,只要堆的大小size<=数组长度就可以了,数组不一定都要存满。)

调整成小堆(非递归版):

 public static void adjustDownSmallHeap (int array[],int index) {
        int parent = index;//需要调整的元素下标
        int child = 2 * parent + 1;//假设最小孩子是左孩子
        //判断右孩子是否存在,找出左右孩子中最小的一个

        while (child < array.length) {//孩子结点存在
            if (child + 1 < array.length && array[child] > array[child + 1]) {
                child += 1;//如果右孩子存在,并且更小,就把右孩子定为最小孩子
            }
            if (array[parent] <= array[child]) {//当待调整元素小于等于最小孩子,则代表满足小堆性质
                break;//跳出循环
            }
            //向下调整,就是和最小孩子交换
            int tmp = array[parent];
            array[parent] = array[child];
            array[child] = tmp;

            // parent中大的元素往下移动,可能会造成子树不满足堆的性质,因此需要继续向下调整
            parent = child;//改变需要调整的元素下标和最小孩子的下标
            child = 2 * parent + 1;
        }
    }

调整成小堆(递归版): 

  public static void adjustDownSmallHeap递归 (int array[],int index) {
        int parent = index;//需要调整的元素下标
        int child = 2 * parent + 1;//假设最小孩子是左孩子
        //判断右孩子是否存在,找出左右孩子中最小的一个
        if(child>=array.length){
            return ;
        }
        if (child + 1 < array.length && array[child] > array[child + 1]) {
            child += 1;//如果右孩子存在,并且更小,就把右孩子定为最小孩子
        }
        if (array[parent] <= array[child]) {//当待调整元素小于等于最小孩子,则代表满足小堆性质
            return;
        }
        //否则不满足堆的性质
        //向下调整,就是和最小孩子交换
        int tmp = array[parent];
        array[parent] = array[child];
        array[child] = tmp;
        
        //递归
        adjustDownSmallHeap递归(array,child);
    }

调整成大堆(非递归版):(注意除了待调整的元素,其他结点元素均要满足大堆的性质,如下图除了根结点2不满足,其他左右子树都已经是满足大堆了) 

public static void adjustDownBigHeap (int array[],int index) {
        int parent = index;//需要调整的元素下标
        int child = 2 * parent + 1;//假设最大孩子是左孩子
        //判断右孩子是否存在,找出左右孩子中最大的一个

        while (child < array.length) {//孩子结点存在
            if (child + 1 < array.length && array[child] < array[child + 1]) {
                child += 1;//如果右孩子存在,并且更大,就把右孩子定为最大孩子
            }
            if (array[parent] >= array[child]) {//当待调整元素大于等于最小孩子,则代表满足大堆性质
                break;//跳出循环
            }
            //向下调整,就是和最大孩子交换
            int tmp = array[parent];
            array[parent] = array[child];
            array[child] = tmp;

            // parent中小的元素往下移动,可能会造成子树不满足堆的性质,因此需要继续向下调整
            parent = child;//改变需要调整的元素下标和最大孩子的下标
            child = 2 * parent + 1;
        }
    }

 调整成大堆(递归版): 

public static void adjustDownBigHeap递归 (int array[],int index) {
        int parent = index;//需要调整的元素下标
        int child = 2 * parent + 1;//假设最大孩子是左孩子
        //判断右孩子是否存在,找出左右孩子中最大的一个
        if (child + 1 < array.length && array[child] < array[child + 1]) {
            child += 1;//如果右孩子存在,并且更大,就把右孩子定为最大孩子
        }
        if (array[parent] >= array[child]) {//当待调整元素大于等于最小孩子,则代表满足大堆性质
            return;//跳出循环
        }
        
        //否则不满足堆的性质
        //向下调整,就是和最大孩子交换
        int tmp = array[parent];
        array[parent] = array[child];
        array[child] = tmp;

        adjustDownBigHeap递归(array,child);
    }

2.堆的创建

对于普通的序列{ 1,5,3,8,7,6 },即根节点的左右子树不满足堆的特性。调整过程如下:

 简而言之就是先调整所有叶子结点的根结点部分,叶子结点那一层已经满足向下调整操作的性质,对该层调整使叶子结点那一层满足堆性质后,再看向上面一层,也就满足向下调整操作的性质,对该层操作满足堆的性质,依次往上。

建小堆:

   public static void createSmallHeap (int array[]){
        int parentIndex=(array.length-1-1)/2;//array.length-1是最后一个叶子结点的位置,(i-1)/2是求父亲结点的公式
        for(int i=parentIndex;i>=0;i--){
            adjustDownSmallHeap(array,i);
        }
    }

建大堆: 

    public static void createBigHeap (int array[]){
        int parentIndex=(array.length-1-1)/2;//array.length-1是最后一个叶子结点的位置,(i-1)/2是求父亲结点的公式
        for(int i=parentIndex;i>=0;i--){
            adjustDownBigHeap(array,i);
        }
    }

3.建堆的时间复杂度

堆是完全二叉树,而满二叉树也是完全二叉树,此处为了简化使用满二叉树来证明(时间复杂度本来看的就是近似值,多几个节点不影响最终结果):建堆的时间复杂度为O(N)
 

(4)堆的操作

1.堆的插入


a. 先将元素放入到底层空间中(注意:空间不够时需要扩容)
b. 将最后新插入的节点向上调整,直到满足堆的性质

2.堆的删除

堆的删除一定删除的是堆顶元素。
a. 将堆顶元素对堆中最后一个元素交换
b. 将堆中有效数据个数减少一个
c. 对堆顶元素进行向下调整

(5)堆的应用

1.优先级队列(PriorityQueue)的实现

底层结构就是依靠堆的性质,其中包括堆的删除、添加元素等等。

package heap_1101;
// 使用小堆来维护
// size >= 0
// array != null
// array + size 满足小堆的性质
// 堆的定义:要求每个位置都比它的两个孩子(如果存在的话)要小
public class MyPriorityQueue {
    // 元素类型使用 long 类型
    // 暂时不考虑扩容的情况
    private final long[] array = new long[1000];
    private int size;       // 元素的个数

    public MyPriorityQueue(){
        size=0;
    }
    // 查看优先级队列中最小值
    // O(1)
    public long peek() {
        if (size <= 0) {
            throw new RuntimeException("空的");
        }

        return array[0];    // 根的位置就是最小值
    }
    // 把 e 添加到堆中(优先级队列)
    // 同时维护好最小堆的性质
    // 最坏情况:从叶子 -> 根
    // O(log(n))
    public void offer(long e) {
       array[size]=e;
       size++;

       int child=size-1;//新加入元素的下标
       while(child!=0){// child == 0 说明是根,不需要调整了
           int parent=(child-1)/2;//新加入元素父亲结点的下标

           if(array[parent]<=array[child]){
                break;
            }
           //交换
            long tmp=array[parent];
            array[parent]=array[child];
            array[child]=tmp;
           //向上调整
            child=parent;
        }

    }
    // 删除堆顶元素
    // 同时维护好最小堆的性质
    // O(log(n))
    public long poll() {
        if (size <= 0) {
            throw new RuntimeException("空的");
        }

        long e = array[0];

        array[0] = array[size - 1];
        array[size - 1] = 0;    // 没有意义,可以不需要这一步
        size--;//调整堆的大小
        //对根结点进行向下调整
        int parent=0;    // O(log(n))
        int child=2*parent+1;
        while(child<size){
            if(child+1<size&&array[child+1]<array[child]){
                child+=1;
            }
            if(array[child]>=array[parent]){
                break;
            }
            long tmp=array[parent];
            array[parent]=array[child];
            array[child]=tmp;

            parent=child;
            child=2*parent+1;
        }

        return e;//返回删除的元素
    }
    public static void main(String[] args) {
        MyPriorityQueue q = new MyPriorityQueue();

        q.offer(3);
        q.offer(9);
        q.offer(7);
        q.offer(2);
        q.offer(6);
        q.offer(8);
        q.offer(5);
        q.offer(4);
        q.offer(3);

        System.out.println(q.poll());   // 2
        q.offer(1);
    }
}

2.Top-k问题

Top-k问题,求取前k个最大或者最小元素。适用于海量数据当中,比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。
对于Top-K问题,能想到的最简单直接的方式就是排序,但是:如果数据量非常大,排序就不太可取了(可能数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决。

基本思路:

a. 用数据集合中前K个元素来建堆
前k个最大的元素,则建小堆
前k个最小的元素,则建大堆
b. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素
将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。

实例运用,见oj相关练习题。

三、PriorityQueue接口

(1)PriorityQueue的特性

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

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

(2)PriorityQueue常用接口介绍

1. 优先级队列的构造

构造器功能介绍
PriorityQueue()创建一个空的优先级队列,默认容量是11
PriorityQueue(int
initialCapacity)
创建一个初始容量为initialCapacity的优先级队列,注意:
initialCapacity不能小于1,否则会抛IllegalArgumentException异
PriorityQueue(Collection<?
extends E> c)
用一个集合来创建优先级队列
static void TestPriorityQueue(){
    // 创建一个空的优先级队列,底层默认容量是11
    PriorityQueue<Integer> q1 = new PriorityQueue<>();
    // 创建一个空的优先级队列,底层的容量为initialCapacity
    PriorityQueue<Integer> q2 = new PriorityQueue<>(100);
    ArrayList<Integer> list = new ArrayList<>();
    list.add(4);
    list.add(3);
    list.add(2);
    list.add(1);
    // 用ArrayList对象来构造一个优先级队列的对象
    // q3中已经包含了三个元素
    PriorityQueue<Integer> q3 = new PriorityQueue<>(list);
    System.out.println(q3.size());
    System.out.println(q3.peek());
}

 PriorityQueue队列是小堆,如果需要大堆需要用户提供比较器。这里可以参考比较这篇博客。

// 用户自己定义的比较器:直接实现Comparator接口,然后重写该接口中的compare方法即可
class IntCmp implements Comparator<Integer>{
    @Override
        public int compare(Integer o1, Integer o2) {
        return o2-o1;
    }
}
public class TestPriorityQueue {
    public static void main(String[] args) {
        PriorityQueue<Integer> p = new PriorityQueue<>(new IntCmp());
        p.offer(4);
        p.offer(3);
        p.offer(2);
        p.offer(1);
        p.offer(5);
        System.out.println(p.peek());
    }
}

2. 优先级队列常用功能

函数名功能介绍
boolean
offer(E e)
插入元素e,插入成功返回true,如果e对象为空,抛出NullPointerException异常,时
间复杂度 ,注意:空间不够时候会进行扩容
E peek()获取优先级最高的元素,如果优先级队列为空,返回null
E poll()移除优先级最高的元素并返回,如果优先级队列为空,返回null
int size()获取有效元素的个数
void
clear()
清空
boolean
isEmpty()
检测优先级队列是否为空,空返回true
static void TestPriorityQueue2(){
    int[] arr = {4,1,9,2,8,0,7,3,6,5};
    // 一般在创建优先级队列对象时,如果知道元素个数,建议就直接将底层容量给好
    // 否则在插入时需要不多的扩容
    // 扩容机制:开辟更大的空间,拷贝元素,这样效率会比较低
    PriorityQueue<Integer> q = new PriorityQueue<>(arr.length);
    for (int e: arr) {
        q.offer(e);
    } 
    System.out.println(q.size()); // 打印优先级队列中有效元素个数
    System.out.println(q.peek()); // 获取优先级最高的元素
    // 从优先级队列中删除两个元素之和,再次获取优先级最高的元素
    q.poll();
    q.poll();
    System.out.println(q.size()); // 打印优先级队列中有效元素个数
    System.out.println(q.peek()); // 获取优先级最高的元素
    q.offer(0);
    System.out.println(q.peek()); // 获取优先级最高的元素
    // 将优先级队列中的有效元素删除掉,检测其是否为空
    q.clear();
    if(q.isEmpty()){
        System.out.println("优先级队列已经为空!!!");
    } else{
        System.out.println("优先级队列不为空");
    }
}

3.优先级队列扩容方式


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

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    private void grow(int minCapacity) {
        int oldCapacity = queue.length;
        // Double size if small; else grow by 50%
        int newCapacity = oldCapacity + ((oldCapacity < 64) ?
        (oldCapacity + 2) :
        (oldCapacity >> 1));
        // overflow-conscious code
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        queue = Arrays.copyOf(queue, newCapacity);
    }
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
    }

四、相关oj练习题

top-k问题:最大或者最小的前k个数据。
面试题 17.14. 最小K个数

class Solution {
    static class IntegerReverseComparator implements Comparator<Integer>{
        public int compare(Integer o1, Integer o2){
            return o2-o1;
        }
    }
    public int[] smallestK(int[] arr, int k) {
        if(k==0){
            return new int [0];
        }
        //要找到最小的k个数,所以要建立一个最大容量为k的大堆
        //java中PriorityQueue内部实现是小堆
        //重新定义5<3,3>5,3=3
        Comparator <Integer> c=new IntegerReverseComparator();
        //传入Comparator 构建优先级队列
        PriorityQueue <Integer> priorityQueue=new PriorityQueue<>(c);
        for(int i=0;i<k;i++){
            priorityQueue.offer(arr[i]);
        }
        //将剩下元素和堆顶元素比较
        for(int i=k;i<arr.length;i++){
            int e=arr[i];
            int top=priorityQueue.peek();
            //把比堆顶元素小的放入堆顶
            if(e<top){
                //把堆顶元素删除
                priorityQueue.poll();
                //放入新堆顶元素
                priorityQueue.offer(e);
            }
        }
        int []ans=new int [k];
        for(int i=0;i<k;i++){
            ans[i]=priorityQueue.poll();
        }
        return ans;
    }
}

 


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/130234.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Nginx access.log日志详解及统计分析

Nginx access.log日志详解及统计分析一、nginx的access.log二、日志流量统计统计接口地址访问量PV统计UV统计独立IP统计三、配置access.log按天生成四、nginx.conf配置一、nginx的access.log 1.日志文件一般存放在 /var/log/nginx 下&#xff0c;若是docker启动则可以使用主机…

奇舞周刊 477 期:一文弄懂 React ref 原理

记得点击文章末尾的“ 阅读原文 ”查看哟~下面先一起看下本期周刊 摘要 吧~奇舞推荐■ ■ ■一文弄懂 React ref 原理对于 Ref 理解与使用&#xff0c;一些读者可能还停留在用 ref 获取真实 DOM 元素和获取类组件实例层面上 其实 ref 除了这两项常用功能之外&#xff0c;还有很…

简单通过Sentinel监控请求

文章目录一&#xff1a;运行Sentinel服务二&#xff1a;安装Sentinel依赖2.1&#xff1a;Sentinel Pom依赖2.2&#xff1a;Sentinel YML 配置注意&#xff1a;clientIp.localhost不同sentinel版本依赖缩进层级结构可能不一样&#xff0c;可根据idea提示回车三&#xff1a;启动服…

年终给您提个醒:明年的分区表创建好了吗?

2022年某月&#xff0c;某运营商客户突然出现部分业务办理失败&#xff0c;数据无法入库的现象......经过查询&#xff0c;应用进程insert提示&#xff1a;“ORA-14400”错误。由此诊断&#xff0c;故障出现是由于上月部分表分区未提前创建&#xff0c;导致本月前端业务在导入数…

130道基础OJ编程题之: 47 ~ 57 道

130道基础OJ编程题之: 47 ~ 57 道 文章目录130道基础OJ编程题之: 47 ~ 57 道0. 昔日OJ编程题:47. BC50 计算单位阶跃函数48. BC51 三角形判断49. BC52 衡量人体胖瘦程度50. BC53 计算一元二次方程51. BC54 获得月份天数52. BC55 简单计算器53. BC56 线段图案54. BC57 正方形图案…

【生信】初探蛋白质性质和结构分析

实验目的 熟悉蛋白质序列和结构的主要分析内容在实践中逐步理解蛋白质序列和结构的主要分析算法的基本原理 实验内容 综合使用多种在线工具&#xff0c;对蛋白质的一级、二级和三级结构进行分析和预测综合使用多种在线工具&#xff0c;对蛋白质的跨膜结构、翻译后修饰、亚细…

第二十八讲:神州路由器地址转换的配置

实验拓扑图如下所示 设置内网地址段为192.168.0.0,S0/1为外网出口。通过nat访问192.168.2.0网段。 操作步骤&#xff1a; 步骤1&#xff1a;连接网络拓扑结构图。 步骤2&#xff1a;配置计算机的IP地址、子网掩码和网关。 步骤3&#xff1a;设置Router-B的接口IP地址和DCE的…

linux0.11+Bochs环境搭建和使用

Linux 系统的创始人在一篇新闻组投稿上所说的&#xff0c;要理解一个软件系统的真正运行机制&#xff0c;一定 要阅读其源代码&#xff08;RTFSC – Read The Fucking Source Code&#xff09;。系统本身是一个完整的整体&#xff0c;具有很多看似 不重要的细节存在&#xff0c…

声明式事物的属性之只读、超时、回滚策略

声明式事物的属性之只读、超时、回滚策略 1. 事务属性&#xff1a;只读 ①介绍 对一个查询操作来说&#xff0c;如果我们把它设置成只读&#xff0c;就能够明确告诉数据库&#xff0c;这个操作不涉及写操作。这样数据库就能够针对查询操作来进行优化。 ②使用方式 Overri…

zabbix报警方式,邮件报警和微信报警。

整理csdn时候发现了一篇2016年整理zabbix报警不知道当时啥情况没有发布出去&#xff0c;凑个数重新发布 最近这些天都在弄Zabbix不再只是简单的监控物理硬件&#xff0c;服务端口&#xff0c;流量图等。让Zabbix的功能发挥到极致。 本篇博客只做笔记介绍zabbix的报警&#xff…

【数据结构与算法】顺序队列与环形队列

文章目录一 顺序队列1 应用场景2 基本概念&#xff08;1&#xff09;基本介绍&#xff08;2&#xff09;队列的顺序实现&#xff08;3&#xff09;队列的入队和出队操作&#xff08;4&#xff09;使用数组模拟队列3 代码实现&#xff08;1&#xff09;初始化队列&#xff08;2&…

React Native windows环境搭建

1.首先准备下载必须的依赖&#xff1a;Node、JDK 、Android Studio、夜神模拟器 ①Node可以直接到 官网 下载&#xff0c;版本必须大于14&#xff0c;我这边用的是v16.15.1 ②Jave JDK&#xff0c;我直接在360软件管家安装的&#xff0c;搜的是JDK 11&#xff0c;React Nativ…

【算法】双指针、位运算、离散化、合并区间

文章目录1.双指针2.位运算3.离散化4.区间合并1.双指针 双指针的算法可以优化时间复杂度,双指针&#xff0c;指的是在遍历对象的过程中&#xff0c;不是普通的使用单个指针进行访问&#xff0c;而是使用两个相同方向&#xff08; 快慢指针 &#xff09;或者相反方向&#xff08…

SQL调优SQLSERVER 数据页

1. 什么是数据页 一般来说&#xff0c;对大块资源或者数据进行高效管理都会按照一定粒度来划分的&#xff0c;比如说 Windows 对内存的管理就是按照 内存页 (4k) 来进行划分&#xff0c;言外之意就是 SQLSERVER 对 mdf 的管理也是按照 数据页 &#xff08;8k) 来划分的&#x…

(小记)matlab散点图

Matlab散点图两种画法一、plot画散点图二、scatter画散点图三、matlab工具画散点图plot画我可以设置坐标轴之类的&#xff0c;方便论文使用&#xff1b;scatter没设置成功。一、plot画散点图 参考&#xff1a;matlab中二维散点图,MATLAB实例&#xff1a;二维散点图 自用代码 …

一站式迁移,人大金仓助力保险业务无感升级

2021年3月&#xff0c;国家发布《中华人民共和国国民经济和社会发展第十四个五年规划和2035年远景目标纲要》&#xff0c;纲要明确提出“稳妥发展金融科技&#xff0c;加快金融机构数字化转型”、“推进金融业信息化核心技术安全可控&#xff0c;维护金融基础设施安全”。2022年…

如果通过股价均线分析股票

目录如果通过股价均线分析股票获取数据为什么要计算均价计算均价分析结果如果通过股价均线分析股票 获取数据 股票数据获取渠道非常丰富&#xff0c;可以通过上一篇文章 各大股票开放接口介绍中接口获取数据&#xff0c;需要提供技术支持的可以私聊。 为什么要计算均价 股票…

MongoDB:基础概述

MongoDB 是一个开源的、跨平台的、面向文档的、基于分布式文件存储的数据库系统&#xff0c;MongoDB 是由 C 语言开发&#xff0c;旨在为 Web 应用提供可扩展的高性能数据存储解决方案。在高负载的情况下&#xff0c;通过添加更多的节点&#xff0c;可以保证服务器性能。 本篇内…

【技术分享】无纸化会议|智慧教室同屏走RTSP组播还是RTMP?

技术背景 我们在做内网多人同屏&#xff08;比如无纸化会议、智慧教室同屏&#xff09;技术方案的时候&#xff0c;遇到个问题&#xff1a;到底使用轻量级RTSP服务实现组播&#xff0c;还是基于RTMP的解决方案&#xff1f; 先说为什么大家喜欢组播吧&#xff1a; 组播技术方…

js实现复制粘贴剪切功能

文章目录js实现复制粘贴功能方式一&#xff1a;原生方式实现复制粘贴剪切&#xff08;不推荐&#xff09;方式二&#xff1a;浏览器自带clipboard API实现复制粘贴&#xff08;推荐&#xff09;简介特点clipboard对象及相关APIClipboard.readText()Clipboard.read()Clipboard.w…