Heap啊,Heap,
上头尖来下头粗。
有朝一日倒过来,
下头尖来上头粗。
using System;
using System.Collections.Generic;
namespace Lucifer.DataStructure
{
public class PriorityQueue<T>
{
#region 私有变量
private int theSize;
private T[] theArray;
private IComparer<T> theComparer;
private const int defaultCapacity = 100;
#endregion
#region 构造函数
public PriorityQueue()
: this(Comparer<T>.Default)
{
}
public PriorityQueue(IComparer<T> comparer)
{
this.theArray = new T[defaultCapacity];
this.theComparer = comparer;
}
public PriorityQueue(IEnumerable<T> collection)
{
this.theComparer = Comparer<T>.Default;
ICollection<T> currentCollection = collection as ICollection<T>;
if (currentCollection != null)
{
this.theSize = currentCollection.Count;
this.theArray = new T[(theSize + 2) * 11 / 10];
currentCollection.CopyTo(theArray, 1);
}
else
{
int i = 1;
foreach (T item in collection)
{
this.theArray[i++] = item;
theSize++;
}
}
this.BuildHeap();
}
#endregion
#region 公有方法
/// <summary>
/// 添加 item 到优先级队列中。
/// </summary>
/// <param name="item">要添加的值。</param>
public void Add(T item)
{
if (theSize + 1 == theArray.Length)
{
Array.Resize<T>(ref theArray, theArray.Length == 0 ? defaultCapacity : (theArray.Length * 2));
}
/*
* 向上过滤。
*/
int hole = ++theSize;
theArray[0] = item;
for (; theComparer.Compare(item, theArray[hole / 2]) < 0; hole /= 2)
{
theArray[hole] = theArray[hole / 2];
}
theArray[hole] = item;
}
/// <summary>
/// 清空优先级队列。
/// </summary>
public void Clear()
{
Array.Clear(theArray, 0, theSize);
this.theSize = 0;
}
/// <summary>
/// 移除优先级队列中最小项。
/// </summary>
/// <returns>返回优先级队列中被移除的最小项。</returns>
public T Remove()
{
T item = this.GetMin();
theArray[1] = theArray[theSize--];
this.PercolateDown(1);
return item;
}
/// <summary>
/// 获得优先级队列中最小项。
/// </summary>
/// <returns>返回优先级队列中最小项。</returns>
/// <exception>抛出 InvalidOperationException 异常,当队列为空时。</exception>
public T GetMin()
{
if (this.IsEmpty())
{
throw new InvalidOperationException("The queue is empty.");
}
return theArray[1];
}
/// <summary>
/// 判断优先级队列是否为空。
/// </summary>
/// <returns>如果是空队列,返回 true 。否则,返回 false 。</returns>
public bool IsEmpty()
{
return theSize == 0;
}
#endregion
#region 公有属性
/// <summary>
/// 获得优先级队列中项的数量。
/// </summary>
public int Count
{
get
{
return theSize;
}
}
#endregion
#region 私有方法
/*
* 构造一个堆。
*/
private void BuildHeap()
{
for (int i = theSize / 2; i > 0; i--)
{
this.PercolateDown(i);
}
}
/*
* 向下过滤。
*/
private void PercolateDown(int hole)
{
int child;
T item = theArray[hole];
for (; hole * 2 <= theSize; hole = child)
{
child = hole * 2;
/*
* 父结点并不总是有两个子结点。
*/
if (child != theSize && theComparer.Compare(theArray[child + 1], theArray[child]) < 0)
{
child++;
}
if (theComparer.Compare(theArray[child], item) < 0)
theArray[hole] = theArray[child];
else
break;
}
theArray[hole] = item;
}
#endregion
}
}