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

【C# 数据结构】队列 FIFO

目录

  • 队列的概念
  • FIFO (First-In, First-Out)
      • `Queue<T>` 的工作原理:
      • 示例:
        • 解释:
      • 小结:
  • 环形队列
      • 1. **FIFO?**
      • 2. **环形缓冲队列如何实现FIFO?**
        • 关键概念:
      • 3. **环形缓冲队列的工作过程**
        • 假设:
        • 操作步骤:
      • 4. **具体例子**
        • 初始状态:
        • 操作1:入队数据 `A`
        • 操作2:入队数据 `B`
        • 操作3:出队
        • 操作4:入队数据 `C`, `D`, `E`
        • 操作5:出队
        • 操作6:入队数据 `F`
        • 操作7:出队
      • 5. **环形缓冲队列的FIFO特性**
      • 6. **环形缓冲队列的FIFO优势**
      • 7. **小结**
  • C# 如何通过代码实现环状队列?
      • 1. **使用 `Queue<T>` 实现环形缓冲队列**
      • 使用示例:
      • 说明:
      • 2. **使用固定大小数组实现环形缓冲队列**
      • 使用示例:
      • 说明:
      • 小结
  • 队列和环状队列的对比
      • 1. **环形缓冲队列是FIFO的一种实现**
      • 2. **环形缓冲队列的特点**
      • 3. **环形缓冲队列 vs 其他FIFO实现**
      • 4. **环形缓冲队列的局限性**
      • 5. **小结**
  • 线程安全问题
      • Queue<T> 如果一个线程只负责写,一个线程只负责读会有问题吗?
      • 问题原因:
      • 一些潜在的风险:
      • 如何解决?
        • 1. 使用锁 (`lock`)
        • 2. 使用 `ConcurrentQueue<T>`
      • 总结:

队列的概念

队列和FIFO是什么关系?队列是一种数据结构。
FIFO是队列需要遵循的基本原则:First-In, First-Out。或者说FIFO是队列的基本特性!
C#中有个类叫做Queue,就是实现了队列这种数据结构的类,它遵循FIFO这个原则。

FIFO (First-In, First-Out)

FIFO(First In First Out,先进先出)是一种数据管理原则,就像排队一样:

  • 先进入队列的数据先被处理
  • 后进入队列的数据后被处理

在 FIFO 队列中,第一个进入队列的元素将是第一个被移除的元素。换句话说,队列中的元素按照它们被加入的顺序排列,最早加入的元素最先被取出。

Queue<T> 的工作原理:

  • 入队 (Enqueue):新元素被添加到队列的尾部。
  • 出队 (Dequeue):最早加入队列的元素从队列的头部移除,并返回该元素。

示例:

假设我们使用一个容量为 3 的队列,依次加入元素 123,然后进行 Dequeue() 操作:

Queue<int> queue = new Queue<int>();// 入队操作
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);// 出队操作,按照 FIFO 顺序返回
Console.WriteLine(queue.Dequeue()); // 输出 1
Console.WriteLine(queue.Dequeue()); // 输出 2
Console.WriteLine(queue.Dequeue()); // 输出 3
解释:
  • Enqueue(1)1 加入队列的尾部。
  • Enqueue(2)2 加入队列的尾部。
  • Enqueue(3)3 加入队列的尾部。
  • Dequeue() 返回并移除队列的头部元素,即最早加入的 1,然后是 23,遵循 FIFO 的顺序。

小结:

通过Queue<T> 的使用我们可以很好的理解 FIFO ,其中元素按照加入的顺序进行排队,最早加入的元素最先被取出。这使得它特别适用于处理排队和任务调度等场景。

环形队列


1. FIFO?

环状队列也是队列的一种,当然也遵循FIFO这个原则!

2. 环形缓冲队列如何实现FIFO?

环形缓冲队列是一种用固定大小的数组实现FIFO的方式。它通过两个指针(头指针和尾指针)来管理数据的入队和出队。

关键概念:
  • 固定大小的数组:预分配一块连续的内存空间。
  • 头指针(head):指向下一个数据写入的位置。
  • 尾指针(tail):指向下一个数据读取的位置。
  • 循环利用:当指针到达数组末尾时,会回到数组开头,形成一个“环”。

3. 环形缓冲队列的工作过程

让我们通过一个具体的例子来说明。

