队列知识及编程练习总结

news2025/1/23 22:39:50

目录

一、背景知识 

二、队列的应用

(一)在Spring中的应用

(二)在其他框架中的应用

(三)在实际开发中的应用

三、相关编程练习

(一)用队列实现栈

(二)使用栈实现队列

(三)设计循环队列

(四)滑动窗口最大值 

(五)课程表

(六)队列的最大值


一、背景知识 

队列是一种常见的数据结构,其特点是先进先出(First-In-First-Out,FIFO),也就是最先入队的元素最先出队。队列可以用来实现任务调度、缓存、消息传递等应用场景。

队列通常有两个基本操作:入队(enqueue)和出队(dequeue)。入队操作将一个元素加入队列的尾部,出队操作将队列头部的元素移除并返回其值。队列还有一个获取队头元素但不移除的操作(peek)。

队列有多种实现方式,包括数组实现和链表实现。数组实现的队列通常需要指定一个固定的容量,而链表实现的队列可以动态增长。

队列还有一些变种,如双端队列(deque)和优先队列(priority queue)。双端队列支持在队头和队尾进行插入和删除操作,优先队列中元素按照一定的优先级顺序出队。

总的来说,队列的基本操作包括:

  1. 入队(enqueue):将一个元素加入队列的尾部。
  2. 出队(dequeue):将队列头部的元素移除并返回其值。
  3. 获取队头元素但不移除(peek):返回队列头部的元素值,但不将其移除。
  4. 判断队列是否为空(isEmpty):如果队列中没有元素则返回 true,否则返回 false。
  5. 判断队列是否已满(isFull):如果队列已满则返回 true,否则返回 false。但是对于链表实现的队列来说,不需要判断队列是否已满,因为链表的长度是动态变化的。(对于数组实现的队列而言才有这个操作)

除了这些基本操作之外,队列的具体实现还可以包括其他的一些操作,例如扩容、缩容等。

按照以上的背景,展示举例:队列的大致流程就像是往管道中一个一个地放入小球,然后小球从管道前头一个个出来。(图来自图灵社区)

二、队列的应用

(一)在Spring中的应用

在 Spring 框架中,队列主要用于异步消息处理,其中的应用包括:

  1. Spring JMS(Java Message Service):Spring JMS 可以使用 JMS 队列实现异步消息处理。消息生产者将消息发送到队列中,消息消费者从队列中获取消息并进行处理。
  2. Spring AMQP(Advanced Message Queuing Protocol):Spring AMQP 是 Spring 对 AMQP 消息协议的支持,可以使用 AMQP 的队列实现异步消息处理。与 JMS 相比,AMQP 具有更强的消息路由和交换机管理能力。
  3. Spring Integration:Spring Integration 提供了丰富的消息通道和消息处理器,可以使用队列实现异步消息处理。
  4. Spring Batch:Spring Batch 是 Spring 提供的批处理框架,其中的 JobLauncher 实现了异步任务处理,使用了内部的任务队列进行任务调度。

总的来说,Spring 框架中队列的应用主要涉及异步消息处理,其背后的思想是将任务分发给多个线程或者处理器,提高任务的处理效率和并发能力

(二)在其他框架中的应用

除了 Spring 框架,队列在其他一些框架中也有广泛的应用,例如:

  1. Apache Kafka:Apache Kafka 是一个分布式消息队列,被广泛用于大规模数据流处理和实时数据管道。它提供高可用、高可靠的消息传输服务,支持多个消费者和分区,同时还具有高性能和可扩展性。
  2. RabbitMQ:RabbitMQ 是一个 AMQP 实现,支持多种消息队列模式,包括点对点、发布/订阅和路由等。它具有高可用、高可靠性和高性能,支持多种客户端语言和多种平台。
  3. Redis:Redis 是一个内存中的数据结构存储系统,可以使用 Redis List 实现队列。它支持数据持久化、集群和复制,同时还支持多种数据结构操作和多种客户端语言。
  4. ActiveMQ:ActiveMQ 是一个开源的 JMS 实现,支持多种消息队列模式,包括点对点、发布/订阅和通配符等。它具有高可用、高可靠性和高性能,同时还支持多种客户端语言和多种平台。

总的来说,队列在分布式系统和大规模数据处理中扮演着重要的角色,被广泛应用于消息传输、任务调度、数据流处理等场景

(三)在实际开发中的应用

