当前位置: 首页 > news >正文

[Collection与数据结构] PriorityQueue与堆

1. 优先级队列

1.1 概念

前面介绍过队列,队列是一种先进先出(FIFO)的数据结构,但有些情况下,操作的数据可能带有优先级,一般出队列时,可能需要优先级高的元素先出队列,该中场景下,使用队列显然不合适,比如:在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话.
在这种情况下,数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)。
在这种情况下,数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)。
在这里插入图片描述

2. 优先级队列的模拟实现

PriorityQueue底层实现使用了这种数据结构,堆实际上就是在完全二叉树的基础上做了一些调整,使得里面的元素按照一定地规则排列,而堆的元素存储在一个数组中.

2.1 堆的概念

如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式存储 在一个一维数组中,并满足:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,则称为 小堆(或大堆)也就是任意拿出一棵子树来,子结点都比父结点小(或大).将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆
在这里插入图片描述

2.2 堆的性质

  • 堆是一颗完全二叉树
  • 堆中的某个结点的值总是不大于或者不小于父结点的值

2.3 堆的存储方式

从堆的概念可知,堆是一棵完全二叉树,因此可以层序的规则采用顺序的方式来高效存储.
实例如上图所示.
将元素存储到数组中后,可以根据二叉树章节的性质对树进行还原。假设i为节点在数组中的下标,则有:

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

2.4 堆的创建

2.4.1 向下调整创建堆

对于集合{ 27,15,19,18,28,34,65,49,25,37 }中的数据,如果将其创建成堆呢?
首先将数组中的元素按照二叉树层序遍历的方法进行存放.
在这里插入图片描述
接下来,我们要做的就是对上面这颗二叉树进行向下调整.那么如何向下调整呢:我们以大根堆为例来说明.

  • 从堆的最后一棵子树开始比较父结点和子结点的大小关系(之所以从最后一棵子树开始调整,是因为必须让子树满足堆的特性,后续才好调整).使用parent标记最后一棵子树的父节点,使用child标记最后一棵子树的左孩子.
  • 把parent的值和child的值进行比较:
    • 比较右孩子的值是否大于左孩子,如果大于,child++,child变量引用移动到右孩子上.
    • 比较parent和child的值,如果child的值大于parent的值,则交换两个值,如果不是则停止向下调整.
    • 之后把parent和child向下移动,再次向下调整,即parent = child,child = child*2+1.直到child的值大于存储元素的数组的最后一个下标.
  • 之后把parent向上移动,即parent–,继续上述过程.
    下面画图来举例,我们给定一个任意完全二叉树:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    之后以此类推…
    为什么要从子树开始调整呢?因为首先要保证子树是大根堆,调整根层数更小的树的时候才会好调整.就像我们盖房子一样,先要把地基打牢,才可以盖得起高楼大厦.
    在这里插入图片描述
    完整过程如下:
    在这里插入图片描述

接下来我们通过代码来创建一个大根堆:

public class MyPriorityQueue {public int usedSize;public int[] elem;//堆通过数组来实现public MyPriorityQueue(int[] elem) {this.elem = elem;usedSize += elem.length;}public void createBigHeap(){for (int parent = (usedSize-2)/2; parent >= 0 ; parent--) {//从最后一棵子树开始调整//之后根向上父结点向上走shiftDown(parent,usedSize-1);//向下调整//子结点永远是这棵树的最后一个结点}}/*** 向下调整* @param parent 父节点* @param end 结束位置*/private void shiftDown(int parent,int end){int child = 2*parent+1;//此时child是左孩子while (child <= end){if (child+1 < usedSize && elem[child] < elem[child+1]){//若右孩子存在,并且大于左孩子child++;//让child到右孩子这里}if (elem[parent] < elem[child]){swap(parent,child);parent = child;child = 2*child+1;}else {break;//如果父结点不大于子结点,说明已经调整完成,因为是从下往上调的}}}private void swap(int s1,int s2){int tmp = elem[s1];elem[s1] = elem[s2];elem[s2] = tmp;}
}

接下来我们来看小根堆如何进行调整,小根堆的调整恰好和大根堆相反,小根堆的调整是从根节点开始调整,直到叶子结点.

  1. 让parent标记需要调整的结点,child标记parent的左孩子节点.
  2. 如果parent的左孩子存在,即child<size,进行以下的操作,直到parent的左孩子不存在.
    • parent右孩子是否存在,存在的话,就找到左右孩子中最小的孩子,让child进行标注.
    • 将parent和child进行比较,如果parent的值小于child,停止调整.否则交换parent和child的值,交换完成之后parent的值和child的值向下移动,即parent = child;child = parent*2+1之后重复上述步骤,直到child大于存储元素数组的最后一个位置.
  3. 之后让parent向下移动,即parent++.重复上述步骤,直到parent到达最后一棵子树.
    在这里插入图片描述
    代码实现:
