读书人

分享一个自己写的简单的最大优先队列。

发布时间: 2012-05-08 22:09:41 作者: rapoo

分享一个自己写的简单的最大优先队列。。。
最近在看算法导论,正好看到优先队列,于是想看看.net framework中的Priority Queue是怎样实现的,结果貌似找不到这个数据结构,于是就自己写了个简陋的最大优先队列,如果有什么错误或者不妥请大家指出。

C# code
    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)        {            int count = array.Length / 2 - 1;            for (; count >= 0; count--)            {                HeapifyDown(count);            }        }        private void EnsureCapacity(int min)        {            int num = min * 2;            T[] detisnationArray = new T[num];            Array.Copy(this.heap, detisnationArray, heap.Length);            heap = detisnationArray;        }        private static void Swap(ref T value1, ref T value2)        {            T temp = value1;            value1 = value2;            value2 = temp;        }        /// <summary>        /// 从指定位置开始向上调整,保证堆的性质        /// </summary>        /// <param name="current"></param>        private void HeapifyUp(int current)        {            //当前元素的父元素            int parent = (current - 1) / 2;            while (current > 0 && heap[parent].CompareTo(heap[current]) < 0)            {                Swap(ref heap[parent],ref heap[current]);                current = (current - 1) / 2;                parent = (parent - 1) / 2;            }        }    } 



[解决办法]
赞一个~~~~~~~
[解决办法]
不错……
[解决办法]
谢谢。另外一些建议:

1、IncreasePriority(int index, T newValue)可以不要。
...a) 这个index用户几乎没有办法使用(他如何知道要调整的元素在那个位置?)
...b) 缺乏对称的DecreasePriority
...c) int index泄露了内部实现。

2、既然名称叫PriorityQueue,
...a) 添加最好叫Enqueue,而不是Insert。
...b) 取出叫Dequeue,而不是ExtractTop。

3、EnsureCapacity中文为确保容量,因此条件语句最好写在函数内。如果已经事先判断是否要增加容量,函数名字可以叫做IncreaseCapacity了。

4、T[] heap可以用List<T> heap来替代,就不需要显式调整容量了。

5、如果一定要动态调整Priority,可以让T实现IPropertyChangeNotification。

6、我可能只会公开以下函数:
C# code
public sealed class PriorityQueue<T> where T : IComparable<T>{    public PriorityQueue();    public PriorityQueue(IEnumerable<T>);    public Enqueue(T value);    public T Dequeue();    public T Peek();}
[解决办法]
探讨

赞一个~~~~~~~

[解决办法]
赞一个~~~
[解决办法]
赞一个~~~
[解决办法]
学习了 不错
[解决办法]
.NET中已有类似功能的类,使用起来非常方便,根本不需要自己实现,不过还是鼓励下。
请自行查看SortedList<T>的用法。
[解决办法]
Queue 的话一般用 pop 和 push 吧,呵呵
[解决办法]
探讨
.NET中已有类似功能的类,使用起来非常方便,根本不需要自己实现,不过还是鼓励下。
请自行查看SortedList<T>的用法。

[解决办法]
探讨
Queue 的话一般用 pop 和 push 吧,呵呵

[解决办法]
好东西哦
[解决办法]
牛人呀, 这么厉害, 我也得像你学习
[解决办法]
看算法的都是牛人
[解决办法]
太强大了!学习了!!
[解决办法]
不错不错 学习了
[解决办法]
MSMQ就有优先队列哦
[解决办法]
探讨
学习了

[解决办法]
看上去是这么个意思
[解决办法]
我顶了,挺好
[解决办法]
楼上这个混淡打广告的 去死!!
[解决办法]
要大赞一下
[解决办法]
赞一下赞一下

读书人网 >C#

热点推荐