假设:
  • 环形缓冲队列的容量为 5(即数组大小为5)。
  • 初始状态:队列为空,headtail 都指向位置 0
操作步骤:
  1. 入队(Enqueue)

    • 将数据写入 head 指向的位置。
    • 然后 head 向前移动一位。
    • 如果 head 到达数组末尾,它会回到数组开头(循环特性)。
  2. 出队(Dequeue)

    • tail 指向的位置读取数据。
    • 然后 tail 向前移动一位。
    • 如果 tail 到达数组末尾,它会回到数组开头。

4. 具体例子

初始状态:
数组索引: [0]  [1]  [2]  [3]  [4]
值:      None None None None None
head = 0, tail = 0
操作1:入队数据 A
  • A 写入 head 指向的位置(索引 0)。
  • head 移动到下一个位置(索引 1)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       A    None None None None
head = 1, tail = 0
操作2:入队数据 B
  • B 写入 head 指向的位置(索引 1)。
  • head 移动到下一个位置(索引 2)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       A     B    None None None
head = 2, tail = 0
操作3:出队
  • tail 指向的位置(索引 0)读取数据 A
  • tail 移动到下一个位置(索引 1)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       A     B    None None None
head = 2, tail = 1
操作4:入队数据 C, D, E
  • 依次将 C, D, E 写入 head 指向的位置。
  • head 移动到下一个位置。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       A     B     C     D     E
head = 0, tail = 1
操作5:出队
  • tail 指向的位置(索引 1)读取数据 B
  • tail 移动到下一个位置(索引 2)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       A     B     C     D     E
head = 0, tail = 2
操作6:入队数据 F
  • F 写入 head 指向的位置(索引 0)。
  • head 移动到下一个位置(索引 1)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       F     B     C     D     E
head = 1, tail = 2
操作7:出队
  • tail 指向的位置(索引 2)读取数据 C
  • tail 移动到下一个位置(索引 3)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       F     B     C     D     E
head = 1, tail = 3

5. 环形缓冲队列的FIFO特性

  • 数据顺序:先入队的数据(如 A, B)先出队,后入队的数据(如 C, D, E)后出队。
  • 循环利用:当 headtail 到达数组末尾时,会回到数组开头,继续使用之前释放的空间。
  • 固定容量:队列的大小是固定的,当队列满时,可以选择覆盖旧数据或报错。

6. 环形缓冲队列的FIFO优势

  • 高效:入队和出队操作的时间复杂度都是 O(1)。
  • 内存紧凑:数据连续存储,缓存友好。
  • 适合实时系统:适合处理固定大小的数据流。

7. 小结

  • 环形缓冲队列是FIFO的一种实现,它通过固定大小的数组和循环指针来实现先进先出的特性。
  • 数据按顺序入队和出队,先进入队列的数据先被处理。
  • 循环利用使得内存使用更高效,适合处理固定大小的数据流。
    通过理解环状队列你是不是对队列又有了更深的理解呢? 😊

C# 如何通过代码实现环状队列?

之前说到,C# 中有个现成的类实现了队列就是Queue这个类。但是并没有现成的环状队列。

要手动实现环形缓冲队列(Circular Buffer)在 C# 中,可以通过结合 Queue<T> 或者直接使用一个固定大小的数组来模拟环形队列的行为。下面是两种常见的实现方式。

1. 使用 Queue<T> 实现环形缓冲队列

虽然 Queue<T> 本身并不是环形队列,但我们可以通过管理队列的最大容量和覆盖旧数据来模拟环形缓冲队列的行为。当队列满时,新的数据会覆盖最旧的数据。

public class CircularQueue<T>
{private readonly Queue<T> queue;private readonly int capacity;public CircularQueue(int capacity){this.capacity = capacity;this.queue = new Queue<T>(capacity);}// 添加元素,如果队列已满,则移除最旧的元素public void Enqueue(T item){if (queue.Count == capacity){queue.Dequeue(); // 移除最旧的元素}queue.Enqueue(item);}// 从队列中取出元素public T Dequeue(){if (queue.Count == 0){throw new InvalidOperationException("Queue is empty.");}return queue.Dequeue();}// 查看队列中的第一个元素public T Peek(){if (queue.Count == 0){throw new InvalidOperationException("Queue is empty.");}return queue.Peek();}// 判断队列是否为空public bool IsEmpty() => queue.Count == 0;// 队列中的元素个数public int Count => queue.Count;
}