/*** 创建小根堆*/
public void createSmallHeap(){for (int parent = 0;parent <= (usedSize-2)/2;parent++){shiftDown2(parent,usedSize-1);}
}/*** 小根堆向下调整*/
private void shiftDown2(int parent,int end) {int child = parent*2+1;if (child+1 < usedSize && elem[child] > elem[child+1]){child++;}while(child <= end){if (elem[parent] > elem[child]){swap(parent, child);parent = child;child = 2*child+1;}else{break;}}
}

向下调整的时间复杂度: 最坏的情况就是从根节点一直比较到叶子结点,比较的次数为完全二叉树的高度,即时间复杂度为O(log2N).

2.4.1 创建堆的时间复杂度推导

在这里插入图片描述
因此:建堆的时间复杂度为O(N).

2.5 堆的插入与删除

2.5.1 堆的插入

堆的插入分下面两个步骤:

  • 把结点插入树的最后一个位置
  • 把这个结点进行向上调整

那么,向上调整又如何调整呢?我们以大根堆为例

  • 把插入元素所在的结点与父节点进行比较.
  • 如果父结点小于插入结点,则交换两个结点,否则停止向上调整.
  • 如果成功交换,重复上述步骤,知道父结点大于子结点或者比较到根结点.
    下面我们通过代码来展示:
