C# 队列(Queue)(超详细)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

前言

在编程世界中,队列(Queue)是一种常见的数据结构,它模拟了现实生活中“先进先出”(FIFO, First-In-First-Out)的场景。无论是超市收银台前的排队、操作系统任务调度,还是网络请求的处理,队列都扮演着关键角色。本文将从基础概念出发,结合代码示例和实际场景,深入讲解 C# 队列(Queue) 的实现、特性及应用方法,帮助读者快速掌握这一核心工具。


一、队列的基本概念与类比

1.1 什么是队列?

队列是一种线性数据结构,遵循 先进先出 的原则。想象一个超市的收银台:第一位顾客进入队列,最后一位顾客离开。队列的两个核心操作是:

  • Enqueue:将元素添加到队列的末尾(入队)。
  • Dequeue:从队列的前端移除元素(出队)。

1.2 队列与栈的对比

队列与栈(Stack)类似,但操作方向相反:

  • :遵循“后进先出”(LIFO),类似叠放盘子,取最后一个放进去的。
  • 队列:遵循“先进先出”,类似排队买票,先到者先被服务。

1.3 C# 中的队列实现

C# 提供了 Queue<T> 类(位于 System.Collections.Generic 命名空间),专门用于实现队列功能。此外,.NET 还提供了 ConcurrentQueue<T>,用于多线程环境下的安全操作。


二、Queue 的核心操作与代码示例

2.1 创建与初始化

使用 Queue<T> 需要指定泛型类型,例如:

Queue<int> numberQueue = new Queue<int>();
Queue<string> stringQueue = new Queue<string>();

2.2 基础操作方法

2.2.1 Enqueue(入队)

numberQueue.Enqueue(10);
numberQueue.Enqueue(20);
// 队列内容:[10, 20]

2.2.2 Dequeue(出队)

int firstItem = numberQueue.Dequeue(); // firstItem 的值为 10
// 出队后队列内容:[20]

2.2.3 Peek(查看队首元素)

int frontItem = numberQueue.Peek(); // frontItem 的值为 20
// 队列内容未改变:[20]

2.2.4 Count 属性

int count = numberQueue.Count; // count 的值为 1

2.3 完整示例代码

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        Queue<string> taskQueue = new Queue<string>();
        
        // 入队操作
        taskQueue.Enqueue("处理订单");
        taskQueue.Enqueue("发送邮件");
        taskQueue.Enqueue("生成报告");
        
        Console.WriteLine("当前队列长度:" + taskQueue.Count); // 输出 3
        
        // 出队并处理任务
        while (taskQueue.Count > 0)
        {
            string task = taskQueue.Dequeue();
            Console.WriteLine("正在处理任务:" + task);
        }
    }
}

三、队列的高级特性与应用场景

3.1 扩展操作:ToArray 和 CopyTo

3.1.1 ToArray

将队列内容转换为数组:

string[] tasksArray = taskQueue.ToArray();

3.1.2 CopyTo

将队列内容复制到数组的指定位置:

string[] buffer = new string[taskQueue.Count];
taskQueue.CopyTo(buffer, 0);

3.2 队列的典型应用场景

3.2.1 任务调度

在多线程环境中,队列可用于管理待执行的任务,例如:

Queue<Action> taskQueue = new Queue<Action>();
taskQueue.Enqueue(() => Console.WriteLine("任务1"));
taskQueue.Enqueue(() => Console.WriteLine("任务2"));
// 启动线程逐个执行队列中的任务

3.2.2 缓存与缓冲

在网络编程中,队列可用于缓冲接收到的数据包,避免直接处理大量数据:

Queue<byte[]> dataBuffer = new Queue<byte[]>();
// 接收数据包时 Enqueue,处理时 Dequeue

四、性能与线程安全

4.1 时间复杂度分析

操作平均时间复杂度
EnqueueO(1)
DequeueO(1)
PeekO(1)
ContainsO(n)

4.2 线程安全问题

Queue<T> 是非线程安全的。在多线程环境下,应使用 ConcurrentQueue<T>

ConcurrentQueue<int> safeQueue = new ConcurrentQueue<int>();
safeQueue.Enqueue(100); // 线程安全的入队操作
int dequeuedItem;
bool success = safeQueue.TryDequeue(out dequeuedItem); // 返回是否成功

五、队列的扩展与优化

5.1 自定义队列实现

若需自定义队列行为(例如限制容量),可通过继承 Queue<T> 或手动实现:

public class BoundedQueue<T> : Queue<T>
{
    private readonly int _capacity;
    
    public BoundedQueue(int capacity) => _capacity = capacity;
    
    public new void Enqueue(T item)
    {
        if (Count >= _capacity)
            throw new InvalidOperationException("队列已满");
        base.Enqueue(item);
    }
}

5.2 优先队列(Priority Queue)

虽然 Queue<T> 不直接支持优先级,但可通过 SortedList 或第三方库(如 System.Collections.PriorityQueue)实现:

// 使用 SortedList 实现简单优先队列
SortedList<int, string> priorityQueue = new SortedList<int, string>();
priorityQueue.Add(1, "高优先级任务");
priorityQueue.Add(2, "中优先级任务");

六、常见问题与解决方案

6.1 为什么 Dequeue 可能抛出异常?

当队列为空时调用 DequeuePeek,会抛出 InvalidOperationException。解决方案包括:

if (taskQueue.Count > 0)
{
    string task = taskQueue.Dequeue();
    // 处理任务
}

6.2 如何遍历队列?

由于队列的 FIFO 特性,遍历通常需结合 PeekDequeue

while (taskQueue.Count > 0)
{
    string task = taskQueue.Dequeue();
    Console.WriteLine(task);
    // 若需保留队列内容,需重新 Enqueue
    taskQueue.Enqueue(task);
}

结论

通过本文,我们系统地学习了 C# 队列(Queue) 的核心概念、操作方法及应用场景。从基础的 EnqueueDequeue,到多线程环境下的 ConcurrentQueue<T>,再到优先队列的实现技巧,队列不仅是算法与数据结构的基础,更是解决实际问题的重要工具。

对于开发者而言,掌握队列的使用不仅能提升代码的效率和可维护性,还能在任务调度、缓冲处理等场景中发挥关键作用。建议读者通过实际项目中的队列应用(如消息队列、任务队列)进一步巩固知识,并探索其与栈、优先队列等结构的结合使用场景。

通过不断实践和优化,队列将成为你编程工具箱中不可或缺的利器。

最新发布