PriorityQueue底层使用Object[]数组实现的一个最小二叉堆,来到达一个优先队列功能,是线程不安全的。它与FIFO的队列的区别在于,优先队列每次出队的元素都是优先级最高的元素。那么怎么确定哪一个元素的优先级最高呢?PriorityQueue使用二叉堆这种数据结构,用户可以自定义的Comparator来确定每次出队的元素总是队列里面最小的,而元素的大小比较方法可以由用户指定Comparator(Comparator就相当于指定优先级),接下来我们先来看看堆这种数据结构。

1.二叉堆介绍

堆数据结构的特性

  • 堆中某个节点的值总是不大于或不小于其父节点的值。

  • 堆总是一棵完全二叉树。

在堆数据结构又有很多种,而PriorityQueue使用的便是二叉堆,二叉堆是一种特殊的堆,二叉堆是一颗完全二叉树或者是近似一颗完全二叉树。

(1)二叉堆分类

二叉堆分为两种:最大堆和最小堆。PriorityQueue使用的便是最小二叉堆,根的位置元素永远是最小的。

  • 最大堆:父结点的键值总是大于或等于任何一个子节点的键值。

  • 最小堆:父结点的键值总是小于或等于任何一个子节点的键值。

(2)二叉堆结构

这里我们最小二叉堆为例,将一个二叉堆结构用一颗完全二叉树表示出来,各个元素位置如下图 :

上图就是一颗完全二叉树(二叉堆),二叉堆特点:那就是在第n层深度被填满之前,不会开始填第n+1层深度,且元素插入是从左往右填满。基于这个特点我们用数据结构来表示一个二叉堆,如下图:

PriorityQueue内部实现就是使用一个Object[]数组来表示二叉堆的,基于数组实现的二叉堆结构具有以下特点:

  • 跟节点:数组实现的二叉堆,根节点在index=0位置上。

  • 左孩子:数组n位置上的元素,其左孩子在[2n+1]位置上。

  • 右孩子:数组n位置上的元素,其右孩子在 2(n+1) 位置上。

  • 父节点:数组n位置上的元素,其父节点在 (n-1)/2 位置上。

到此二叉堆的结构就了解完了,接下来在继续看看PriorityQueue是怎么实现的?

2.PriorityQueue源码分析

(1)PriorityQueue主要结构

PriorityQueue继承了AbstractQueue抽象类,并实现了Serializable接口,AbstractQueue抽象类实现了Queue接口,对元素添加、删除等方法进行了一些通用的定义。PriorityQueue的底层存储结构相关定义如下:

public class PriorityQueue<E> extends AbstractQueue<E>implements java.io.Serializable {private static final long serialVersionUID = -7720805057305804111L;// 用数组实现的二叉堆: 如前面的说法一样,左右子节点位置、父节点位置、根节点位置。/*** Priority queue represented as a balanced binary heap: the two* children of queue[n] are queue[2*n+1] and queue[2*(n+1)].  The* priority queue is ordered by comparator, or by the elements'* natural ordering, if comparator is null: For each node n in the* heap and each descendant d of n, n <= d.  The element with the* lowest value is in queue[0], assuming the queue is nonempty.*/transient Object[] queue; // non-private to simplify nested class access//数组默认初始化大小 private static final int DEFAULT_INITIAL_CAPACITY = 11;//队列的元素数量private int size = 0;//自定义比较器private final Comparator<? super E> comparator;//队列修改次数:修改版本transient int modCount = 0;//queue数组的最大长度,即队列的最大长度private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
}

可以看到PriorityQueue也是基于数组来实现一个二叉堆,PriorityQueue是一个有限队列,数据queue最大不能超过Integer.MAX_VALUE - 8,PriorityQueue中的优先级可以由用户指定,就是用户指定元素的Comparator比较器。

(2)PriorityQueue的构造方法

//1.默认构造方法:使用默认的初始11来构造一个优先队列,比较器comparator为空,这里要求入队的元素必须实现Comparator接口,不然在put元素时会抛ClassCastException
public PriorityQueue() {this(DEFAULT_INITIAL_CAPACITY, null);
}//2.指定一个初始化大小来构造优先队列,比较器comparator为空,这里要求入队的元素必须实现Comparator接口
public PriorityQueue(int initialCapacity) {this(initialCapacity, null);
}//3.默认初始化大小 和 指定一个comparator构造优先级队列
public PriorityQueue(Comparator<? super E> comparator) {this(DEFAULT_INITIAL_CAPACITY, comparator);
}//4.使用指定的初始大小和比较器来构造一个优先队列
public PriorityQueue(int initialCapacity,Comparator<? super E> comparator) {//初始大小不允许小于1if (initialCapacity < 1)throw new IllegalArgumentException();//使用指定初始大小创建数组this.queue = new Object[initialCapacity];//初始化比较器this.comparator = comparator;
}