使用示例:

CircularQueue<int> circularQueue = new CircularQueue<int>(3);circularQueue.Enqueue(1);
circularQueue.Enqueue(2);
circularQueue.Enqueue(3);Console.WriteLine(circularQueue.Dequeue()); // 输出 1
circularQueue.Enqueue(4); // 现在队列已满,1 会被覆盖Console.WriteLine(circularQueue.Dequeue()); // 输出 2
Console.WriteLine(circularQueue.Dequeue()); // 输出 3
Console.WriteLine(circularQueue.Dequeue()); // 输出 4

说明:

  • Queue<T> 用于存储数据,最大容量为 capacity
  • 当队列满时(元素数量等于 capacity),通过 Dequeue() 移除最旧的元素,再插入新的元素,模拟环形缓冲的行为。

这种方式依赖于 Queue<T> 来管理队列的基本操作,简单易懂,但不能完全利用环形缓冲队列的内存高效性,尤其是在每次扩展队列容量时仍会引起内存分配。


2. 使用固定大小数组实现环形缓冲队列

这种方法通过手动管理队列的头尾指针和数组来实现环形缓冲区,避免了 Queue<T> 的扩展和额外的内存分配。下面是一个更低层次的实现方式:

public class CircularBuffer<T>
{private readonly T[] buffer;private int head;private int tail;private int size;private readonly int capacity;public CircularBuffer(int capacity){this.capacity = capacity;this.buffer = new T[capacity];this.head = 0;this.tail = 0;this.size = 0;}// 添加元素到队列public void Enqueue(T item){if (size == capacity){// 队列已满,覆盖最旧的数据head = (head + 1) % capacity; // 更新头指针}else{size++;}buffer[tail] = item;tail = (tail + 1) % capacity; // 更新尾指针}// 从队列中取出元素public T Dequeue(){if (size == 0){throw new InvalidOperationException("Queue is empty.");}T value = buffer[head];head = (head + 1) % capacity; // 更新头指针size--;return value;}// 查看队列的第一个元素public T Peek(){if (size == 0){throw new InvalidOperationException("Queue is empty.");}return buffer[head];}// 判断队列是否为空public bool IsEmpty() => size == 0;// 队列中的元素个数public int Count => size;
}

使用示例:

CircularBuffer<int> buffer = new CircularBuffer<int>(3);buffer.Enqueue(1);
buffer.Enqueue(2);
buffer.Enqueue(3);Console.WriteLine(buffer.Dequeue()); // 输出 1
buffer.Enqueue(4); // 1 被覆盖Console.WriteLine(buffer.Dequeue()); // 输出 2
Console.WriteLine(buffer.Dequeue()); // 输出 3
Console.WriteLine(buffer.Dequeue()); // 输出 4

说明:

  • 通过一个固定大小的数组 buffer 存储数据,队列大小为 capacity
  • headtail 指针管理数据的入队和出队。head 指针指向队列的头部(最旧的元素),tail 指针指向队列的尾部(最新的元素)。
  • 当队列满时,新元素会覆盖最旧的数据,head 指针会移动到下一个位置,从而实现环形缓冲队列的覆盖行为。

这种方式比 Queue<T> 更高效,避免了额外的内存分配,适合需要频繁进行入队和出队操作的场景。


小结

  • 使用 Queue<T>:可以通过在队列满时删除最旧元素来模拟环形缓冲队列,适用于简单的场景。
  • 使用固定大小数组:手动管理头尾指针和队列大小,更高效,避免内存分配,适用于性能要求较高的场景。

队列和环状队列的对比


1. 环形缓冲队列是FIFO的一种实现

  • FIFO原则:数据按照到达顺序处理,先进入队列的数据先被取出。
  • 环形缓冲队列:通过固定大小的数组和循环指针实现FIFO,满足先进先出的特性。

2. 环形缓冲队列的特点

  • 固定大小:预分配固定容量的内存,空间利用率高。
  • 循环利用:通过头尾指针循环移动,重复利用数组空间。
  • 高效性能:插入和删除操作的时间复杂度都是O(1)。
  • 内存紧凑:数据连续存储,缓存友好。

3. 环形缓冲队列 vs 其他FIFO实现

