using System; using System.Collections; using System.Collections.Generic; /// /// 泛型优先队列 /// 基于二叉堆算法,适用于所有.NET版本 /// /// 队列元素类型 /// 优先级类型,必须实现IComparable public sealed class PriorityQueue : IEnumerable<(TElement Element, TPriority Priority)> where TPriority : IComparable { private readonly List<(TElement Element, TPriority Priority)> _heap; private readonly IComparer _comparer; private readonly Dictionary _elementCounts; public enum PriorityQueueOrder { Min, Max } /// /// 初始化优先队列新实例 /// /// 初始容量 /// 队列排序方式 public PriorityQueue(int capacity = 0, PriorityQueueOrder order = PriorityQueueOrder.Min) { _heap = capacity > 0 ? new List<(TElement, TPriority)>(capacity) : new List<(TElement, TPriority)>(); _elementCounts = capacity > 0 ? new Dictionary(capacity) : new Dictionary(); _comparer = order == PriorityQueueOrder.Min ? Comparer.Default : Comparer.Create((x, y) => y.CompareTo(x)); } /// /// 使用自定义比较器初始化 /// public PriorityQueue(IComparer comparer, int capacity = 0) { _comparer = comparer ?? throw new ArgumentNullException(nameof(comparer)); _heap = capacity > 0 ? new List<(TElement, TPriority)>(capacity) : new List<(TElement, TPriority)>(); _elementCounts = capacity > 0 ? new Dictionary(capacity) : new Dictionary(); } public int Count => _heap.Count; public bool IsEmpty => _heap.Count == 0; public void Enqueue(TElement element, TPriority priority) { if (element == null) throw new ArgumentNullException(nameof(element)); _heap.Add((element, priority)); // 更新元素计数 if (_elementCounts.ContainsKey(element)) ++_elementCounts[element]; else _elementCounts[element] = 1; HeapifyUp(_heap.Count - 1); } public TElement Peek() { if (_heap.Count == 0) throw new InvalidOperationException("Queue is empty"); return _heap[0].Element; } public TElement Dequeue() { if (_heap.Count == 0) throw new InvalidOperationException("Queue is empty"); TElement result = _heap[0].Element; RemoveRoot(); return result; } public bool TryDequeue(out TElement element, out TPriority priority) { if (_heap.Count > 0) { element = _heap[0].Element; priority = _heap[0].Priority; RemoveRoot(); return true; } element = default; priority = default; return false; } public bool TryPeek(out TElement element, out TPriority priority) { if (_heap.Count > 0) { element = _heap[0].Element; priority = _heap[0].Priority; return true; } element = default; priority = default; return false; } /// /// 检查队列是否包含指定元素 /// public bool Contains(TElement element) { if (element == null) throw new ArgumentNullException(nameof(element)); return _elementCounts.ContainsKey(element); } /// /// 获取指定元素在队列中的出现次数 /// public int GetElementCount(TElement element) { if (element == null) throw new ArgumentNullException(nameof(element)); return _elementCounts.TryGetValue(element, out int count) ? count : 0; } /// /// 移除队列中指定元素的所有实例 /// public bool RemoveAll(TElement element) { if (element == null) throw new ArgumentNullException(nameof(element)); if (!_elementCounts.ContainsKey(element)) return false; // 记录要移除的元素数量 int countToRemove = _elementCounts[element]; // 从堆中移除所有匹配的元素 _heap.RemoveAll(item => EqualityComparer.Default.Equals(item.Element, element)); // 重建堆(因为直接移除破坏了堆结构) RebuildHeap(); // 更新计数 _elementCounts.Remove(element); return countToRemove > 0; } /// /// 移除队列中指定元素的一个实例 /// public bool Remove(TElement element) { if (element == null) throw new ArgumentNullException(nameof(element)); if (!_elementCounts.ContainsKey(element)) return false; // 查找元素的第一个出现位置 int index = -1; for (int i = 0; i < _heap.Count; i++) { if (EqualityComparer.Default.Equals(_heap[i].Element, element)) { index = i; break; } } if (index == -1) return false; // 移除元素 RemoveAt(index); return true; } public void Clear() { _heap.Clear(); _elementCounts.Clear(); } public (TElement Element, TPriority Priority)[] ToArray() { return _heap.ToArray(); } public IEnumerator<(TElement Element, TPriority Priority)> GetEnumerator() { return _heap.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } private void RemoveRoot() { if (_heap.Count == 0) return; var rootElement = _heap[0].Element; int lastIndex = _heap.Count - 1; _heap[0] = _heap[lastIndex]; _heap.RemoveAt(lastIndex); // 更新元素计数 UpdateElementCount(rootElement, -1); if (_heap.Count > 0) { HeapifyDown(0); } } private void RemoveAt(int index) { if (index < 0 || index >= _heap.Count) return; var element = _heap[index].Element; // 将最后一个元素移动到当前位置 int lastIndex = _heap.Count - 1; _heap[index] = _heap[lastIndex]; _heap.RemoveAt(lastIndex); // 更新元素计数 UpdateElementCount(element, -1); // 如果需要,调整堆结构 if (index < _heap.Count) { HeapifyUp(index); HeapifyDown(index); } } private void UpdateElementCount(TElement element, int delta) { if (_elementCounts.ContainsKey(element)) { _elementCounts[element] += delta; if (_elementCounts[element] <= 0) { _elementCounts.Remove(element); } } } private void RebuildHeap() { // 简单的堆重建方法:从最后一个非叶子节点开始向下堆化 for (int i = _heap.Count / 2 - 1; i >= 0; i--) { HeapifyDown(i); } } private void HeapifyUp(int index) { while (index > 0) { int parentIndex = (index - 1) / 2; if (_comparer.Compare(_heap[index].Priority, _heap[parentIndex].Priority) >= 0) break; Swap(index, parentIndex); index = parentIndex; } } private void HeapifyDown(int index) { while (index < _heap.Count) { int leftChild = 2 * index + 1; int rightChild = 2 * index + 2; int smallest = index; if (leftChild < _heap.Count && _comparer.Compare(_heap[leftChild].Priority, _heap[smallest].Priority) < 0) { smallest = leftChild; } if (rightChild < _heap.Count && _comparer.Compare(_heap[rightChild].Priority, _heap[smallest].Priority) < 0) { smallest = rightChild; } if (smallest == index) break; Swap(index, smallest); index = smallest; } } private void Swap(int i, int j) { (_heap[j], _heap[i]) = (_heap[i], _heap[j]); } }