优先级队列PriorityQueue也支持在构建的时候,将一个集合的元素初始化到该优先级队列中去。一共提供了三种构造器,如下继续分析源码。

//构造一个指定Collection集合参数的优先队列
public PriorityQueue(Collection<? extends E> c) {//判断集合c是不是SortedSet实例if (c instanceof SortedSet<?>) {SortedSet<? extends E> ss = (SortedSet<? extends E>) c;//使用SortedSet集合的比较器来初始化队列的Comparatorthis.comparator = (Comparator<? super E>) ss.comparator();//从集合中初始化数据到队列(注意:SortedSet是一个已经排好序的二叉树,所以初始化到优先级队列后不需要额外排序)initElementsFromCollection(ss);}//判断集合c是不是优先队列实例else if (c instanceof PriorityQueue<?>) {PriorityQueue<? extends E> pq = (PriorityQueue<? extends E>) c;//使用PriorityQueue的比较器来初始化队列的Comparatorthis.comparator = (Comparator<? super E>) pq.comparator();//从集合中初始化数据到队列(优先级队列不需要额外排序)initFromPriorityQueue(pq);}else {//其他类型的集合,元素必须实现Comparator接口,在压堆和出堆时需要将元素强转成Comparator在比较大小this.comparator = null;//从集合c中初始化元素到队列中(优先级队列需要额外排序)initFromCollection(c);}
}

上面构造器中initElementsFromCollection()、initFromPriorityQueue()和initFromCollection()的作用是将集合中的元素初始化到优先级队列中去,具体会涉及到堆结构的初始化。