特性环形缓冲队列链表实现的FIFO动态数组实现的FIFO
内存分配一次性预分配动态分配节点动态扩容
空间利用率100%较低(每个节点有额外开销)较高(但有扩容开销)
插入/删除性能O(1)O(1)均摊O(1),扩容时O(n)
随机访问不支持不支持支持
适用场景固定大小数据流、实时系统数据量变化大、简单实现需要随机访问的场景

4. 环形缓冲队列的局限性

  • 固定大小:需要预先确定容量,不适合数据量变化大的场景。
  • 不支持随机访问:只能按顺序访问数据。
  • 溢出处理:队列满时需要明确策略(覆盖旧数据或报错)。

5. 小结

  • 环形缓冲队列是FIFO的一种高效实现,特别适合固定大小、高吞吐量的场景。
  • 它通过循环利用预分配的内存,避免了动态内存分配的开销,同时保持了FIFO的特性。
  • 如果需要动态扩容或更灵活的内存管理,可以选择其他FIFO实现(如链表或动态数组)。

线程安全问题


1 多线程访问队列的潜在问题
1.1 竞态条件(Race Condition)
问题描述:多个线程同时修改队列的状态(如 head 和 tail 指针),导致数据不一致。

示例:
线程A和线程B同时执行入队操作。
两者读取相同的 head 指针值,导致数据覆盖或丢失。

1.2 数据不一致
问题描述:一个线程正在修改队列,另一个线程同时读取队列,导致读取到不完整或错误的数据。

示例:

线程A正在入队,更新了 head 指针但还未写入数据。

线程B读取 head 指针,误认为新数据已写入。

1.3 死锁(Deadlock)
问题描述:多个线程互相等待对方释放锁,导致程序无法继续执行。

示例:

线程A持有锁1并等待锁2。

线程B持有锁2并等待锁1。

Queue 如果一个线程只负责写,一个线程只负责读会有问题吗?

如果一个线程 只负责写Enqueue)而另一个线程 只负责读Dequeue),在 不使用锁 或其他线程同步机制的情况下,Queue<T> 仍然 可能会遇到问题,即使你不打算在同一时间内进行读写操作。

问题原因:

  • 队列的内部状态Queue<T> 并没有内建的线程安全机制来保证即使在读写操作不重叠的情况下,两个线程对队列的访问是安全的。
    • 例如,读线程可能会在 写线程 操作队列时,导致内部数据不一致或访问冲突。即使一个线程只负责写,另一个线程只负责读,也可能会出现 竞态条件(race condition)或 内存可见性问题

一些潜在的风险:

  1. 队列大小(Count)的读取:如果 Queue<T> 正在被修改(例如,写线程在 Enqueue),另一个线程试图读取队列大小或进行 Dequeue 操作,可能会得到不一致的结果。因为写线程可能在修改队列时,读线程同时查看到一个不完全或不一致的队列状态。

  2. 数据一致性:尽管读写操作看似是顺序执行的,实际上在多个线程访问共享数据时,现代 CPU 和优化可能导致线程看到过时或不一致的数据(内存可见性问题)。因此,即使操作本身是序列化的,底层的硬件优化仍可能引发问题。

如何解决?

1. 使用锁 (lock)

通过使用 lock 确保 写操作读操作 不会同时进行,这样可以防止数据竞争和不一致性:

public class ThreadSafeQueue<T>
{private readonly Queue<T> queue = new Queue<T>();private readonly object lockObject = new object();public void Enqueue(T item){lock (lockObject){queue.Enqueue(item);}}public T Dequeue(){lock (lockObject){if (queue.Count == 0)throw new InvalidOperationException("Queue is empty.");return queue.Dequeue();}}public int Count{get{lock (lockObject){return queue.Count;}}}
}

在这个示例中,通过 lock 来确保写操作和读操作不会发生竞态条件。

2. 使用 ConcurrentQueue<T>

如果你不希望手动加锁,可以使用 ConcurrentQueue<T>,它是线程安全的,可以在多个线程中同时进行读写操作,保证数据的一致性和正确性:

using System.Collections.Concurrent;var concurrentQueue = new ConcurrentQueue<int>();// 写线程:入队
concurrentQueue.Enqueue(1);
concurrentQueue.Enqueue(2);// 读线程:出队
if (concurrentQueue.TryDequeue(out int result))
{Console.WriteLine(result); // 安全地获取队列元素
}

ConcurrentQueue<T> 会自动管理线程同步,因此你不需要担心加锁的问题,它会确保多线程环境下的正确性。

