最大堆能够在O(1)的时间内取得集合中的最大值,并且在集合中加入新元素的时候,能够以O(Logn)的时间将新的元素插入到堆中。
当取出最大的元素时,能够以O(Logn)的时间重新将堆整理成最大堆。最小堆同理。
最大优先级队列的应用实例:基于优先级的作业调度,在所有等待调度的作业中,选择具有最大优先级作业进行处理。同时一个新的作业也可以插入到队列里面去。
例如可以实现自己的基于优先级的多线程作业调度程序。
最小优先级队列的应用实例:可以实现一个基于时间的作业调度程序,时间最小的被优先选择进行事件通知或者处理。Huffman编码的实现可以依靠最小优先级队列实现。
最大最小优先级队列的C#实现:
队列处理的数据类型:
public interface IHeapValue
{
int Value { get; set; }
}
最大优先级队列:
public class MaxPriorityQueue<TNode>
where TNode : IHeapValue
{
private TNode[] array;
//cursor 指向第一个空出来的位置
private int cursor;
public MaxPriorityQueue()
{
array = new TNode[32];
cursor = 0;
}
public bool IsEmpty { get { return cursor <=0; } }
public void Insert(TNode x)
{
if (cursor + 1 == array.Count())
{
TNode[] tmparray = new TNode[array.Count() * 2];
array.CopyTo(tmparray, 0);
array = tmparray;
}
//往上检查是否成最大堆
int xIndex = cursor++;
array[xIndex] = x;
while (xIndex / 2 >= 0)
{
if (array[xIndex / 2].Value >= array[xIndex].Value) break;
TNode tmpNode = array[xIndex / 2];
array[xIndex / 2] = array[xIndex];
array[xIndex] = tmpNode;
xIndex = xIndex / 2;
}
}
public TNode Maximum()
{
return array[0];
}
public TNode ExtractMax()
{
TNode hn = array[0];
//把最后一个元素换到第一个 array[0]= array[cursor-1],array[cursor-1]=null;cursor--;
array[0] = array[cursor - 1];
array[cursor - 1] = default(TNode);
cursor--;
maxHeapify(0, cursor - 1, 0);
return hn;
}
public void IncreaseKey(int nodeIndex, int newValue)
{
if (nodeIndex < cursor && array[nodeIndex].Value < newValue)
{
array[nodeIndex].Value = newValue;
while (nodeIndex / 2 >= 0)
{
if (array[nodeIndex / 2].Value >= array[nodeIndex].Value) break;
TNode tmpNode = array[nodeIndex / 2];
array[nodeIndex / 2] = array[nodeIndex];
array[nodeIndex] = tmpNode;
nodeIndex = nodeIndex / 2;
}
}}
//由下向上建堆时使用此函数,下面已经建好,上面还没好时使用
private void maxHeapify(int startIndex, int endIndex, int newRootIndex)
{//int L = (newRootIndex - startIndex) * 2 + 1 + startIndex;
int L = (newRootIndex - startIndex + 1) * 2 + startIndex - 1;//The array base is from 0.
int R = L + 1;
int tmpLargestIndex = newRootIndex;
if (L <= endIndex && array[L].Value.CompareTo(array[tmpLargestIndex].Value) > 0)
{
tmpLargestIndex = L;
}
if (R <= endIndex && array[R].Value.CompareTo(array[tmpLargestIndex].Value) > 0)
{
tmpLargestIndex = R;
}
if (tmpLargestIndex != newRootIndex)
{
//swap array[tmpLargestIndex] and array[newRootIndex]
TNode tmpT = array[tmpLargestIndex];
array[tmpLargestIndex] = array[newRootIndex];
array[newRootIndex] = tmpT;
//MaxHeapify the child branch, the newRootIndex= tmpLargestIndex
maxHeapify(startIndex, endIndex, tmpLargestIndex);
}
}
}
MaxPriorityQueue
最小优先级队列:
public class MinPriorityQueue<TNode>
where TNode : IHeapValue
{
private TNode[] array;
//cursor 指向第一个空出来的位置
private int cursor;
public MinPriorityQueue()
{
array = new TNode[32];
cursor = 0;
}
public bool IsEmpty { get { return cursor <= 0; } }
public void Insert(TNode x)
{
if (cursor + 1 == array.Count())
{
TNode[] tmparray = new TNode[array.Count() * 2];
array.CopyTo(tmparray, 0);
array = tmparray;
}
//往上检查是否成最小堆
int xIndex = cursor++;
array[xIndex] = x;
while (xIndex / 2 >= 0)
{
if (array[xIndex / 2].Value <= array[xIndex].Value) break;
TNode tmpNode = array[xIndex / 2];
array[xIndex / 2] = array[xIndex];
array[xIndex] = tmpNode;
xIndex = xIndex / 2;
}
}
public TNode Minimum()
{
return array[0];
}
public TNode ExtractMin()
{
TNode hn = array[0];
//把最后一个元素换到第一个 array[0]= array[cursor-1],array[cursor-1]=null;cursor--;
array[0] = array[cursor - 1];
array[cursor - 1] = default(TNode);
cursor--;
minHeapify(0, cursor - 1, 0);
return hn;
}
public void DecreaseKey(int nodeIndex, int newValue)
{
if (nodeIndex < cursor && array[nodeIndex].Value < newValue)
{
array[nodeIndex].Value = newValue;
while (nodeIndex / 2 >= 0)
{
if (array[nodeIndex / 2].Value <= array[nodeIndex].Value) break;
TNode tmpNode = array[nodeIndex / 2];
array[nodeIndex / 2] = array[nodeIndex];
array[nodeIndex] = tmpNode;
nodeIndex = nodeIndex / 2;
}
}}
//由下向上建堆时使用此函数,下面已经建好,上面还没好时使用
private void minHeapify(int startIndex, int endIndex, int newRootIndex)
{//int L = (newRootIndex - startIndex) * 2 + 1 + startIndex;
int L = (newRootIndex - startIndex + 1) * 2 + startIndex - 1;//The array base is from 0.
int R = L + 1;
int tmpLargestIndex = newRootIndex;
if (L <= endIndex && array[L].Value.CompareTo(array[tmpLargestIndex].Value) < 0)
{
tmpLargestIndex = L;
}
if (R <= endIndex && array[R].Value.CompareTo(array[tmpLargestIndex].Value) < 0)
{
tmpLargestIndex = R;
}
if (tmpLargestIndex != newRootIndex)
{
//swap array[tmpLargestIndex] and array[newRootIndex]
TNode tmpT = array[tmpLargestIndex];
array[tmpLargestIndex] = array[newRootIndex];
array[newRootIndex] = tmpT;
//MaxHeapify the child branch, the newRootIndex= tmpLargestIndex
minHeapify(startIndex, endIndex, tmpLargestIndex);
}
}
}
MinPriorityQueue
基于控制台输出的测试调用方法:
MaxPriorityQueue<IHeapValue> maxheap = new MaxPriorityQueue<IHeapValue>();
MinPriorityQueue<IHeapValue> minheap = new MinPriorityQueue<IHeapValue>();
List<IHeapValue> list = new List<IHeapValue>();
Random rnd = new Random(DateTime.Now.Millisecond);
for (int i = 0; i < 10; i++)
{
HeapNode hn = new HeapNode() { Value = rnd.Next(0, 100) };
list.Add(hn);
maxheap.Insert(hn);
minheap.Insert(hn);
}
Console.WriteLine("RandomData:");
list.ForEach(n => Console.Write("{0},", n.Value));
Console.WriteLine(Environment.NewLine + "MaxHeapOutput:");
while (!maxheap.IsEmpty)
{
Console.Write("{0},", maxheap.ExtractMax().Value);
}
Console.WriteLine(Environment.NewLine + "MinHeapOutput:");
while (!minheap.IsEmpty)
{
Console.Write("{0},", minheap.ExtractMin().Value);
}
Console.ReadKey();
调用方法
输出:
作者:Andy Zeng
欢迎任何形式的转载,但请务必注明出处。
http://www.cnblogs.com/andyzeng/p/3702401.html
基于堆的最大最小优先级队列的实现,码迷,mamicode.com