在实际开发工作中,队列可以应用于多个场景,例如:

  1. 异步任务处理:当系统需要执行大量耗时的任务时,可以将任务放入队列中,由多个工作者线程异步地处理任务,从而提高系统的并发能力和性能。
  2. 消息队列:当系统需要在多个进程或者机器之间传递消息时,可以使用消息队列。生产者将消息放入队列中,消费者从队列中获取消息并进行处理,从而实现不同进程或者机器之间的异步通信。
  3. 数据流处理:当系统需要处理大规模的数据流时,可以使用队列将数据分配给多个处理节点进行处理。例如,将用户行为日志放入队列中,由多个处理节点进行数据分析和挖掘。
  4. 任务调度:当系统需要执行周期性的任务时,可以使用队列进行任务调度。将任务放入队列中,由任务调度器定时执行任务,并将执行结果返回给系统。
  5. 网络流量控制:当系统需要控制网络流量时,可以使用队列进行流量控制。例如,将网络请求放入队列中,限制同时处理请求的数量,从而避免系统崩溃。

总的来说,队列在实际开发工作中应用广泛,涉及任务调度、消息传输、数据处理等多个场景,可以提高系统的并发能力和性能,提高系统的可靠性和稳定性

三、相关编程练习

(一)用队列实现栈

与栈知识及编程练习总结_张彦峰ZYF的博客-CSDN博客中练习三(五)相同,请直接跳转阅读。

(二)使用栈实现队列

与栈知识及编程练习总结_张彦峰ZYF的博客-CSDN博客中练习三(四)相同,请直接跳转阅读。

(三)设计循环队列

题目描述:设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

你的实现应该支持如下操作:

  • MyCircularQueue(k): 构造器,设置队列长度为 k 。
  • Front: 从队首获取元素。如果队列为空,返回 -1 。
  • Rear: 获取队尾元素。如果队列为空,返回 -1 。
  • enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
  • deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
  • isEmpty(): 检查循环队列是否为空。
  • isFull(): 检查循环队列是否已满。

示例:

MyCircularQueue circularQueue = new MyCircularQueue(3); // 设置长度为 3
circularQueue.enQueue(1);  // 返回 true
circularQueue.enQueue(2);  // 返回 true
circularQueue.enQueue(3);  // 返回 true
circularQueue.enQueue(4);  // 返回 false,队列已满
circularQueue.Rear();  // 返回 3
circularQueue.isFull();  // 返回 true
circularQueue.deQueue();  // 返回 true
circularQueue.enQueue(4);  // 返回 true
circularQueue.Rear();  // 返回 4
 

提示:

  • 所有的值都在 0 至 1000 的范围内;
  • 操作数将在 1 至 1000 的范围内;
  • 请不要使用内置的队列库。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/design-circular-queue

解题思路

比较常见的实现方式,使用一个数组和两个指针 frontrear 分别指向队列的头部和尾部,同时使用一个变量 size 维护队列中元素的个数,在 enQueue()deQueue() 方法中,需要将指针向后移动一位,并使用取模操作保证指针不会越界。在 enQueue() 方法中,还需要注意特殊情况,即当队列为空时,需要将 front 指向插入的元素。

这个实现方式的时间复杂度为O(1)。

 具体代码展示

package org.zyf.javabasic.letcode.queue;

/**
 * @author yanfengzhang
 * @description 设计你的循环队列实现。
 * 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
 * <p>
 * 循环队列的一个好处是我们可以利用这个队列之前用过的空间。
 * 在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。
 * 但是使用循环队列,我们能使用这些空间去存储新的值。
 * @date 2023/4/9  14:58
 */
public class MyCircularQueue {
    /*存储队列元素的数组*/
    private int[] data;
    /*队头指针,指向队头元素*/
    private int front;
    /*队尾指针,指向队尾元素的下一个位置*/
    private int rear;
    /*队列中元素的个数*/
    private int size;

    public MyCircularQueue(int k) {
        /*初始化数组*/
        data = new int[k];
        /*初始时队头指针指向 -1*/
        front = -1;
        /*初始时队尾指针指向 -1*/
        rear = -1;
        /*初始时队列中元素个数为 0*/
        size = 0;
    }