总结:

  • 即使一个线程只负责写,另一个线程只负责读,Queue<T> 仍然 不保证线程安全,会有潜在的竞态条件和数据不一致问题。
  • 如果需要确保线程安全,可以使用 lock 来同步读写操作,或者使用 ConcurrentQueue<T> 来避免手动管理同步。推荐使用 ConcurrentQueue<T>,因为它是专为多线程设计并且已经实现了高效的线程安全。

相关文章:

【C# 数据结构】队列 FIFO

目录 队列的概念FIFO (First-In, First-Out)Queue<T> 的工作原理&#xff1a;示例&#xff1a;解释&#xff1a; 小结&#xff1a; 环形队列1. **FIFO&#xff1f;**2. **环形缓冲队列如何实现FIFO&#xff1f;**关键概念&#xff1a; 3. **环形缓冲队列的工作过程**假设…...

论文笔记-WWWCompanion2024-LLM as Data Augmenters for Cold-Start Item Recommendation

论文笔记-WWW Companion 2024-Large Language Models as Data Augmenters for Cold-Start Item Recommendation 大语言模型作为冷启动项目推荐的数据增强器摘要1.引言2.前言3.LLMs作为数据增强3.1增强数据生成3.2成对比较损失 4.实验4.1实验设置4.2结果和分析4.3超参数实验 5.总…...

Java 语法新特性(Records、Pattern Matching、Sealed Classes)深度解析(11/17/21)✨

一、Records&#xff08;Java 16&#xff09; &#x1f4dd; 核心价值&#xff1a;简化不可变数据载体的定义 // 传统POJO vs Record public record User(String name, int age) {} // 自动生成&#xff1a;构造方法/equals()/hashCode()/toString() User user new User(&qu…...

QUdpSocket的readyRead信号只触发一次

问题 QUdpSocket的readyRead信号只触发一次。 原因 on_readyRead槽函数里必须读出现有数据后&#xff0c;才能触发新的事件。 解决办法 在on_readyRead槽函数里取出数据。 void MainWindow::on_readyRead() {qDebug() << "on_readyRead in";while (m_udp…...

jsherp importItemExcel接口存在SQL注入

一、漏洞简介 很多人说管伊佳ERP&#xff08;原名&#xff1a;华夏ERP&#xff0c;英文名&#xff1a;jshERP&#xff09;是目前人气领先的国产ERP系统虽然目前只有进销存财务生产的功能&#xff0c;但后面将会推出ERP的全部功能&#xff0c;有兴趣请帮点一下 二、漏洞影响 …...

测试data_management函数

测试data_management函数 这是我最近正在开发的AI工具信息平台的部门功能模块测试&#xff0c;基于streamlit架构。整理出来与大家分享&#xff0c;也为我以后自己回溯找到资源。 为了测试 data_management 函数并结合 Excel 文件中的 “Tools” 表单内容&#xff0c;我们需要…...

微信小程序---计划时钟设计与实现

微信小程序-计划时钟已上线,欢迎各位小伙伴的测试和使用~(微信小程序搜计划时钟即可使用) 在这篇博客中,我们将探讨如何在微信小程序中设计和实现一个任务管理功能,该功能允许用户添加、删除和查看任务。任务管理系统的核心是基于日期和时间的任务管理,可以设置任务的开…...

深度学习之图像回归(二)

前言 这篇文章主要是在图像回归&#xff08;一&#xff09;的基础上对该项目进行的优化。&#xff08;一&#xff09;主要是帮助迅速入门 理清一个深度学习项目的逻辑 这篇文章则主要注重在此基础上对于数据预处理和模型训练进行优化前者会通过涉及PCA主成分分析 特征选择 后…...

深入理解HttpSecurity的设计

一、HttpSecurity的应用 在前章节的介绍中我们讲解了基于配置文件的使用方式,也就是如下的使用。 也就是在配置文件中通过 security:http 等标签来定义了认证需要的相关信息,但是在SpringBoot项目中,我们慢慢脱离了xml配置文件的方式,在SpringSecurity中提供了HttpSecurity…...

15增减字符串匹配(贪心)思路解析+源码

