日期:2014-05-18 浏览次数:21174 次
public sealed class PriorityQueue<T> where T : IComparable<T>
{
private T[] heap;
public int Count { get; private set; }
public PriorityQueue(int capacity)
{
if (capacity <= 0)
{
throw new InvalidOperationException("优先队列的初始容量必须大于0");
}
heap = new T[capacity];
}
public PriorityQueue()
: this(32)
{ }
public PriorityQueue(T[] array)
{
Count = array.Length;
heap = array;
BuildMaxHeap(heap);
}
/// <summary>
/// 获取优先级最高的元素
/// </summary>
/// <returns></returns>
public T Top()
{
ThrowExceptionIfPriorityQueueIsNull();
return heap[0];
}
/// <summary>
/// 删除并返回优先级最高的元素
/// </summary>
/// <returns></returns>
public T ExtractTop()
{
ThrowExceptionIfPriorityQueueIsNull();
T top = heap[0];
heap[0] = heap[this.Count - 1];
heap[this.Count - 1] = default(T);
this.Count--;
//保持堆的性质
HeapifyDown(0);
return top;
}
private void ThrowExceptionIfPriorityQueueIsNull()
{
if (Count <= 0)
throw new InvalidOperationException("优先队列为空");
}
/// <summary>
/// 增加索引位置元素的优先级
/// </summary>
/// <param name="index">当前元素的索引</param>
/// <param name="newValue">新的优先级元素</param>
public void IncreasePriority(int index, T newValue)
{
if (index < 0 || index >= Count)
{
throw new IndexOutOfRangeException("当前索引超出队列范围");
}
if (newValue.CompareTo(heap[index]) < 0)
{
throw new InvalidOperationException("新值必须大于当前值");
}
heap[index] = newValue;
HeapifyUp(index);
}
/// <summary>
/// 从指定位置向下调整堆,保证堆的性质
/// </summary>
/// <param name="current"></param>
private void HeapifyDown(int current)
{
//当前元素的左子元素的索引
int left = (current + 1) * 2 - 1;
//当前元素的右子元素的索引
int right = left + 1;
int largest;
if (left < Count && heap[left].CompareTo(heap[current]) > 0)
{
largest = left;
}
else
{
largest = current;
}
if (right < Count && heap[right].CompareTo(heap[largest]) > 0)
{
largest = right;
}
//如果单前值得优先级不为最高,则继续向下调整
if (largest != current)
{
Swap(ref heap[current], ref heap[largest]);
HeapifyDown(largest);
}
}
/// <summary>
/// 给优先队列添加新的元素
/// </summary>
/// <param name="key"></param>
public void Insert(T key)
{
if (Count == heap.Length)
{
EnsureCapacity(Count);
}
heap[Count++] = key;
HeapifyUp(Count - 1);
}
/// <summary>
/// 将数组调整为最大堆
/// </summary>
/// <param name="array"></param>
private void BuildMaxHeap(T[] array)
{