    public boolean enQueue(int value) {
        /*队列已满,插入失败*/
        if (isFull()) {
            return false;
        }
        /*队列为空,需要将 front 指向插入的元素*/
        if (isEmpty()) {
            front = 0;
        }
        /*队尾指针向后移动一位,并使用取模操作保证指针不会越界*/
        rear = (rear + 1) % data.length;
        /*在队尾插入元素*/
        data[rear] = value;
        /*队列中元素个数加一*/
        size++;
        /*插入成功*/
        return true;
    }

    public boolean deQueue() {
        /*队列为空,删除失败*/
        if (isEmpty()) {
            return false;
        }
        /*队列中只有一个元素,需要将 front 和 rear 指向 -1*/
        if (front == rear) {
            front = -1;
            rear = -1;
        }
        /*队列中有多个元素,需要将 front 指针向后移动一位*/
        else {
            /*队头指针向后移动一位,并使用取模操作保证指针不会越界*/
            front = (front + 1) % data.length;
        }
        /*队列中元素个数减一*/
        size--;
        /*删除成功*/
        return true;
    }

    public int Front() {
        if (isEmpty()) {
            /*队列为空,返回 -1*/
            return -1;
        }
        /*返回队头元素*/
        return data[front];
    }

    public int Rear() {
        /*队列为空,返回 -1*/
        if (isEmpty()) {
            return -1;
        }
        /*返回队尾元素*/
        return data[rear];
    }

    public boolean isEmpty() {
        /*判断队列是否为空*/
        return size == 0;
    }

    public boolean isFull() {
        /*判断队列是否已满*/
        return size == data.length;
    }

    /**
     * 在该测试代码中,我们创建了一个容量为 3 的循环队列,
     * 然后进行了一系列操作来测试该类的实现是否正确。
     * 最后输出的结果符合预期,说明该循环队列的实现是正确的。
     */
    public static void main(String[] args) {
        /*创建容量为 3 的循环队列*/
        MyCircularQueue circularQueue = new MyCircularQueue(3);
        /*输出 true,队列变为 [1]*/
        System.out.println(circularQueue.enQueue(1));
        /*输出 true,队列变为 [1, 2]*/
        System.out.println(circularQueue.enQueue(2));
        /*输出 true,队列变为 [1, 2, 3]*/
        System.out.println(circularQueue.enQueue(3));
        /*输出 false,队列已满,插入失败*/
        System.out.println(circularQueue.enQueue(4));
        /*输出 3,队尾元素为 3*/
        System.out.println(circularQueue.Rear());
        /*输出 true,队列已满*/
        System.out.println(circularQueue.isFull());
        /*输出 true,队列变为 [2, 3]*/
        System.out.println(circularQueue.deQueue());
        /*输出 true,队列变为 [2, 3, 4]*/
        System.out.println(circularQueue.enQueue(4));
        /*输出 4,队尾元素为 4*/
        System.out.println(circularQueue.Rear());
    }
}

(四)滑动窗口最大值 

题目描述:给定一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回滑动窗口中的最大值。

示例:输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3       输出: [3,3,5,5,6,7]

解释:滑动窗口的位置 最大值

  • [1 3 -1] -3 5 3 6 7 3
  • 1 [3 -1 -3] 5 3 6 7 3
  • 1 3 [-1 -3 5] 3 6 7 5
  • 1 3 -1 [-3 5 3] 6 7 5
  • 1 3 -1 -3 [5 3 6] 7 6
  • 1 3 -1 -3 5 [3 6 7] 7

提示:你可以假设 k 总是有效的,在输入数组不为空的情况下,1 ≤ k ≤ 输入数组的大小。

进阶:你能在线性时间复杂度内解决此题吗?

解题思路

滑动窗口最大值问题可以使用单调队列来解决,具体思路如下:

  1. 我们使用双端队列 deque,存储数组的下标。deque 中的元素按照从大到小的顺序排列,即 deque 中的第一个元素是滑动窗口中的最大值。
  2. 我们遍历数组,依次将元素放入 deque 中。当元素个数大于 k 时,我们需要将 deque 的第一个元素弹出,因为它不在滑动窗口中了。
  3. 对于新加入 deque 的元素,从队尾开始比较,如果队尾的元素比当前元素小,则说明队尾的元素不可能是滑动窗口中的最大值,将其弹出。直到队尾的元素比当前元素大,或者 deque 为空,我们再将当前元素插入队尾。
  4. 每次队列中的最大值即为 deque 的第一个元素,我们将其存入结果数组中。

由于每个元素最多进 deque 和出 deque 一次,因此时间复杂度为 O(n)。