/*** 插入元素* @param val 要插入的值*/public void offer(int val){if (isFull()){this.elem = Arrays.copyOf(elem,elem.length*2);//如果数组满了的话,需要进行扩容}elem[usedSize] = val;usedSize++;shiftUp(usedSize-1);//这里注意是usedSize-1,因为usedSize++过,现在需要//向上调整的元素是usedSize-1位置上的元素}/*** 向上调整* @param child 因为向上调整的终点都是根结点,所以传入child*/private void shiftUp(int child){int parent = (child - 1)/2;while (child > 0){if (elem[parent] < elem[child]){swap(elem[parent],elem[child]);child = parent;parent = (parent-1)/2;}else {break;}}}/*** 判断堆元素是否为满* @return*/private boolean isFull(){if (elem.length == usedSize){return true;}else {return false;}}

2.5.2 堆的删除

注意:在删除元素的时候,一定删除的是堆顶元素.

  • 将堆顶元素和最后一个元素进行交换
  • 删除最后一个元素
  • 将堆顶结点进行向下调整
    在这里插入图片描述
    下面通过代码来展示:
/**
* 删除堆顶元素
*/
public void poll(){if (usedSize == 0){return;}swap(elem[0],elem[usedSize-1]);usedSize --;shiftDown(0,usedSize-1);
}

这里需要注意的是,与堆的创建不同,这里只需要堆根节点进行向下调整即可,不需要堆整棵树进行向下调整.

3. PriorityQueue

3.1 PriorityQueue的性质

Java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的,本文主要介绍PriorityQueue.
关于PriorityQueue的使用要注意:

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

3.2 PriorityQueue的使用

  1. 构造方法
构造器功能介绍
PriorityQueue()创建一个空的优先级队列,默认容量是11
PriorityQueue(int initialCapacity)创建一个初始容量为initialCapacity的优先级队列,注意:initialCapacity不能小于1,否则会抛IllegalArgumentException异常
PriorityQueue(Collection<? extends E> c)用一个集合来创建优先级队列
public PriorityQueue(Comparator<? super E> comparator)传入比较器----改变元素之间的比较规则

源码如下:

private static final int DEFAULT_INITIAL_CAPACITY = 11;//默认容量
public PriorityQueue() {this(DEFAULT_INITIAL_CAPACITY, null);}
public PriorityQueue(int initialCapacity) {//用户传入自定义容量this(initialCapacity, null);}
public PriorityQueue(Comparator<? super E> comparator) {this(DEFAULT_INITIAL_CAPACITY, comparator);//通过比较器改变优先级队列中元素的比较规则}
public PriorityQueue(Collection<? extends E> c) {if (c instanceof SortedSet<?>) {SortedSet<? extends E> ss = (SortedSet<? extends E>) c;this.comparator = (Comparator<? super E>) ss.comparator();initElementsFromCollection(ss);}else if (c instanceof PriorityQueue<?>) {PriorityQueue<? extends E> pq = (PriorityQueue<? extends E>) c;this.comparator = (Comparator<? super E>) pq.comparator();initFromPriorityQueue(pq);}else {this.comparator = null;initFromCollection(c);}}

使用实例:

static void TestPriorityQueue(){// 创建一个空的优先级队列,底层默认容量是11PriorityQueue<Integer> q1 = new PriorityQueue<>();// 创建一个空的优先级队列,底层的容量为initialCapacityPriorityQueue<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());}

通过传入比较器来创建大根堆,需要注意的是,这里在创建比较器的时候,需要实现Comparator接口(注意单词的拼写),在接口之后指定泛型参数,并且重写compare()方法.

public class Compare implements Comparator<Integer> {@Overridepublic int compare(Integer o1, Integer o2) {return o2-o1;}
}
public class Main {public static void main(String[] args) {PriorityQueue<Integer> priorityQueue1 = new PriorityQueue<>(new Compare());priorityQueue1.offer(1);priorityQueue1.offer(2);priorityQueue1.offer(3);priorityQueue1.offer(4);priorityQueue1.offer(5);System.out.println(priorityQueue1);//通过传入比较器对象,可以构建大根堆}
}

也可以通过传入比较器使得不可比较的对象变为可比较的对象:

public class Student{public String name;public int age;@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}public Student(String name, int age) {this.name = name;this.age = age;}
}
import java.util.Comparator;/*** 年龄比较规则*/
public class Compare1 implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o2.age - o1.age;}
}
public class Main {public static void main(String[] args) {PriorityQueue<Student> priorityQueue2 = new PriorityQueue<>(new Compare1());//由于Student没有默认创建比较方法,所以必须传入比较器对象,否者异常priorityQueue2.offer(new Student("zhangsan",12));priorityQueue2.offer(new Student("lisi",17));priorityQueue2.offer(new Student("wangwu",19));System.out.println(priorityQueue2);//按照年龄进行大根堆构建}
}

我们也可以使用lambda表达式代替比较器.其中lambda表达式中,括号中的两个参数表示的是优先级队列中的两个对象,箭头后面表示的是比较的规则.

public class Student{public String name;public int age;@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}public Student(String name, int age) {this.name = name;this.age = age;}
}
public class Main {public static void main(String[] args) {PriorityQueue<Student> priorityQueue2 = new PriorityQueue<>((s1,s2) -> s2.age-s1.age);//由于Student没有默认创建比较方法,所以必须传入比较器对象,否者异常priorityQueue2.offer(new Student("zhangsan",12));priorityQueue2.offer(new Student("lisi",17));priorityQueue2.offer(new Student("wangwu",19));System.out.println(priorityQueue2);//按照年龄进行大根堆构建}
}

也可以不传入比较器,在类中实现Comparable接口,让这个对象变成一个可比较的对象,并重写其中的compareTo方法:

public class Student implements Comparable<Student>{public String name;public int age;@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic int compareTo(Student o) {return this.name.compareTo(o.name);}
}
public class Main {public static void main(String[] args) {PriorityQueue<Student> priorityQueue3 = new PriorityQueue<>();priorityQueue3.offer(new Student("zhang",12));priorityQueue3.offer(new Student("li",15));priorityQueue3.offer(new Student("wang",17));System.out.println(priorityQueue3);}
}
  1. 插入,删除,获取优先级队列中的方法
函数名功能介绍
boolean offer(E e)插入元素e,插入成功返回true,如果e对象为空,抛出NullPointerException异常,时间复杂度 ,注意:空间不够时候会进行扩容
E peek()获取优先级最高的元素,如果优先级队列为空,返回null
E poll()移除优先级最高的元素并返回,如果优先级队列为空,返回null
int size()获取有效元素的个数
void clear()清空
boolean isEmpty()检测优先级队列是否为空,空返回true
  1. 优先级队列的扩容
    jdk17 的源码如下:
public boolean offer(E e) {if (e == null)throw new NullPointerException();modCount++;int i = size;if (i >= queue.length)grow(i + 1);//大于队列大小的时候,进行扩容siftUp(i, e);size = i + 1;return true;}
private void grow(int minCapacity) {int oldCapacity = queue.length;// Double size if small; else grow by 50%int newCapacity = ArraysSupport.newLength(oldCapacity,minCapacity - oldCapacity, /* minimum growth */oldCapacity < 64 ? oldCapacity + 2 : oldCapacity >> 1/* preferred growth */);queue = Arrays.copyOf(queue, newCapacity);}

优先级队列的扩容说明:

  • 容量小于64的时候,按照2倍扩容.
  • 容量大于64的时候,按照1.5倍扩容.

4. top-k问题

这种算法一般适用于数据比较大的情况下,比如要在1亿,甚至10亿数据中找出前k的数据.
OJ链接
在这里插入图片描述
这里在寻找top-k元素的时候为什么要创建大根堆呢,因为在元素与对顶元素比较的时候,比较的是大根堆中最大的元素,如果说这个元素比大根堆中最大的元素小的话,那么就会替换掉大根堆中最大的元素,每次删除的时候都删除的是堆中最大的元素, 最终保证大根堆中都是比较小的元素, 最终堆顶就是k个元素中最大的元素,即第k小的元素.

class BigComparator implements Comparator<Integer> {@Overridepublic int compare(Integer o1, Integer o2) {return o2-o1;//通过比较器来创建大根堆}
}
public class Top_k {public int[] smallestK(int[] arr, int k) {if (k <= 0){;return new int[0];//如果k==0,返回空数组}PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(new BigComparator());//先取前k个元素放入for (int i = 0; i < k; i++) {priorityQueue.offer(arr[i]);}//如果堆顶元素大于遍历到的元素,删除堆顶元素,让遍历到的元素进来for (int i = k; i < arr.length; i++) {if (priorityQueue.peek() > arr[i]){priorityQueue.poll();priorityQueue.offer(arr[i]);}}int[] array = new int[k];//使用数组取出前k个元素for (int i = 0; i < k; i++) {array[i] = priorityQueue.poll();}return array;}
}

当然我们在每次入队列的时候也可以不与堆顶元素进行比较,直接让元素入队列,只需要保证每次队列中的元素是k个即可.如果队列中的元素个数超过了k个,就把堆顶元素弹出.
这种情况一般用于arr.length < k的情况,如果是上面的代码去跑arr.length < k的情况,会报出数组越界异常.

class Solution {public int[] smallestK(int[] arr, int k) {PriorityQueue<Integer> q = new PriorityQueue<>((x,y)->y-x);int[] ret = new int[k];for (int i = 0;i < arr.length;i++){q.offer(arr[i]);if (q.size() > k){q.poll();}}for (int i = 0;i < k;i++){ret[i] = q.poll();}return ret;}
}

其实这种做法和上面那种做法本质上是一样的,如果入了一个比堆顶元素大的元素,那么优先级队列在重新调整的时候,这个元素依然会把这个元素调整到堆顶,堆顶还是会被弹出,相当于这个元素没有进来过,如果小于堆顶元素,那么调整后的堆顶元素就不是这个元素,下一次出去的元素也不是这个元素,就相当于这个元素进入了队列.

相关文章:

[Collection与数据结构] PriorityQueue与堆

1. 优先级队列 1.1 概念 前面介绍过队列&#xff0c;队列是一种先进先出(FIFO)的数据结构&#xff0c;但有些情况下&#xff0c;操作的数据可能带有优先级&#xff0c;一般出队列时&#xff0c;可能需要优先级高的元素先出队列&#xff0c;该中场景下&#xff0c;使用队列显然…...

C#调用OpenCvSharp实现图像的开运算和闭运算

对图像同时进行腐蚀和膨胀操作&#xff0c;顺序不同则效果也不同。先腐蚀后膨胀为开运算&#xff0c;能够消除小斑点和细小的突出物、平滑图像以及改善边缘&#xff1b;先膨胀后腐蚀为闭运算&#xff0c;能够去除噪点、填补图像孔洞、连接邻近物体和平滑物体边界。   OpenCvS…...

okhttp断点续传

使用 OkHttp 实现断点续传&#xff0c;关键是通过设置 Range 请求头向服务器请求文件的部分内容。下面是详细的实现步骤和示例代码。 步骤 获取文件的总大小&#xff1a;在开始下载前&#xff0c;通常需要知道文件的总大小&#xff0c;可以通过发送一个初始请求来获取。记录已…...

异步 HTTP 请求

fetch 是一个用于进行异步 HTTP 请求的 JavaScript API。 fetch 基本用法 // 使用 fetch 进行 GET 请求 fetch(https://api.example.com/data).then(response > {// 检查响应是否成功if (!response.ok) {throw new Error(Network response was not ok);}// 解析响应数据为…...

仿射密码实验——Python实现(完整解析版)

文章目录 前言实验内容实验操作步骤1.编写主程序2.编写加密模块3.编写解密模块4.编写文件加解密模块 实验结果实验心得实验源码scirpt.pyusefile.py 前言 实验目的 1&#xff09;初步了解古典密码 2&#xff09;掌握仿射密码的实现 实验方法 根据下图仿射密码&#xff08;变换…...

Ubuntu安装K8S

第一步&#xff1a; 安装docker Install Docker #注意docker是早期的名称已经过时了&#xff0c;因此请使用如下命令&#xff0c;一步到位安装docker-ce。 第二步&#xff1a;设置K8S源&#xff1a; &#xff08;大陆使用aliyun源&#xff0c;大陆外使用google源&#xff09;…...

C语言初阶习题【29】杨氏矩阵

1. 题目描述——杨氏矩阵 有一个数字矩阵&#xff0c;矩阵的每行从左到右是递增的&#xff0c;矩阵从上到下是递增的&#xff0c;请编写程序在这样的矩阵中查找某个数字是否存在。 要求&#xff1a;时间复杂度小于O(N); 2. 思路 3. 代码实现1 #include<stdio.h>void fin…...

(01)FreeRTOS移植到STM32

一、以STM32的裸机工程模板 任意模板即可 二、去官网上下载FreeRTOS V9.0.0 源码 在移植之前&#xff0c;我们首先要获取到 FreeRTOS 的官方的源码包。这里我们提供两个下载 链 接 &#xff0c; 一 个 是 官 网 &#xff1a; http://www.freertos.org/ &#xff0c; 另…...

从AI生成内容到虚拟现实:娱乐体验的新边界

引言 在快速发展的科技时代&#xff0c;娱乐行业正经历一场前所未有的变革。传统的娱乐方式正与先进技术融合&#xff0c;创造出全新的沉浸式体验。从AI生成的个性化内容&#xff0c;到虚拟现实带来的身临其境的互动场景&#xff0c;科技不仅改变了我们消费娱乐的方式&#xf…...

买入的股票

银行12 工商&#xff0c;建设&#xff0c;农业&#xff0c;中国&#xff0c;招商&#xff0c;交通&#xff0c;邮储&#xff0c;中信&#xff0c;兴业&#xff0c;浦发&#xff0c;平安&#xff0c;光大 保险4&#xff1a;人寿&#xff0c;平安&#xff0c;太平洋&#xff0c…...

Springboot Redisson 分布式锁、缓存、消息队列、布隆过滤器

redisson-spring-boot-starter 是 Redisson 提供的 Spring Boot 集成包&#xff0c;旨在简化与 Redis 的交互&#xff0c;包括分布式锁、缓存、消息队列、布隆过滤器等功能的实现。 Maven 依赖 在 Spring Boot 项目中添加 redisson-spring-boot-starter 依赖&#xff1a; <…...

如何在 Rocky Linux 上安装极狐GitLab?

本文分享如何在 Rocky Linux 操作系统上安装极狐GitLab。 相关资料 极狐GitLab 在各种操作系统下的安装指南官网文档 前提条件 一个安装了 Rocky Linux 操作系统的云服务器 可以查看 /etc/os-release 中的信息&#xff0c;确认操作系统信息&#xff1a; NAME"Rocky …...

50.【8】BUUCTF WEB HardSql

进入靶场 随便输输 上order by ????????&#xff0c;被过滤了,继续找其他也被过滤的关键字 #&#xff0c;-- -&#xff0c;-- 都不行&#xff0c;尝试其他特殊字符后发现and&#xff0c;union&#xff0c;select&#xff0c;空格&#xff0c;都被过滤了 如下 我就不知…...

Shell的运行原理以及Linux中的权限问题

Shell的运行原理 Linux严格意义上说的是一个操作系统&#xff0c;我们称之为“核心&#xff08;kernel&#xff09;“ &#xff0c;但我们一般用户&#xff0c;不能直接使用kernel。 而是通过kernel的“外壳”程序&#xff0c;也就是所谓的shell&#xff0c;来与kernel沟通。如…...

Maven在Win10上的安装教程

诸神缄默不语-个人CSDN博文目录 这个文件可以跟我要&#xff0c;也可以从官网下载&#xff1a; 第一步&#xff1a;解压文件 第二步&#xff1a;设置环境变量 在系统变量处点击新建&#xff0c;输入变量名MAVEN_HOME&#xff0c;变量值为解压路径&#xff1a; 在系统变…...

服务器数据恢复—EMC存储POOL中数据卷被删除的数据恢复案例

服务器数据恢复环境&故障&#xff1a; EMC Unity 400存储连接了2台硬盘柜。2台硬盘柜上一共有21块硬盘&#xff08;520字节&#xff09;。21块盘组建了2组RAID6&#xff1a;一组有11块硬盘&#xff0c;一组有10块硬盘。 在存储运行过程中&#xff0c;管理员误操作删除了 2组…...

Go语言之路————func

Go语言之路————func 前言1.最基本的方法定义2.方法中参数的传递3.方法中的返回值4.匿名方法5.闭包的概念6.defer关键词 前言 我是一名多年Java开发人员&#xff0c;因为工作需要现在要学习go语言&#xff0c;Go语言之路是一个系列&#xff0c;记录着我从0开始接触Go&#…...

基于 Electron 应用的安全测试基础 — 提取和分析 .asar 文件

视频教程在我主页简介或专栏里 目录&#xff1a; 提取和分析 .asar 文件 4.1. .asar 文件提取工具 4.1.1. 为什么选择 NPX&#xff1f; 4.2. 提取过程 4.3. 提取 .asar 文件的重要性 4.3.1 关键词 4.3.2 执行关键词搜索 4.3.2.1 使用命令行工具“grep”进行关键词搜索 4.3.2…...

微软与腾讯技术交锋,TRELLIS引领3D生成领域多格式支持新方向

去年 11 月&#xff0c;腾讯推出 Hunyuan3D 生成模型&#xff0c;是业界首个同时支持文字和图像生成 3D 的开源大模型。紧接着不到一个月&#xff0c;微软便发布了全新框架 TRELLIS&#xff0c;加入 3D 资产生成领域的竞争中。TRELLIS 支持多格式输出&#xff0c;包括辐射场、3…...

ubuntu18.04开发环境下samba服务器的搭建

嵌入式linux的发展很快&#xff0c;最近准备在一个新项目上采用新一代的linux核心板&#xff0c;发现linux内核的版本已经更新到5.4以上甚至6.0以上&#xff1b;之前常用的linux内核版本是2.6.4&#xff0c;虽然在某些项目上还能用但是明显跟不上时代的步伐了&#xff0c;所以要…...

LabVIEW实现油浸式变压器自主监测与实时报告

油浸式变压器广泛应用于电力系统中&#xff0c;尤其是在电力传输和分配领域。为了确保变压器的安全、稳定运行&#xff0c;及时监测其工作状态至关重要。传统的变压器监测方法通常依赖人工巡检和定期检查&#xff0c;但这不能及时发现潜在的故障隐患&#xff0c;且效率较低。随…...

21_Spring Boot缓存注解介绍

前面我们通过使用@EnableCaching、@Cacheable注解实现了Spring Boot默认的基于注解的缓存管理,除此之外,还有更多的缓存注解以及注解属性可以配置优化缓存管理。下面我们针对Spring Boot中的缓存注解及相关属性进行详细讲解。 1.@EnableCaching注解 @EnableCaching是由Spri…...

Linux和Docker常用终端命令:保姆级图文详解

文章目录 前言1、Docker 常用命令1.1、镜像管理1.2、容器管理1.3、网络管理1.4、数据卷管理1.5、监控和性能管理 2、Linux 常用命令分类2.1、文件和目录管理2.2、用户管理2.3、系统监控和性能2.4、软件包管理2.5、网络管理 前言 亲爱的家人们&#xff0c;创作很不容易&#xf…...

【WRF理论第九期】输出文件:wrfout 和 wrfrst

【WRF理论第九期】输出文件:wrfout 和 wrfrst 1. wrfout 文件wrfout 文件读取(Python)2. wrfrst 文件参考在 WRF(Weather Research and Forecasting)模型中,wrfout 和 wrfrst 是两种重要的输出文件,分别代表不同类型的模拟结果和功能。 1. wrfout 文件 wrfout 文件是 …...

学习threejs,使用OrbitControls相机控制器

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.OrbitControls 相机控…...

CryptoMamba:利用状态空间模型实现精确的比特币价格预测

“CryptoMamba: Leveraging State Space Models for Accurate Bitcoin Price Prediction” 论文地址&#xff1a;https://arxiv.org/pdf/2501.01010 Github地址&#xff1a;https://github.com/MShahabSepehri/CryptoMamba 摘要 预测比特币价格由于市场的高波动性和复杂的非线…...

RocketMQ 知识速览

文章目录 一、消息队列对比二、RocketMQ 基础1. 消息模型2. 技术架构3. 消息类型4. 消费者类型5. 消费者分组和生产者分组 三、RocketMQ 高级1. 如何解决顺序消费和重复消费2. 如何实现分布式事务3. 如何解决消息堆积问题4. 如何保证高性能读写5. 刷盘机制 &#xff08;topic 模…...

uniapp button 去除边框

在找去除边框的办法时试了好久 css里设置了 border: none; /* 去掉边框 */outline: none; /* 确保点击时不出现轮廓 */压根不行&#xff0c;按钮还是浮在页面上有明显轮廓 最后看到了大佬的文章 https://www.cnblogs.com/menxiaojin/p/13752916.html button::after{border: no…...

基于mybatis、bootstarp、的maven新人练手学生管理studentManage项目

分析&#xff1a;如果能注册并且登录&#xff0c;那每个人都是管理员&#xff0c;任何人都可以对数据恶意操作&#xff0c;这样数据极其不安全。为了数据的安全考虑&#xff0c; 要么创建学生注册页面&#xff0c;但是主页面只能显示本人信息&#xff0c;不能对其他人进行操作&…...

Visual Studio Community 2022(VS2022)安装方法

废话不多说直接上图&#xff1a; 直接上步骤&#xff1a; 1&#xff0c;首先可以下载安装一个Visual Studio安装器&#xff0c;叫做Visual Studio installer。这个安装文件很小&#xff0c;很快就安装完成了。 2&#xff0c;打开Visual Studio installer 小软件 3&#xff0c…...

.NET 9.0 的 Blazor Web App 项目中 Hash 变换(MD5、Pbkdf2) 使用备忘

一、生成 string 对应的 MD5 码 /// <summary>/// 生成 string 对应的 MD5 码/// </summary>/// <param name"s">需要转换的字符串 string<br/>/// 如果用于远程第三方认证&#xff0c;s username DateTime.Now.Ticks.ToString() 线下传递…...

【Unity-Game4Automation PRO 插件】

Game4Automation PRO 插件 是一个用于 Unity 引擎 的工业自动化仿真工具&#xff0c;它提供了对工业自动化领域的仿真和虚拟调试支持&#xff0c;特别是在与工业机器人、生产线、PLC 系统的集成方面。该插件旨在将工业自动化的实时仿真与游戏开发的高质量 3D 可视化能力结合起来…...

Js:正则表达式及其方法

一、正则表达式的介绍&#xff1a; 1、含义&#xff1a; 正则表达式用来定义一个规则&#xff0c;是Js中的一个对象。 2、作用&#xff1a; ① 计算机可以检查一个字符串是否符合规则 ② 将字符串中符合规则的内容进行提取 二、正则表达式的创建&#xff1a; 1、 通过构造…...

Webpack和Vite的区别

一、构建速度方面 webpack默认是将所有模块都统一打包成一个js文件&#xff0c;每次修改都会重写构建整个项目&#xff0c;自上而下串行执行&#xff0c;所以会随着项目规模的增大&#xff0c;导致其构建打包速度会越来越慢 vite只会对修改过的模块进行重构&#xff0c;构建速…...

获取当前页面的url相关信息

引言&#xff1a;如何通过javascript获取当前html页面的链接信息 let currentUrl window.location.href; let protocol window.location.protocol; // 协议 let host window.location.host; // 主机名和端口 let hostname window.location.hostname; // 主机名 le…...

iOS面试模版

iOS基础面试题&#xff1a;iOS基础知识| ProcessOn免费在线作图,在线流程图,在线思维导图 iOS高级面试题&#xff1a;https://juejin.cn/post/6844903752835530765 先自我介绍&#xff0c;看有无亮点&#xff0c;了解一下做过的项目类型 了解技术栈&#xff08;oc、swift、sw…...

大模型相关资料、基础技术和排行榜

大模型排行榜 测试集CEval中文多个学科测试集排名MMLU大规模多任务语言理解英文排名&#xff0c;介绍斯坦福排行榜Math-VMath-VistaOpen LLMs LeaderboardCMMLU 大模型数据集 标题简介19个大模型常用的评估数据集和训练数据集汇总19个大模型常用的评估数据集和训练数据集汇总最…...

RDD和DataFrame两种数据结构的对比

文章目录 1. 实战概述2. RDD&#xff08;弹性分布式数据集&#xff09;2.1 RDD概念2.2 RDD特点2.3 实战操作 3. DataFrame&#xff08;数据帧&#xff09;3.1 DataFrame概念3.2 DataFrame优点3.3 实战操作 4. 实战小结 1. 实战概述 今天我们将深入探讨 Apache Spark 中的两种核…...

10.Linux 时间

文章目录 10.1 日历时间&#xff08;Calendar Time&#xff09;1. **日历时间的表示**2. **系统调用 gettimeofday()**3. **系统调用 time()**4. **time() 与 gettimeofday() 的关系** 总结 10.2 时间转换函数1. **ctime() 示例**2. **asctime() 示例**3. **strftime() 示例**4…...

Java最常用的几种设计模式详解及适用业务场景

Java设计模式详解及适用业务场景 在软件开发中&#xff0c;设计模式是解决常见问题的最佳实践。通过采用这些设计模式&#xff0c;我们可以提高代码的可维护性、可读性和可扩展性。本文将介绍几种常见的Java设计模式&#xff0c;并结合具体代码示例&#xff0c;探讨它们适用的…...

运行fastGPT 第二步 安装宝塔面板 用于管理安装docker和其文件

if [ -f /usr/bin/curl ];then curl -sSO https://download.bt.cn/install/install_panel.sh;else wget -O install_panel.sh https://download.bt.cn/install/install_panel.sh;fi;bash install_panel.sh ed8484bec 上面运行以下&#xff0c;安装宝塔。如果不行&#xff0c;系…...

深度学习电影推荐-CNN算法

文章目录 前言视频演示效果1.数据集环境配置安装教程与资源说明1.1 ML-1M 数据集概述1.1.1数据集内容1.1.2. 数据集规模1.1.3. 数据特点1.1.4. 文件格式1.1.5. 应用场景 2.模型架构3.推荐实现3.1 用户数据3.2 电影数据3.3 评分数据3.4 数据预处理3.5实现数据预处理3.6 加载数据…...

CSS3的aria-hidden学习

前言 aria-hidden 属性可用于隐藏非交互内容&#xff0c;使其在无障碍 API 中不可见。即当aria-hidden"true" 添加到一个元素会将该元素及其所有子元素从无障碍树中移除&#xff0c;这可以通过隐藏来改善辅助技术用户的体验&#xff1a; 纯装饰性内容&#xff0c;如…...

如何在前端给视频进行去除绿幕并替换背景?-----Vue3!!

最近在做这个这项目奇店桶装水小程序V1.3.9安装包骑手端V2.0.1小程序前端 最近&#xff0c;我在进行前端开发时&#xff0c;遇到了一个难题“如何给前端的视频进行去除绿幕并替换背景”。这是一个“数字人项目”所需&#xff0c;我一直在冥思苦想。终于有了一个解决方法…...

【Linux】进程间通信IPC

目录 进程间通信 IPC 1. 进程间通信方式 2. 无名管道 2.1 特点 2.2 函数接口 2.3 注意事项 3. 有名管道 3.1 特点 3.2 函数接口 3.3 注意事项 3.4 有名管道和无名管道的区别 4. 信号 4.1概念 4.2信号的响应方式 4.3 信号种类 4.4 函数接口 4.4.1 信号发送和挂…...

go语言实现UTF8与GB2312内码转换

使用Go语言做个UTF-8转GB2312的代码,输入utf-8编码的文本&#xff0c;输出转换后的国标编码的hex内码 package mainimport ("fmt""os""strings""golang.org/x/text/encoding/simplifiedchinese""golang.org/x/text/transform&quo…...

【WPS】【WORDWORD】【JavaScript】实现微软WORD自动更正的效果

1.效果展示 2.核心代码展示 function readTableData(filePath) {let tableData {};let doc Application.Documents.Open(filePath); // 打开文档let table doc.Tables(1); // 获取第一个表格// 遍历表格&#xff0c;存储编号和描述的映射for (let i 1; i < table.Rows.…...

Excel数据叠加生成新DataFrame:操作指南与案例

目录 一、准备工作 二、读取Excel文件 三、数据叠加 四、处理重复数据(可选) 五、保存新DataFrame到Excel文件 六、案例演示 七、注意事项 八、总结 在日常数据处理工作中,我们经常需要将不同Excel文档中的数据整合到一个新的DataFrame中,以便进行进一步的分析和处…...

springBoot项目使用Elasticsearch教程

目录 一、引言&#xff08;一&#xff09;使用背景&#xff08;二&#xff09;版本库区别 二、引入依赖&#xff08;一&#xff09;springboot集成的es依赖&#xff08;建议&#xff09;&#xff08;二&#xff09;es提供的客户端库 三、配置&#xff08;以yaml文件为例&#x…...

摄像头模块在狩猎相机中的应用

摄像头模块是狩猎相机的核心组件&#xff0c;在狩猎相机中发挥着关键作用&#xff0c;以下是其主要应用&#xff1a; 图像与视频拍摄 高清成像&#xff1a;高像素的摄像头模块可确保狩猎相机拍摄出清晰的图像和视频&#xff0c;能够捕捉到动物的毛发纹理、行为细节及周围环境的…...