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

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

posted @ 2014-04-30 23:51  AndyZeng  阅读(927)  评论(1编辑  收藏  举报