需要注意的是,deque 中存储的是数组中元素的下标,而不是元素本身。因此在计算 deque 中的最大值时,需要根据下标从原数组中取出对应的元素。

具体代码展示

package org.zyf.javabasic.letcode.queue;

import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;

/**
 * @author yanfengzhang
 * @description 给定一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。
 * 你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
 * 返回滑动窗口中的最大值。
 * @date 2023/4/9  15:23
 */
public class MaxSlidingWindow {

    /**
     * 1 我们使用双端队列 deque,存储数组的下标。deque 中的元素按照从大到小的顺序排列,即 deque 中的第一个元素是滑动窗口中的最大值。
     * 2 我们遍历数组,依次将元素放入 deque 中。当元素个数大于 k 时,我们需要将 deque 的第一个元素弹出,因为它不在滑动窗口中了。
     * 3 对于新加入 deque 的元素,从队尾开始比较,如果队尾的元素比当前元素小,
     * 则说明队尾的元素不可能是滑动窗口中的最大值,将其弹出。
     * 直到队尾的元素比当前元素大,或者 deque 为空,我们再将当前元素插入队尾。
     * 4 每次队列中的最大值即为 deque 的第一个元素,我们将其存入结果数组中。
     */
    public int[] maxSlidingWindow(int[] nums, int k) {
        int n = nums.length;
        if (n == 0) {
            return new int[0];
        }
        if (k == 1) {
            return nums;
        }

        /*双端队列,存储数组下标*/
        Deque<Integer> deque = new LinkedList<>();

        /*初始化队列,从 0 到 k - 1,把队列中比 nums[i] 小的元素全部弹出*/
        for (int i = 0; i < k; i++) {
            while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {
                deque.pollLast();
            }
            deque.offerLast(i);
        }

        int[] ans = new int[n - k + 1];
        ans[0] = nums[deque.peekFirst()];

        /*遍历数组,维护队列中的元素*/
        for (int i = k; i < n; i++) {
            /*判断队首是否在滑动窗口中*/
            if (deque.peekFirst() <= i - k) {
                deque.pollFirst();
            }

            /*把队列中比 nums[i] 小的元素全部弹出*/
            while (!deque.isEmpty() && nums[i] >= nums[deque.peekLast()]) {
                deque.pollLast();
            }

            /*将当前元素插入队尾*/
            deque.offerLast(i);

            ans[i - k + 1] = nums[deque.peekFirst()];
        }

        return ans;
    }

    public static void main(String[] args) {
        int[] nums = {1, 3, -1, -3, 5, 3, 6, 7};
        int k = 3;
        int[] result = new MaxSlidingWindow().maxSlidingWindow(nums, k);
        /*输出:[3, 3, 5, 5, 6, 7]*/
        System.out.println(Arrays.toString(result));

    }
}

(五)课程表

题目描述:你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。

在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程  bi 。

例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。
请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。

 提示:

  • 1 <= numCourses <= 105
  • 0 <= prerequisites.length <= 5000
  • prerequisites[i].length == 2
  • 0 <= ai, bi < numCourses
  • prerequisites[i] 中的所有课程对 互不相同

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/course-schedule

解题思路

该问题可以抽象成一个有向图,课程之间的先修关系可以表示为图中的边。因此,该问题就转化为在有向图中判断是否存在环。若存在环,那么就无法完成所有课程的学习,否则就可以完成。

使用拓扑排序算法可以解决该问题。拓扑排序可以输出图的节点,满足节点的前驱节点已经全部输出。对于本题,我们可以使用拓扑排序来判断有向图中是否存在环。具体做法是,每次选择一个入度为 0 的节点,并移除该节点以及以该节点为起点的所有边,重复这个过程直到图为空,若过程中存在没有入度为 0 的节点的情况,那么就说明图中存在环。如果最终能够将所有节点输出,那么就说明没有环,可以完成所有课程的学习。

也可以使用队列实现拓扑排序算法。具体实现方法是:

  1. 统计所有节点的入度,将入度为 0 的节点加入队列。
  2. 取出队首节点,输出该节点,并将以该节点为起点的所有边移除,更新它们的入度。如果某个节点入度变为 0,则将该节点加入队列。
  3. 重复第 2 步,直到队列为空或者无法再取出入度为 0 的节点。

如果最终能够输出所有节点,说明不存在环;否则,说明存在环。

具体代码展示

