日期:2014-05-18  浏览次数:20980 次

分享一个自己写的简单的最大优先队列。。。
最近在看算法导论,正好看到优先队列,于是想看看.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)
        {