C#中的优先队列详解
C# 中的优先队列( PriorityQueue<TElement, TPriority> )是按优先级排序的数据结构,优先级高的元素会被优先取出,底层通过最小堆实现,需引用 System.Collections.Generic 命名空间(.NET 6+ 正式引入)。
一、核心特性与原理
1. 优先级驱动:元素入队时需关联一个优先级(如 int、double 等可比较类型),出队时始终取出优先级最高(默认最小优先级值视为最高)的元素,而非按入队顺序。
2. 底层实现:基于最小堆(一种完全二叉树),确保每次获取/移除优先级最高的元素时,时间复杂度仅为 O(log n),效率远高于普通队列排序。
3. 优先级规则:默认使用 IComparer<TPriority> 比较优先级,如 int 类型中, 1 的优先级高于 2 ;可自定义比较器修改规则(如让大值优先级更高)。
二、典型应用场景
- 任务调度:如操作系统中高优先级进程优先执行、游戏中紧急事件(如角色死亡)优先处理。
- 最短路径算法:如 Dijkstra 算法,优先选择当前距离起点最近的节点。
- 事件驱动系统:如日志系统中,错误日志(高优先级)比信息日志(低优先级)优先输出。
三、核心方法与代码示例
1. 常用方法
方法名 功能描述
- Enqueue 向队列中添加元素及对应的优先级
- Dequeue 移除并返回优先级最高的元素(队首)
- Peek 仅返回(不移除)优先级最高的元素
- TryDequeue 尝试移除并返回最高优先级元素,返回是否成功
- Count 获取队列中元素的总数
- Clear 清空队列中所有元素
2. 基础示例:模拟任务调度
需求:3个任务分别标注优先级(1=紧急,3=普通),让紧急任务优先执行。
using System;
using System.Collections.Generic;
class PriorityQueueDemo
{
static void Main()
{
// 定义优先队列:TElement=任务名称(string),TPriority=优先级(int)
PriorityQueue<string, int> taskQueue = new PriorityQueue<string, int>();
// 1. 入队:添加任务及优先级(1=最高,3=最低)
taskQueue.Enqueue("生成用户报表(普通)", 3);
taskQueue.Enqueue("修复支付bug(紧急)", 1);
taskQueue.Enqueue("同步数据库数据(一般)", 2);
Console.WriteLine($"任务总数:{taskQueue.Count}\n"); // 输出:3
// 2. 出队:按优先级从高到低执行任务
while (taskQueue.Count > 0)
{
// 取出优先级最高的任务
string currentTask = taskQueue.Dequeue();
Console.WriteLine($"正在执行:{currentTask}");
}
}
}
// 输出结果(优先级1最先,3最后):
// 任务总数:3
// 正在执行:修复支付bug(紧急)
// 正在执行:同步数据库数据(一般)
// 正在执行:生成用户报表(普通)
3. 进阶示例:自定义优先级规则
需求:让数值大的优先级更高(如优先级 3 比 1 先执行),需自定义 IComparer<int> 。
using System;
using System.Collections.Generic;
// 自定义比较器:反转默认规则,大值优先级更高
class ReversePriorityComparer : IComparer<int>
{
public int Compare(int x, int y)
{
// 默认 Compare(x,y) 返回负数时 x 优先级高,此处反转,让 y 比 x 小则 x 优先级高
return y.CompareTo(x);
}
}
class CustomPriorityDemo
{
static void Main()
{
// 初始化队列时传入自定义比较器
PriorityQueue<string, int> queue = new PriorityQueue<string, int>(new ReversePriorityComparer());
queue.Enqueue("任务A", 1);
queue.Enqueue("任务B", 3);
queue.Enqueue("任务C", 2);
// 出队顺序:3(B)→2(C)→1(A)
while (queue.Count > 0)
{
Console.WriteLine(queue.Dequeue()); // 输出:任务B → 任务C → 任务A
}
}
}
四、注意事项
1. 优先级类型必须可比较: TPriority 必须实现 IComparable<TPriority> 接口,否则需在初始化时传入自定义 IComparer<TPriority> ,否则会报错。
2. 相同优先级的元素:当多个元素优先级相同时,按入队顺序出队(底层堆结构保证先进先出)。
3. 空值处理: TElement 允许为 null (引用类型),但 TPriority 不允许为 null ,否则会抛出 ArgumentNullException 。
更多推荐



所有评论(0)