package org.zyf.javabasic.letcode.queue;

import java.util.LinkedList;
import java.util.Queue;

/**
 * @author yanfengzhang
 * @description 你这个学期必须选修 numCourses 门课程,记为0到numCourses - 1 。
 * 在选修某些课程之前需要一些先修课程。
 * 先修课程按数组prerequisites 给出,其中prerequisites[i] = [ai, bi] ,表示如果要学习课程ai 则 必须 先学习课程bi 。
 * <p>
 * 例如,先修课程对[0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。
 * 请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。
 * @date 2023/4/9  15:55
 */
public class CanFinishCourses {

    /**
     * 使用队列实现拓扑排序算法。具体实现方法是:
     * 统计所有节点的入度,将入度为 0 的节点加入队列。
     * 取出队首节点,输出该节点,并将以该节点为起点的所有边移除,更新它们的入度。如果某个节点入度变为 0,则将该节点加入队列。
     * 重复第 2 步,直到队列为空或者无法再取出入度为 0 的节点。
     * 如果最终能够输出所有节点,说明不存在环;否则,说明存在环。
     */
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        /*记录每个节点的入度*/
        int[] inDegree = new int[numCourses];
        for (int[] pre : prerequisites) {
            inDegree[pre[0]]++;
        }

        Queue<Integer> queue = new LinkedList<>();
        /*将入度为 0 的节点加入队列*/
        for (int i = 0; i < numCourses; i++) {
            if (inDegree[i] == 0) {
                queue.offer(i);
            }
        }

        int count = 0;
        /*取出队首节点,输出该节点,并将以该节点为起点的所有边移除,更新它们的入度*/
        while (!queue.isEmpty()) {
            int curr = queue.poll();
            count++;
            for (int[] pre : prerequisites) {
                if (pre[1] == curr) {
                    inDegree[pre[0]]--;
                    if (inDegree[pre[0]] == 0) {
                        queue.offer(pre[0]);
                    }
                }
            }
        }

        /*如果最终能够输出所有节点,说明不存在环;否则,说明存在环*/
        return count == numCourses;
    }
}

(六)队列的最大值

题目描述:请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。

若队列为空,pop_front 和 max_value 需要返回 -1

 限制:

  • 1 <= push_back,pop_front,max_value的总操作数 <= 10000
  • 1 <= value <= 10^5

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/dui-lie-de-zui-da-zhi-lcof

解题思路

可以使用两个队列来实现,一个队列用来存储插入的元素,另一个队列用来存储当前队列中的最大值。

具体实现时,我们可以使用两个 LinkedList 来实现双端队列,一个队列用来存储插入的元素,另一个队列用来存储当前队列中的最大值。

每次插入元素时,先将该元素插入到存储元素的队列中,然后将最大值队列中小于等于该元素的元素全部弹出,保证最大值队列中的元素始终是递减的。然后将该元素插入到最大值队列中。

当需要弹出队首元素时,如果队首元素等于最大值队列中的第一个元素,则同时弹出该元素。

由于每个元素最多只会被弹入和弹出一次,因此总时间复杂度为O(n),均摊时间复杂度为 O(1)。

具体代码展示

package org.zyf.javabasic.letcode.queue;

import java.util.LinkedList;

/**
 * @author yanfengzhang
 * @description 请定义一个队列并实现函数 max_value 得到队列里的最大值,
 * 要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。
 * <p>
 * 若队列为空,pop_front 和 max_value需要返回 -1
 * @date 2023/4/9  16:19
 */
public class MaxQueue {
    /*存储正常数据的队列*/
    private LinkedList<Integer> queue;
    /*存储当前队列中最大值的队列*/
    private LinkedList<Integer> maxQueue;

    public MaxQueue() {
        queue = new LinkedList<>();
        maxQueue = new LinkedList<>();
    }

    public int max_value() {
        if (maxQueue.isEmpty()) {
            return -1;
        }
        /*返回最大值队列的队首元素*/
        return maxQueue.peekFirst();
    }

    public void push_back(int value) {
        /*将元素加入正常队列*/
        queue.offerLast(value);
        while (!maxQueue.isEmpty() && maxQueue.peekLast() < value) {
            /*将小于当前元素的元素从最大值队列中弹出*/
            maxQueue.pollLast();
        }
        /*将当前元素加入最大值队列*/
        maxQueue.offerLast(value);
    }