文章目录 题目[](https://leetcode.cn/problems/di-string-match/)算法原理贪心证明源码总结题目 假设s="I D I D"也就是增降增降,在0-4中,每两个数存在这种方式数组为【1, 3,2, 4,0】;(如下图) 算法原理 解法:贪心 1.当遇到“I”:选择当前最小的那个数 2…...

Java NIO与传统IO性能对比分析

Java NIO与传统IO性能对比分析 在Java中&#xff0c;I/O&#xff08;输入输出&#xff09;操作是开发中最常见的任务之一。传统的I/O方式基于阻塞模型&#xff0c;而Java NIO&#xff08;New I/O&#xff09;引入了非阻塞和基于通道&#xff08;Channel&#xff09;和缓冲区&a…...

14.7 LangChain Experimental 模块解析:解锁 Auto-GPT 开发新范式

LangChain Experimental 模块解析:解锁 Auto-GPT 开发新范式 关键词:LangChain Experimental、Auto-GPT 实现、自主智能体开发、Agent 架构设计、实验性功能实践 1. LangChain Experimental 模块的定位与核心能力 模块定位解析: #mermaid-svg-4xz2OlZBUFjkBmqw {font-fami…...

wps中的js开发

严格区分大小写 /*** learn_js Macro*/ function test() {Range(D7).Value2Selection.Value2; // Selection.formula "100" }function Workbook_SheetSelectionChange(Sh, Target) {if(Sh.Name Sheet1) {test();}}function test2() {// 把I4单元格及其周边有数的单…...

day16_推荐系统和总结

文章目录 day16_推荐系统和总结一、推荐实现1、基于流行度推荐&#xff08;掌握&#xff09;1.1 近期热门商品推荐1.2 个人热门商品推荐 2、基于隐语义模型的协同过滤推荐&#xff08;了解&#xff09;2.1 ALS算法介绍2.2 推荐代码 3、基于物品的协同过滤推荐&#xff08;了解&…...

一文说清楚编码、摘要、加密、公钥、私钥、解密、签名、验签

编码 对信息进行编码&#xff0c;没有信息损失&#xff0c;任何人都能通过编码方式对信息进行解码。例如 ASCII 码&#xff0c;base64 编码。 例如下面是 ASCII 编码表&#xff1a; ​ 摘要 对信息计算摘要值&#xff0c;有信息损失&#xff0c;例如 md5 摘要&#xff0c;sh…...

Repeated Sequence

记suma[1]a[2]a[3]...a[n]。 该序列以a[1]&#xff0c;a[2]&#xff0c;a[3]....a[n]为循环节&#xff0c;明显的&#xff0c;问题可转化为:s%sum是否为该序列的某个连续子序列和。 断环为链。将a复制一份。 枚举a[i]为左端点的所有区间的和。再查找s是否存在。二分O&#x…...

CT dicom 去除床板 去除床位,检查床去除

1. 前言 医院拍摄患者CT与MRI 图像&#xff0c; 但是CT图像中就会出现检查床的区域&#xff0c;来看CT扫描设备是什么样子的&#xff0c;红色标出区域 可以在图中看到&#xff0c;在头部位置安装有固定头部的类似支架的东西&#xff0c;这个东西拍摄出来时什么样子呢&#xff…...

react 踩坑记 too many re-renders.

报错信息&#xff1a; too many re-renders. React limits the number of randers to prevent an infinite loop. 需求 tabs只有特定标签页才展示某些按钮 button要用 传递函数引用方式 ()>{} *还有要注意子组件内loading触发 导致的重复渲染...

YOLOv8与BiFormer注意力机制的融合:提升多场景目标检测性能的研究

文章目录 1. YOLOv8的改进背景2. BiFormer注意力机制的核心原理2.1 Bi-level Attention结构2.2 路由策略与加权融合 3. YOLOv8与BiFormer的结合3.1 YOLOv8架构概述3.2 BiFormer与YOLOv8的融合策略 4. 实现代码示例5. 结果分析与实验5.1 数据集与实验设置5.2 实验结果 6. 进一步…...

Ubuntu24.04LTS的下载安装超细图文教程(VMware虚拟机及正常安装)

&#x1f638;个人主页&#x1f449;&#xff1a;神兽汤姆猫 &#x1f4d6;系列专栏&#xff1a;开发语言环境配置 、 Java学习 、Java面试 、Markdown等 学习上的每一次进步&#xff0c;均来自于平时的努力与坚持。 &#x1f495;如果此篇文章对您有帮助的话&#xff0c;请点…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...