基于堆的最大最小优先级队列的实现

最大堆能够在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

时间: 2024-10-15 00:17:33

基于堆的最大最小优先级队列的实现的相关文章

STL源码笔记(15)—堆和优先级队列(二)

STL源码笔记(15)-堆和优先级队列 优先级队列的源码实现基于heap的操作,底层容器默认是vector. 优先级队列简介 优先级队列跟队列类似,一端插入一端删除,不同的是,优先级队列的元素入队后会根据其优先级进行调整,默认情况下优先级高的将优先出队,在SGI STL中,优先级队列的功能保证由heap实现:stl_heap.h中,heap的分析见:STL堆源码分析 优先级队列构造函数 默认情况下,优先级队列使用vector作为底层容器,使用less作为比较函数,其在源码中的定义声明如下: te

【数据结构】用模版实现大小堆、实现优先级队列,以及堆排序

一.用模版实现大小堆 如果不用模版的话,写大小堆,就需要分别实现两次,但是应用模版的话问题就简单多了,我们只需要实现两个仿函数,Greater和Less就行了,仿函数就是用类实现一个()的重载就实现了仿函数.这个看下代码就能理解了.再设计参数的时候,需要把模版设计成模版的模版参数,因为要实现大小堆嘛!当我们实现好一个大堆或者小队的逻辑后只需要用模版接收的Greater或Less类定义一个变量,就能实现通用功能了. template<typename T> struct Less {     b

优先级队列(Priority Queue)

优先级队列(Priority Queue) 注:队列是一种特征为FIFO的数据结构,每次从队列中取出的是最早加入队列中的元素.但是,许多应用需要另一种队列,每次从队列中取出的应是具有最高优先权的元素,这种队列就是优先级队列(Priority Queue),也称为优先权队列. 1. 优先级队列的概念 1.1 优先级队列的定义 优先级队列是不同于先进先出队列的另一种队列.每次从队列中取出的是具有最高优先权的元素. 1.2 优先级队列的特点 优先级队列是0个或多个元素的集合,每个元素都有一个优先权或值

经典白话算法之优先级队列

<1>概念 优先级队列,顾名思义,就是一种根据一定优先级存储和取出数据的队列.它可以说是队列和排序的完美结合体,不仅可以存储数据,还可以将这些数据按照我们设定的规则进行排序.优先级队列是堆的一种常见应用.有最大优先级队列(最大堆)和最小优先级队列(最小堆).优先级队列是一种维护有一组元素构成的集合S的数据结构. <2>优先队列支持的基本运算 [cpp] view plaincopy //建立一个保存元素为int的优先级队列,其实是建了一个小顶堆 //但是请特别注意这样的建的堆默认是

STL中的优先级队列priority_queue

priority_queue(queue类似)完全以底部容器为根据,再加上二叉堆(大根堆或者小根堆)的实现原理,所以其实现非常简单,缺省情况下priority_queue以vector作为底部容器.另外priority_queue缺省比较规则是less: class Compare = less<typename Sequence::value_type> less对应的是按照大根堆来实现优先级队列,当然也可以将比较规则设置为greater,这时候是按照小根堆来实现的优先级队列. priori

初学算法-基于最小堆的优先级队列C++实现

笔者近日实现了最小堆类及其派生的优先级队列,特将代码奉上,不足之处还请指出! 在实现优先级队列时,笔者表示萌萌哒没有用过template写派生类,结果写完了出现error: *** was not decleared in this scope..后来各种补上this->才完事,在CSDN(笔者的帖子地址? http://bbs.csdn.net/topics/391806995)上提问后才知道是模板参数依赖,笔者表示涨姿势了.. /**  * The Minimum Heap Class an

python[数据]--队列,堆,优先级队列

队列:from collections import deque:实现保存最后几条历史记录,list = deque(maxlen=6),那么超过六条记录会删除之前的记录. 堆:import heapq;最大特点是第一弹出的元素总是堆中最小的元素:list=[1,2,3] heap=heapq.heapify(list) ,nlargest(3,数据,key=lambda) nsmallest() 优先级队列:堆中的元素(-优先级,序号,item)这样即可实现优先级,优先级越高最先pop出堆,优

Jcompress: 一款基于huffman编码和最小堆的压缩、解压缩小程序

前言 最近基于huffman编码和最小堆排序算法实现了一个压缩.解压缩的小程序.其源代码已经上传到github上面: Jcompress下载地址 .在本人的github上面有一个叫Utility的repository,该分类下面有一个名为Jcompress的目录便是本文所述的压缩.解压缩小程序的源代码.后续会在Utility下面增加其他一些实用的小程序,比如基于socket的文件断点下载小程序等等.如果你读了此文觉得还不错,不防给笔者的github点个star, 哈哈.在正式介绍Jcompres

初学图论-Dijkstra单源最短路径算法基于优先级队列(Priority Queue)的实现

这一次,笔者使用了STL库中的优先级队列(Priority Queue)来完成Dijkstra算法中extract-min()语句(即从未选中的节点中选取一个距离原点s最小的点)的功能.由于优先级队列的插入.删除操作只需要logn的时间花费,因此降低了不少运行时间. 本文使用C++实现了这一基本算法.参考<算法导论>第24.3节. /**  * Dijkstra's Single Source Shortest Path Algorithm in C++  * Time Cost : O(Ml