    public int pop_front() {
        if (queue.isEmpty()) {
            return -1;
        }
        /*弹出正常队列的队首元素*/
        int front = queue.pollFirst();
        if (front == maxQueue.peekFirst()) {
            /*如果该元素是最大值队列的队首元素,则同时弹出*/
            maxQueue.pollFirst();
        }
        return front;
    }

    public static void main(String[] args) {
        MaxQueue q = new MaxQueue();
        /*输出 -1*/
        System.out.println(q.max_value());
        q.push_back(1);
        q.push_back(3);
        q.push_back(2);
        /*输出 3*/
        System.out.println(q.max_value());
        /*输出 1*/
        System.out.println(q.pop_front());
        /*输出 3*/
        System.out.println(q.max_value());
        /*输出 3*/
        System.out.println(q.pop_front());
        /*输出 2*/
        System.out.println(q.max_value());
        /*输出 2*/
        System.out.println(q.pop_front());
        /*输出 -1*/
        System.out.println(q.max_value());
    }

}

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

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

相关文章

【CE】Mac下的CE教程Tutorial:进阶篇(第8关:多级指针)

▒ 目录 ▒&#x1f6eb; 导读开发环境1️⃣ 第8关&#xff1a;多级指针翻译操作验证其它方案&#x1f6ec; 文章小结&#x1f4d6; 参考资料&#x1f6eb; 导读 开发环境 版本号描述文章日期2023-03-操作系统MacOS Big Sur 11.5Cheat Engine7.4.3 1️⃣ 第8关&#xff1a;多…

DCT-Net工业级轻量化人像漫画

工业级轻量AI人像漫画开源模型技术解析_哔哩哔哩_bilibiliModelScope 旨在打造下一代开源的模型即 服务共享平台&#xff0c;为泛 AI 开发者提供灵活、易用、低成本的一站式模型服务产品&#xff0c;让模型应用更简单&#xff01;欢迎使用魔搭社区&#xff1a;ModelScope.cn, 视…

JVM:线上服务CPU爆满,如何排查(三)

0. 引言 前一段时间出现了一个正则表达式引起的线上CPU爆满的问题&#xff0c;一开始没有在第一时间定位到问题&#xff0c;这里也特此记录一下&#xff0c;同时也系统的梳理下CPU爆满问题的排查思路和方法&#xff0c;为后续的同学提供参考。 1. CPU爆满问题产生的原因 我们…

八大排序算法之插入排序、希尔排序、选择排序

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【数据结构初阶&#xff08;C实现&#xff09;】 本篇主要讲解八大排序算法中的三种排序&#xff0c;分别是&#xff1a;插入排序、希尔排…

yum源配置

一、互联网yum源&#xff08;centos7为例&#xff09;: cd /etc/yum.repos.d/ && rm -f *.repo;wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && wget -P /etc/yum.repos.d/ http://mirrors.aliyun.com/repo…

Golang编译报错 ‘invalid char’

现象 最近在新电脑安装go环境&#xff0c;发现 golang 包名如果有汉字就不能编译运行。 具体来讲&#xff0c;就是 go mod tidy 报错 ‘invalid char’ 但是&#xff0c;我在以前的电脑上运行 go mod tidy 没有问题 原因 我对比了 go sdk 版本&#xff0c;旧电脑用 go 1.13…

Html5钢琴块游戏制作(音乐游戏)

当年一款手机节奏音游&#xff0c;相信不少人都玩过或见过。最近也是将其做了出来分享给大家。 游戏的基本玩法&#xff1a;点击下落的黑色方块&#xff0c;弹奏音乐。&#xff08;下落的速度会越来越快&#xff09; 可以进行试玩&#xff0c;手机玩起来效果会更好些。 点击…

Java就业前景如何?

Java还有出路吗&#xff1f;2023年的就业市场依然经历着面临挑战&#xff0c;很多有经验有技术的人被淘汰下来&#xff0c;而马上又有一千多万的新鲜血液涌入就业市场。经济大环境对于各行各业的影响是非常大的&#xff0c;也为IT行业的内卷推波助澜。在2023年想学习Java入行就…

面试造航母,入职拧螺丝,工资...

有粉丝跟我吐槽说&#xff1a;金三银四去面试软件测试岗&#xff0c;真的是面试造航母&#xff0c;入职拧螺丝&#xff0c;工资还低 这种现象很正常&#xff0c;因为找一个测试员&#xff0c;当然希望他能做的业务越多越好&#xff0c;最好像机器猫一样&#xff0c;啥事儿都能…