//将元素从集合中初始化到优先级队列中
private void initElementsFromCollection(Collection<? extends E> c) {//目标队列Object[] a = c.toArray();//如果不是Object数组,则将c转换成Object数组if (a.getClass() != Object[].class)a = Arrays.copyOf(a, a.length, Object[].class);int len = a.length;if (len == 1 || this.comparator != null)//循环遍历check集合里面有没有为null的元素for (int i = 0; i < len; i++)if (a[i] == null)throw new NullPointerException();this.queue = a;this.size = a.length;
}//如果初始化集合就是一个优先级队列,直接赋值,不需额外的堆排序操作
private void initFromPriorityQueue(PriorityQueue<? extends E> c) {if (c.getClass() == PriorityQueue.class) {this.queue = c.toArray();this.size = c.size();} else {//如果集合C不是优先级队列类型时,需要额外的最小堆排序initFromCollection(c);}
}//初始化优先级队列object[]数组后,再额外的进行堆化(最小堆排序)
private void initFromCollection(Collection<? extends E> c) {//初始化object[]数组initElementsFromCollection(c);//堆化:最小堆排序操作(后面在详细分析)heapify();
}

在构造方法中,会调用initFromCollection方法将传入集合C初始化到优先队列queue后,再调用heapify方法对数组进行调整,使得它符合二叉堆的规范或者特点,具体heapify是怎么构造二叉堆的,后面再详细分析,先看看PriorityQueue的二叉堆的添加元素和删除元素的原理。

(3)PriorityQueue的入队实现

红黑树TreeMap的结构里为了维护其红黑平衡,主要有三个动作:左旋、右旋、变色。那么二叉堆为了维护他的特点又需要进行什么样的操作呢?先看看最小二叉堆的特点:

  • (1)父结点的键值总是小于或等于任何一个子节点的键值。

  • (2)基于数组实现的二叉堆,对于数组中任意位置的n上元素,其左孩子在[2n+1]位置上,右孩子[2(n+1)]位置,它的父亲则在[n-1/2]上,而根的位置则是[0]。

为了维护这个特点,二叉堆在添加元素的时候,需要一个"上移"的动作,那么怎么上移操作的呢?过程如下图。

结合上面的图解,说明一下二叉堆的添加元素的过程:

  • (1)将元素2添加在最后一个位置(队尾)(图2)。

  • (2)由于2比其父亲6要小,所以将元素2上移,交换2和6的位置(图3)。

  • (3)然后由于2比5小,继续将2上移,交换2和5的位置(图4),此时2大于其父亲(根节点)1,结束。

下面我们来具体分析一下PriorityQueue入队代码的具体实现过程。

//(1)添加元素
public boolean add(E e) {return offer(e);
}//(2)元素上移操作
public boolean offer(E e) {//添加元素不能为null,需要comparator比较元素大小if (e == null)throw new NullPointerException();//修改版本+1modCount++;//记录当前队列中元素的个数int i = size;//如果当前元素个数大于等于队列底层数组的长度,则进行扩容if (i >= queue.length)grow(i + 1);//元素个数+1size = i + 1;if (i == 0)//如果队列中没有元素,则将元素e直接添加至根(数组小标0的位置)queue[0] = e;else//否则调用siftUp方法,将元素添加到尾部,进行上移判断siftUp(i, e);return true;
}//(3)数组扩容:添加时,元素个数大于等于队列底层数组的长度,则进行扩容。
private void grow(int minCapacity) {//获取队列的数组的长度int oldCapacity = queue.length;//扩容:如果oldCapacity小于64,每次扩容到2*oldCapacity + 2大小;否则扩大到3倍int newCapacity = oldCapacity + ((oldCapacity < 64) ?(oldCapacity + 2) :(oldCapacity >> 1));//长度溢出判断:newCapacity长度超出了最大值限制,hugeCapacity方法赋值为Integer.MAX_VALUEif (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);//扩容并拷贝元素queue = Arrays.copyOf(queue, newCapacity);
}//(4)元素上移实现方法:x表示新增的元素,k表示原堆数组的长度。
private void siftUp(int k, E x) {if (comparator != null)//如果比较器comparator不为空,则调用siftUpUsingComparator方法进行上移操作siftUpUsingComparator(k, x);else//如果比较器comparator为空,则调用siftUpComparable方法进行上移操siftUpComparable(k, x);
}
//(5)元素上移操作具体实现:用户指定了comparator。(x表示新增的元素,k表示原堆数组的长度)
private void siftUpUsingComparator(int k, E x) {//k>0表示判断k不是根的情况下,也就是元素x有父节点while (k > 0) {//计算原数组最后一个元素的父节点位置[(n-1)/2]int parent = (k - 1) >>> 1;//取出原数组最后一个元素的父亲eObject e = queue[parent];//如果新增的元素x比最后一个元素的父亲e大,则不需要"上移",跳出循环结束if (comparator.compare(x, (E) e) >= 0)break;//x比父亲小,则需要进行"上移",交换元素x和父亲e的位置queue[k] = e;//将新插入元素的位置k指向父亲的位置,进行下一层循环k = parent;}//找到新增元素x的合适位置k之后,进行赋值queue[k] = x;
}//(6)元素上移操作具体实现:使用元素的comparator进行比较,逻辑和siftUpUsingComparator()一样
private void siftUpComparable(int k, E x) {Comparable<? super E> key = (Comparable<? super E>) x;while (k > 0) {int parent = (k - 1) >>> 1;Object e = queue[parent];if (key.compareTo((E) e) >= 0)break;queue[k] = e;k = parent;}queue[k] = key;
}

添加元素时,二叉堆"上移"操作的代码还是很容易理解的,主要就是不断的将新增元素和其父亲进行大小比较,比父亲小则上移,最终找到一个合适的位置。中间有一个点需要注意的就是扩容问题。

(4)PriorityQueue的出队实现

PriorityQueue的出队实现实际就是二叉堆的删除根的原理;对于二叉堆的出队操作,出队永远是删除根元素操作,也就是最小的元素,要删除根元素,就要找一个元素替代者移动到根位置,相对于被删除的元素来说就是"下移"。下移过程如下:

结合上面的图解,我们来说明一下二叉堆的出队过程:

  • (1)将找出队尾的元素8,并将它在队尾位置上删除(图2)。

  • (2)此时队尾元素8比根元素1的最小孩子3要大,所以将元素1下移,交换1和3的位置(图3)。

  • (3)然后此时队尾元素8比元素1的最小孩子4要大,继续将1下移,交换1和4的位置(图4)。

  • (4)然后此时根元素8比元素1的最小孩子9要小,不需要下移,直接将根元素8赋值给此时元素1的位置,再将队尾位置值置null(图5),结束。

下面我们来具体分析一下PriorityQueue的代码是怎么实现出队操作的。

//(1)PriorityQueue二叉堆的出队操作
public E poll() {//队列为空,返回nullif (size == 0)return null;//队列元素个数-1int s = --size;//修改版本+1modCount++;//取出队头的元素E result = (E) queue[0];//取出队尾的元素E x = (E) queue[s];//将队尾元素置为nullqueue[s] = null;//如果队列中不止队尾一个元素,则调用siftDown方法进行"下移"操作if (s != 0)siftDown(0, x);return result;
}//(2)下移操作:x表示队尾的元素,k表示被删除元素在数组的位置
private void siftDown(int k, E x) {if (comparator != null)//如果比较器comparator不为空,则调用siftDownUsingComparator方法进行下移操作siftDownUsingComparator(k, x);else//比较器comparator为空,则调用siftDownComparable方法进行下移操作siftDownComparable(k, x);
}//(3)元素下移操作具体实现:指定comparator
private void siftDownUsingComparator(int k, E x) {//通过size/2找到第一个没有叶子节点的元素(根据堆父节点位子关系:父节点在 (n-1)/2位置上,堆最后一个元素的位子是size-1,则最后一个有叶子节点的元素位子是:(size-1-1)/2,所以第一个没有叶子节点的元素的位子是size/2)int half = size >>> 1;//比较位置k和half,如果k小于half,则k位置的元素就不是叶子节点while (k < half) {//找到根元素的左孩子的位置[2n+1]int child = (k << 1) + 1;//左孩子的元素Object c = queue[child];//找到根元素的右孩子的位置[2(n+1)]int right = child + 1;//如果左孩子大于右孩子,则将c赋值为右孩子的值,这里也就是找出左右孩子哪个最小if (right < size && comparator.compare((E) c, (E) queue[right]) > 0)c = queue[child = right];//如果队尾元素比根元素孩子都要小,则不需"下移",结束。(此时就找到了尾节点x要赋值的位子)if (comparator.compare(x, (E) c) <= 0)break;//队尾元素比根元素孩子都大,则需要"下移",交换跟元素和孩子c的位置queue[k] = c;//将根元素位置k指向最小孩子的位置,进入下次循环k = child;}//找到队尾元素x的合适位置k之后进行赋值queue[k] = x;
}//(4)元素下移操作具体实现:使用元素的comparator,和siftDownUsingComparator逻辑一样
private void siftDownComparable(int k, E x) {Comparable<? super E> key = (Comparable<? super E>)x;int half = size >>> 1;        // loop while a non-leafwhile (k < half) {int child = (k << 1) + 1; // assume left child is leastObject c = queue[child];int right = child + 1;if (right < size &&((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)c = queue[child = right];if (key.compareTo((E) c) <= 0)break;queue[k] = c;k = child;}queue[k] = key;
}

PriorityQueue中,不是直接将根元素删除,然后再将下面的元素做上移,重新补充根元素;而是找出队尾的元素,并在队尾的位置上删除,然后通过根元素的下移,给队尾元素找到一个合适的位置,最终覆盖掉跟元素,从而达到删除根元素的目的。这样做在一些情况下,会比直接删除在上移根元素,或者直接下移根元素再调整队尾元素的位置少操作一些步奏。

搞明白了二叉堆的入队和出队操作后,接下来我们再来看一个二叉堆中比较重要的过程:二叉堆的初始化构造。

(5)最小堆的构造过程

在前面构造函数中可以指定集合初始化到优先级队列中,提到堆的构造是通过一个heapify方法实现的,下面我们来看下heapify方法的实现。

private void heapify() {for (int i = (size >>> 1) - 1; i >= 0; i--)siftDown(i, (E) queue[i]);
}

这个方法很简单,就这几行代码,但是理解起来却不是那么容器的。具体来分析一下,假设有一个无序的数组,要求我们将这个数组建成一个二叉堆,最简单的办法当然是将数组的数据一个个取出来,调用入队方法。但是这样做,每次入队都有可能会伴随着元素的移动,这么做是十分低效的。那么有没有更加高效的方法呢,就是我问上面讲到的"下移"操作

为了方便,先构建一个无序的二叉堆数组,顺序已经随机打乱,暂时不用符合最小二叉堆的标准。如下图:int a = [7, 6, 5, 12, 10, 3, 1, 11, 15, 4 ]。

观察下用数组a建成的二叉堆,很明显,对于叶子节点4、15、11、1、3来说,它们已经是一个合法的堆。所以只要最后一个节点的父节点,也就是最后一个非叶子节点a[4]=10开始调整,然后依次调整a[3]=12,a[2]=5,a[1]=6,a[0]=7,分别对这几个节点做一次"下移"操作就可以完成了堆的构造。操作过程如下这个过程。

参照图解分别来解释下这几个步奏:

  • (1)对于节点a[4]=10的调整(图1),只需要交换元素10和其子节点4的位置(图2)。

  • (2)对于节点a[3]=12的调整,只需要交换元素12和其最小子节点11的位置(图3)。

  • (3)对于节点a[2]=5的调整,只需要交换元素5和其最小子节点1的位置(图4)。

  • (4)对于节点a[1]=6的调整,只需要交换元素6和其最小子节点4的位置(图5)。

  • (5)对于节点a[0]=7的调整,只需要交换元素7和其最小子节点1的位置,然后交换7和其最小自己点3的位置(图6)。

至此,调整完毕,建堆完成。 再来回顾一下,PriorityQueue的建堆代码,这下就可以看得懂了。

private void heapify() {#(size >>> 1) - 1,这行代码是为了找寻最后一个非叶子节点,然后倒序进行"下移"siftDown操作。for (int i = (size >>> 1) - 1; i >= 0; i--)siftDown(i, (E) queue[i]);
}#备注:最后一个非叶子节点就是数组最后一个节点的父节点,根据最好二叉堆父节点在 (n-1)/2位置上,则最后一个节点的父节点为:(size-1-1)/2 = size/2 -1

到此PriorityQueue的最小二叉堆结构重要的操作就分析完了,明白了其底层二叉堆的概念及其入队、出队、建堆等操作,其他的一些方法代码就很简单了。

 通过最近在找工作,才发现好多知识点平时都学得不深入,只是停留在皮毛上;每一次的痛苦都是成长的过程,坚持学习,持续成长,最后才能变成自己想变成的人。

                                                                             2020年08月08日 晚 于北京记

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 2020秋招面试必刷题:并发编程+JVM+设计模式+Redis+Spring

    面试主要及经常问到技术点: 并发编程、多线程、JVM、优化、Spring、消息框架、分布式、缓存等以及你使用过的框架且第一轮的基础很重要,通过会后录取可能性就相对高了! 今天已经将这些都常问的技术点的问题都整理出来了,希望能帮助到深夜还在为面试做准的朋友、后续准备面试…...

    2024/4/28 13:11:51
  2. Netty中内存泄漏问题

    现在需要做一个流媒体服务器,打算使用Netty来实现协议的解析,视频流的转码等。数据的传输载体使用的是ByteBuf,但是写完代码进行单元压测时,老是内存泄漏,现在记录一下。Netty里四种主力的ByteBuf其中UnpooledHeapByteBuf 底下的byte[]能够依赖JVM GC自然回收;而Unpooled…...

    2024/4/22 5:06:29
  3. Android端的短视频软件开发,我们该如何快速实现移动端短视频功能?

    一.短视频内容生产优质短视频内容的产生依赖于短视频的采集和特效编辑,这就要求在进行抖音APP开发时,用到基础的美颜、混音、滤镜、变速、图片视频混剪、字幕等功能,在这些功能基础上,进行预处理,结合OpenGL、AI、AR技术,产生很多有趣的动态贴纸玩法,使得短视频内容更具…...

    2024/4/28 21:32:09
  4. Fabric区块大小的实验

    首先记录已在账本的大小,见下图,大小是319784字节。修改peer的源代码,将区块写入文件时,输出新区块的大小。编译peer并替代原来的peer,重新启动节点。在终端上记录区块高度。调用智能合约的链码函数,产生一个新区块,账本大小变为324059,相对之前增加了4275字节。观察pe…...

    2024/4/27 2:37:51
  5. Linux按键驱动

    按键驱动一、补充知识1.中断1.1 概念1.2 Linux中断上下部分区别:1.3 处理原则1.4 中断下半部1.5 中断使用2. 定时器jiffies3. 等待队列3.1 定义并初始化"等待队列头"3.2 等待事件3.3唤醒队列二、驱动程序编写1. 创建描述设备数据结构2. 编写模块3.模块配置4. 配置卸…...

    2024/4/28 11:39:06
  6. 数学建模

    (一)线性规划线性规划问题是在一组线性约束条件的限制下,求一线性目标函数最大或最小的问题。线性规划的Matlab标准形式:其中和为维列向量,、为适当维数的矩阵,、为适当维数的列向量。例如线性规划的Matlab标准型为1、求解线性规划问题c = [2;3;-5]; a = [-2 5 -1;1 3 1]…...

    2024/4/28 8:38:34
  7. Java中数据的存储方式

    Java中内存的划分方法区:用于存放类的相关信息栈区(Stack):存放的是变量的相关信息 如:局部变量;方法的运行一定要在栈中 ​ 局部变量:方法中的参数或者是方法{}中的变量 ​ 作用域:只在当前方法中有效,超出该方法则无效堆区(Heap):凡是new出来的东西,都存储在堆区中 ​ 堆区内…...

    2024/4/28 15:46:13
  8. Mybatis连接数据库和使用Mybatis要注意的坑

    使用mybatis连接数据库首先要导入jar 可以自己找需要的jar:maven中央仓库 //mybatis <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId>&l…...

    2024/4/27 23:11:37
  9. 随笔:列表(序列)遍历的一个小坑

    问题描述:循环按序号遍历列表时,对列表中元素删除,可能会影响启遍因效果# 功能描述:将从l1中,删除s1中的元素 l1 = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j&q…...

    2024/4/28 3:45:37
  10. I.MX6ULL镜像文件

    文章目录1 I.MX6ULL镜像文件 1 I.MX6ULL镜像文件 boot ROM程序: 选择内部启动方式,启动boot ROM程序初始化时钟、外部DDR3 从外部存储介质加载代码必须解决两个问题:DDR3初始化参数如何确定?代码加载到哪里?镜像文件中就描述了这些问题。 镜像文件的五要素:空偏移芯片厂商…...

    2024/4/28 20:01:13
  11. 短视频软件开发 SDK 架构设计实践

    短视频发展史图 1图 1 所示是短视频及直播的发展史,众所周知,2016 年是直播元年,在这期间诞生了很多直播平台,比如熊猫、映客、斗鱼等;而在 2017 年,短视频的火爆程度并不亚于直播,可能大家都以为短视频是从 2017 年开始火爆起来的,但其实早在 2015 年就已经诞生出快手…...

    2024/4/28 20:01:55
  12. Mybatis开始驼峰匹配

    可以在mybatis-config.xml配置文件中,通过settings标签进行设置配置文件代码:<settings><!--开启驼峰匹配--><setting name="mapUnderscoreToCamelCase" value="true"/></settings>...

    2024/4/28 16:40:49
  13. SPARK YARN CLUSTER模式的启动过程

    通过submit命令启动后${SPARK_HOME}/bin/spark-submit --master yarn-cluster --class com.bigdata.WordCount --executor-memory 2G \ --num-executors 4 ${SPARK_HOME}/wordcount-1.0-SNAPSHOT.jar hdfs://spark-master:9000 /temp/inputdir /temp/outputdir实际上启动的是o…...

    2024/4/23 15:45:29
  14. 阿里云”7天实践训练营“[day3]总结笔记

    搭建Linux学习环境Linux远程管理一、命令终端二、文件传输三、代码编辑四、设置安全组为Linux环境安装图形化桌面(Gnome)Ubuntu安装方式CentOS安装方式Linux基本操作 Linux远程管理 一般来说 Linux 的远程管理分三个模块:命令终端、文件传输和代码编辑。 一、命令终端 命令终…...

    2024/4/26 19:49:03
  15. 实验·搭建nginx网站

    实验搭建nginx网站 实验环境 CentOS 7.6 nginx源码包 nginx-1.12.2.tar 实验步骤===>开启nginx统计模块并可以正常访问 #创建用户nginx [root@localhost opt]# useradd -M -s /sbin/nologin nginx#安装环境 [root@localhost opt]# yum -y install gcc gcc-c++ pcre pcre-dev…...

    2024/3/29 2:16:06
  16. Semaphore 使用信号量控制对资源的N个副本的并发访问

    目录Semaphore:主程序:打印机组:Semaphore:这是一个计数器,用来控制N个共享资源的访问,这是一种基本的并发编程工具。主程序:该DEMO模拟20个任务,共享3个打印机的过程。并使其有序使用打印机。package xyz.jangle.thread.test.n3_2.semaphore;/*** Semaphore DEMO 使用…...

    2024/4/22 7:56:59
  17. P1029 最大公约数和最小公倍数问题

    这道题蛮简单的,但是也需要一点预备知识,两个数的最小公倍数和最大公约数的乘积等于这两个数的乘积. 证明:x0 y0的最大公约数是A,最小公倍数是B, x1=x0/A,y1=y0/A 那么x1 y1一定是互质的 所以x1 * y1 * A=B 展开一下就可以得到 A*B=x0 * y0 至于为什么x1y1A=B,可以去康一下最…...

    2024/4/19 8:19:45
  18. 递归——N皇后问题(c++)

    声明:解法来自 北京大学 郭炜老师的程序设计与算法(二)算法基础 仅作学习笔记 问题描述在一个N*N的棋盘上放置N个皇后,每行一个并使其不能互相攻击(同一行、同一列、同一斜线上的皇后都会自动攻击)样例输入4样例输出2 4 1 3 3 1 4 2代码 #include<iostream> #inclu…...

    2024/4/19 5:43:41
  19. python赋值操作、浅拷贝、深拷贝以及函数传递参数详细解析

    学过C语言的同学都能分清楚变量和指针的区别,而python的变量全部是指针的形式,所以在变量的赋值操作时(如a=b),只是将索引复制了一份。如果想把指针索引的内容进行复制, 则需要用到浅拷贝和深拷贝。下面来介绍一下python的赋值操作、浅拷贝和深拷贝的区别。 赋值操作 如果…...

    2024/4/26 22:57:55
  20. springCloud服务注入进consul,出现错误Service ‘consul-provider-payment‘ check unhealthy

    出错如下;自己查了一下,原来是默认把心跳协议关了3. 解决方法就很简单了,在application文件中,把心跳协议打开就好了。4. 最后重启一下就好了...

    2024/4/24 7:35:31

最新文章

  1. [tkinter实现]汉字笔顺小软件

    软件简介 本软件旨在帮助小学生通过互动式学习掌握汉字的基本笔画和笔顺。软件采用Tkinter库构建&#xff0c;提供了一个用户友好的图形界面&#xff0c;适合小学生使用。 主要功能&#xff1a; 汉字展示&#xff1a;软件能够展示单个汉字&#xff0c;并以动画形式演示其标准…...

    2024/4/28 23:44:46
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 腾讯云云原生数据库TDSQL-C mysql 以及项目怎么接入

    要接入腾讯云的云原生数据库TDSQL-C的MySQL版本&#xff0c;并将它用于你的项目中&#xff0c;你需要按照以下步骤进行&#xff1a; 创建TDSQL-C的MySQL数据库实例&#xff1a; 登录腾讯云控制台。在产品搜索框中搜索TDSQL-C&#xff0c;然后选择它。在TDSQL-C的产品页面上&…...

    2024/4/27 8:49:34
  4. FreeRTOS学习 -- 再识

    工作中一直使用FreeRTOS进行着开发&#xff0c;但是没有进行过系统的总结过。现在将快速使用几天时间将FreeRTOS相关知识点加以总结。 官网&#xff1a; https://www.freertos.org/zh-cn-cmn-s/ 参看资料&#xff1a; 正点原子 STM32F1 FreeRTOS开发手册_V1.2.pdf The FreeRTOS…...

    2024/4/23 6:24:52
  5. 备战蓝桥杯Day37 - 真题 - 特殊日期

    一、题目描述 思路&#xff1a; 1、统计2000年到2000000年的日期&#xff0c;肯定是需要遍历 2、闰年的2月是29天&#xff0c;非闰年的2月是28天。我们需要判断这一年是否是闰年。 1、3、5、7、8、10、12月是31天&#xff0c;4、6、9、11月是30天。 3、年份yy是月份mm的倍数…...

    2024/4/24 9:33:16
  6. 416. 分割等和子集问题(动态规划)

    题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义&#xff1a;dp[i][j]表示当背包容量为j&#xff0c;用前i个物品是否正好可以将背包填满&#xff…...

    2024/4/28 4:04:40
  7. 【Java】ExcelWriter自适应宽度工具类(支持中文)

    工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...

    2024/4/28 12:01:04
  8. Spring cloud负载均衡@LoadBalanced LoadBalancerClient

    LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon&#xff0c;直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件&#xff0c;我们讨论Spring负载均衡以Spring Cloud2020之后版本为主&#xff0c;学习Spring Cloud LoadBalance&#xff0c;暂不讨论Ribbon…...

    2024/4/28 16:34:55
  9. TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案

    一、背景需求分析 在工业产业园、化工园或生产制造园区中&#xff0c;周界防范意义重大&#xff0c;对园区的安全起到重要的作用。常规的安防方式是采用人员巡查&#xff0c;人力投入成本大而且效率低。周界一旦被破坏或入侵&#xff0c;会影响园区人员和资产安全&#xff0c;…...

    2024/4/28 18:31:47
  10. VB.net WebBrowser网页元素抓取分析方法

    在用WebBrowser编程实现网页操作自动化时&#xff0c;常要分析网页Html&#xff0c;例如网页在加载数据时&#xff0c;常会显示“系统处理中&#xff0c;请稍候..”&#xff0c;我们需要在数据加载完成后才能继续下一步操作&#xff0c;如何抓取这个信息的网页html元素变化&…...

    2024/4/28 12:01:03
  11. 【Objective-C】Objective-C汇总

    方法定义 参考&#xff1a;https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...

    2024/4/28 12:01:03
  12. 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】

    &#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格…...

    2024/4/28 12:01:03
  13. 【ES6.0】- 扩展运算符(...)

    【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数&#xff0…...

    2024/4/28 16:07:14
  14. 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?

    文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕&#xff0c;各大品牌纷纷晒出优异的成绩单&#xff0c;摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称&#xff0c;在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁&#xff0c;多个平台数据都表现出极度异常…...

    2024/4/28 23:42:05
  15. Go语言常用命令详解(二)

    文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令&#xff0c;这些命令可以帮助您在Go开发中进行编译、测试、运行和…...

    2024/4/28 9:00:42
  16. 用欧拉路径判断图同构推出reverse合法性:1116T4

    http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b&#xff0c;我们在 a i a_i ai​ 和 a i 1 a_{i1} ai1​ 之间连边&#xff0c; b b b 同理&#xff0c;则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然&#xff0…...

    2024/4/27 18:40:35
  17. 【NGINX--1】基础知识

    1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息&#xff0c;并安装一些有助于配置官方 NGINX 软件包仓库的软件包&#xff1a; apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...

    2024/4/28 4:14:21
  18. Hive默认分割符、存储格式与数据压缩

    目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限&#xff08;ROW FORMAT&#xff09;配置标准HQL为&#xff1a; ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...

    2024/4/27 13:52:15
  19. 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法

    文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中&#xff0c;传感器和控制器产生大量周…...

    2024/4/27 13:38:13
  20. --max-old-space-size=8192报错

    vue项目运行时&#xff0c;如果经常运行慢&#xff0c;崩溃停止服务&#xff0c;报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中&#xff0c;通过JavaScript使用内存时只能使用部分内存&#xff08;64位系统&…...

    2024/4/28 12:00:58
  21. 基于深度学习的恶意软件检测

    恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞&#xff0c;例如可以被劫持的合法软件&#xff08;例如浏览器或 Web 应用程序插件&#xff09;中的错误。 恶意软件渗透可能会造成灾难性的后果&#xff0c;包括数据被盗、勒索或网…...

    2024/4/28 12:00:58
  22. JS原型对象prototype

    让我简单的为大家介绍一下原型对象prototype吧&#xff01; 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定&#xff0c;每一个构造函数都有一个 prototype 属性&#xff0c;指向另一个对象&#xff0c;所以我们也称为原型对象…...

    2024/4/27 22:51:49
  23. C++中只能有一个实例的单例类

    C中只能有一个实例的单例类 前面讨论的 President 类很不错&#xff0c;但存在一个缺陷&#xff1a;无法禁止通过实例化多个对象来创建多名总统&#xff1a; President One, Two, Three; 由于复制构造函数是私有的&#xff0c;其中每个对象都是不可复制的&#xff0c;但您的目…...

    2024/4/28 7:31:46
  24. python django 小程序图书借阅源码

    开发工具&#xff1a; PyCharm&#xff0c;mysql5.7&#xff0c;微信开发者工具 技术说明&#xff1a; python django html 小程序 功能介绍&#xff1a; 用户端&#xff1a; 登录注册&#xff08;含授权登录&#xff09; 首页显示搜索图书&#xff0c;轮播图&#xff0…...

    2024/4/28 8:32:05
  25. 电子学会C/C++编程等级考试2022年03月(一级)真题解析

    C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...

    2024/4/27 20:28:35
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57