代码改变世界

算法笔记(堆实现的最大优先队列)

2011-11-17 20:20  java线程例子  阅读(318)  评论(0编辑  收藏  举报

采用最大堆实现的优先队列,QueueElement是队列元素类,包含一个卫星数据成员和一个权重Key值:

 
public class QueueElement<T>
    {
        public int KeyValue{get;internal set;}
        public T Element{get;private set;}
        public QueueElement(T Item,int KeyVal)
        {
            KeyValue = KeyVal;
            Element = Item;
        }
    }
    public class MaxHeapQueue<T> 
    {
        private List<QueueElement<T>> _queueValues = new List<QueueElement<T>>();
        public int Count
        {
            get
            {
                return _queueValues.Count;
            }
        }
        public T GetMaximum()
        {
            return _queueValues[0].Element;
        }
        public T ExtractMax()
        {
            if (_queueValues.Count <= 0)
            {
                throw new Exception("队列为空");
            }
            T theMax = _queueValues[0].Element;
            int theTail = Count -1;
            _queueValues[0] = _queueValues[theTail];
            _queueValues.RemoveAt(theTail);
            MaxHeapify(0);
            return theMax;
        }
        public void MaxHeapify(int i)
        {
            int HeapSize = Count;
            int theL = HeapL(i);
            int theR = HeapR(i);
            int thelargest = i;
            if (theL < HeapSize && _queueValues[theL].KeyValue> _queueValues[thelargest].KeyValue)
            {
                thelargest = theL;
            }
            if (theR < HeapSize && _queueValues[theR].KeyValue> _queueValues[thelargest].KeyValue)
            {
                thelargest = theR;
            }
            if (thelargest != i)
            {
                SwapElement(i, thelargest);
                MaxHeapify(thelargest);
            }
        }

        public void IncreaseKey(Func<T, bool> SelectFunc, int NewKey)
        {
            int theIndex = -1;
            for (int i = 0; i < Count; i++)
            {
                if (SelectFunc(_queueValues[i].Element) == true)
                {
                    theIndex = i;
                    break;
                }
            }
            if (theIndex < 0)
            {
                return;
            }
            if (_queueValues[theIndex].KeyValue >= NewKey)
            {
                return;
            }
            _queueValues[theIndex].KeyValue = NewKey;
            UpAdjust(theIndex);
        }
        private void UpAdjust(int i)
        {
            int theIndex = i;
            int thePIndex = HeapP(theIndex);
            while (thePIndex >= 0 && _queueValues[theIndex].KeyValue > _queueValues[thePIndex].KeyValue)
            {
                SwapElement(thePIndex, theIndex);
                theIndex = thePIndex;
                thePIndex = HeapP(theIndex);
            }
        }
        public void IncreaseKey(int i, int NewKey)
        {
            int theIndex = i;
            if (_queueValues[theIndex].KeyValue >= NewKey)
            {
                return;
            }
            _queueValues[theIndex].KeyValue = NewKey;
            int thePIndex = HeapP(theIndex);
            while (thePIndex >= 0 && _queueValues[theIndex].KeyValue > _queueValues[thePIndex].KeyValue)
            {
                SwapElement(thePIndex, theIndex);
                theIndex = thePIndex;
                thePIndex = HeapP(theIndex);
            }
        }
        public void HeapDelete(Func<T, bool> SelectFunc)
        {
            int theIndex = -1;
            for (int i = 0; i < Count; i++)
            {
                if (SelectFunc(_queueValues[i].Element) == true)
                {
                    theIndex = i;
                    break;
                }
            }
            if (theIndex < 0)
            {
                return;
            }
            SwapElement(theIndex, Count - 1);
            _queueValues.RemoveAt(Count-1);
            if (theIndex < Count)
            {
                int theP = HeapP(theIndex);
                bool theUp = false;
                if (theP >= 0)
                {
                    if (_queueValues[theIndex].KeyValue > _queueValues[theP].KeyValue)
                    {
                        UpAdjust(theIndex);
                        theUp = true;
                    }
                }
                if(theUp==false)
                {
                    MaxHeapify(theIndex);
                }
            }
            
        }
        private void SwapElement(int i, int j)
        {
            QueueElement<T> theTmp = _queueValues[i];
            _queueValues[i] = _queueValues[j];
            _queueValues[j] = theTmp;
        }
        public void HeapInsert(T Element, int Key)
        {
            _queueValues.Add(new QueueElement<T>(Element, int.MinValue));
            IncreaseKey(Count-1, Key);
        }
        private int HeapL(int i)
        {
            return i * 2 + 1;
        }
        private  int HeapR(int i)
        {
            return i * 2 + 2;
        }
        private  int HeapP(int i)
        {
            return (i + 1) / 2 - 1;
        }
}