Chatgpt 实践经验分享

数据准备&#xff1a;ChatGPT 需要大量的训练数据来支撑模型的训练和优化&#xff0c;因此需要进行充分的数据准备。在数据准备方面&#xff0c;需要考虑数据的质量、覆盖范围以及数据的预处理方式等。模型训练&#xff1a;ChatGPT 使用端到端学习的方式训练模型&#xff0c;需…

自动控制原理模拟卷1

自动控制原理模拟题一 Question1 已知机械系统和电网络如下图所示,求解两个系统的传递函数,并证明这两个系统是相似系统. 解: 【图a系统】 由电网络原理图并根据复阻抗原理,可得系统传递函数为: E o ( s ) E i

离线安装k8s/kubernetesv1.17.1

条件&#xff1a; 3台没有网络的centos7.9服务器 1.系统优化 hostnamectl set-hostname k8s-master && bash #只在master节点上执行 hostnamectl set-hostname k8s-node1 && bash #只在node1节点上执行 hostnamectl set-hostname k8s-node2 && …

基于stm32单片机和rt-thread操作系统的智能灯

目 录 一、 总体概况 二、 各部分介绍 2.1 STM32F4开发板 2.2 光敏模块 2.3 麦克风模块 2.4 超声波模块 三、 RT-Thread介绍 四、 开发过程 五、 未来设想 六、 开发心得 总体概况 本次测试技术与信号处理课程作业&#xff0c;我利用了stm32单片机和rt-thread…

SpringBoot中使用WebSocket Demo

大概目录结构 依赖只引入了JSP 和SpringBoot整合WebSocket Spring Web index.jsp <% page contentType"text/html;charsetUTF-8" language"java" %> <!DOCTYPE html> <html> <head><meta charset"utf-8"><s…

STM32开发(十三)STM32F103 片内资源 —— 外部中断 按键 详解

文章目录一、基础知识点二、开发环境三、STM32CubeMX相关配置四、Vscode代码讲解五、结果演示一、基础知识点 外部中断/事件控制器主要特征&#xff1a; 每个中断/事件都有独立的触发和屏蔽每个中断线都有专用的状态位支持多达20个软件的中断/事件请求检测脉冲宽度低于APB2时…

校园一键报警柱的作用

校园一键报警柱是一种用于校园安全的紧急报警系统&#xff0c;可以随时随地向校园安全管理部门发送紧急警报。这种系统通常采用带有紧急按钮的电缆或无线警报装置&#xff0c;使学生、教师和工作人员可以在出现紧急情况时轻松报告安全问题&#xff0c;迅速地通知校园安全人员&a…

彻底理解java中泛型

一、什么是泛型&#xff1f; 泛型是JDK5引入的一种特性&#xff0c;是一种类型安全检测机制&#xff0c;开发者在编译阶段发现类型相关的报错。 泛型即参数类型化&#xff0c;将操作的数据类型定义为参数&#xff0c;可定义在类、接口、方法中。 可以把类型参数看作是使用参数化…

CorelDRAW2023中文版矢量制图及设计软件更新发布

矢量制图及设计软件&#xff0c;CorelDRAW Graphics Suite 2023中文版&#xff08;以下简称CorelDRAW 2023&#xff09;对新手来说&#xff0c;对于自己多久才能学会cdr软件这个问题是比较关心的。如果你的学习能力比较强&#xff0c;一周时间是有可能完全学会cdr的。但由于每个…

您可以找到的 5 种最佳数据恢复软件

数据恢复软件对很多人来说是一个非常有价值的工具。无论您是否意识到&#xff0c;宝贵的数据都有被删除的风险&#xff0c;而且很多人直到丢失数据才知道数据的价值。 5 种数据恢复软件 如果发生这种情况&#xff0c;您需要最好的软件来恢复数据并确保这种情况不会再次发生。这…

PostgreSQL 函数(一) 数学函数和字符串函数

1.数学函数 1.1.符号函数sign 用于判断正负 1.2.求余函数mod 1.3.圆周率函数pi 1.4.平方根函数sqrt 1.5.向上取整函数ceil和ceiling 1.6.向下取整函数floor 1.7.绝对值函数abs 1.8.四舍五入函数round 第2位参数为保留位数 1.9.其他函数 正弦函数sin, 反正弦函数asin, 余弦…