Priority Queue : Queue « Collections Data Structure « C# / C Sharp






Priority Queue

   

/*==
== Copyright : BlueCurve (c)
== Licence   : Gnu/GPL v2.x
== Author    : Teddy Albina
== Email     : bluecurveteam@gmail.com
== Web site  : http://www.codeplex.com/BlueCurve
*/
using System;
using BlueCurve.Search.Common;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace BlueCurve.Search.Common.PriorityQueue
{
    /// <summary>
    /// Struct dfinissant un PriorityQueueItem
    /// </summary>
    /// <typeparam name="TValue">Clef</typeparam>
    /// <typeparam name="TPriority">Valeur</typeparam>
    [Serializable]
    public struct PriorityQueueItem<TValue, TPriority>
    {
        private TValue _value;
        public TValue Value
        {
            get { return _value; }
            set { _value = value; }
        }

        private TPriority _priority;
        public TPriority Priority
        {
            get { return _priority; }
            set { _priority = value; }
        }

        internal PriorityQueueItem(TValue val, TPriority pri)
        {
            this._value = val;
            this._priority = pri;
        }
    }



    /// <summary>
    /// Fournit une implmentation de priorityQueue
    /// </summary>
    /// <typeparam name="TValue">Type de clef</typeparam>
    /// <typeparam name="TPriority">Type de valeur</typeparam>
    [Serializable]
    public class PriorityQueue<TValue, TPriority> : ICollection , IEnumerable<PriorityQueueItem<TValue, TPriority>>
    {
        /// <summary>
        /// This features enable the priority queue to increment automaticaly
        /// the priority of the item
        /// </summary>
        private PriorityQueueItem<TValue, TPriority>[] items;
        /// <summary>
        /// Default capacity of the queue
        /// </summary>
        private const Int32 DefaultCapacity = 1024;
        /// <summary>
        /// Capacity of the queue
        /// </summary>
        private Int32 capacity;
        /// <summary>
        /// Numbers of items in the queue
        /// </summary>
        private Int32 numItems;
        /// <summary>
        /// Comparison delegate
        /// </summary>
        private Comparison<TPriority> compareFunc;

        /// <summary>
        /// Initializes a new instance of the PriorityQueue class that is empty,
        /// has the default initial capacity, and uses the default IComparer.
        /// </summary>
        public PriorityQueue()
            : this(DefaultCapacity, Comparer<TPriority>.Default)
        {
        }

        public PriorityQueue(Int32 initialCapacity)
            : this(initialCapacity, Comparer<TPriority>.Default)
        {
        }

        public PriorityQueue(IComparer<TPriority> comparer)
            : this(DefaultCapacity, comparer)
        {
        }

        public PriorityQueue(int initialCapacity, IComparer<TPriority> comparer)
        {
            Init(initialCapacity, new Comparison<TPriority>(comparer.Compare));
        }

        public PriorityQueue(Comparison<TPriority> comparison)
            : this(DefaultCapacity, comparison)
        {
        }

        public PriorityQueue(int initialCapacity, Comparison<TPriority> comparison)
        {
            Init(initialCapacity, comparison);
        }

        private void Init(int initialCapacity, Comparison<TPriority> comparison)
        {
            numItems = 0;
            compareFunc = comparison;
            SetCapacity(initialCapacity);
        }

        public int Count
        {
            get { return numItems; }
        }

        public int Capacity
        {
            get { return items.Length; }
            set { SetCapacity(value); }
        }

        private void SetCapacity(int newCapacity)
        {
            int newCap = newCapacity;
            if (newCap < DefaultCapacity)
                newCap = DefaultCapacity;

            // throw exception if newCapacity < NumItems
            if (newCap < numItems)
                throw new ArgumentOutOfRangeException("newCapacity", "New capacity is less than Count");

            this.capacity = newCap;
            if (items == null)
            {
                items = new PriorityQueueItem<TValue, TPriority>[newCap];
                return;
            }

            // Resize the array.
            Array.Resize<PriorityQueueItem<TValue, TPriority>>(ref items, newCap);
        }

        public void Enqueue(PriorityQueueItem<TValue, TPriority> newItem)
        {
            if (numItems == capacity)
            {
                // need to increase capacity
                // grow by 50 percent
                SetCapacity((3 * Capacity) / 2);
            }

            int i = numItems;
            ++numItems;
            while ((i > 0) && (compareFunc(items[(i - 1) / 2].Priority, newItem.Priority) < 0))
            {
                items[i] = items[(i - 1) / 2];
                i = (i - 1) / 2;
            }
            items[i] = newItem;
        }

        /// <summary>
        /// Permet d'ajouter des elements dans la pile
        /// </summary>
        /// <param name="value">Clef</param>
        /// <param name="priority">Priorit</param>
        public void Enqueue(TValue value, TPriority priority)
        {
            Enqueue(new PriorityQueueItem<TValue, TPriority>(value, priority));
        }


        /// <summary>
        /// Permet de supprimer un intervale de la file d'attente
        /// </summary>
        /// <param name="index">dbut de l'intervalle</param>
        /// <returns>PriorityQueueItem</returns>
        private PriorityQueueItem<TValue, TPriority> RemoveAt(Int32 index)
        {
            PriorityQueueItem<TValue, TPriority> o = items[index];
            --numItems;
            // move the last item to fill the hole
            PriorityQueueItem<TValue, TPriority> tmp = items[numItems];
            // If you forget to clear this, you have a potential memory leak.
            items[numItems] = default(PriorityQueueItem<TValue, TPriority>);
            if (numItems > 0 && index != numItems)
            {
                // If the new item is greater than its parent, bubble up.
                int i = index;
                int parent = (i - 1) / 2;
                while (compareFunc(tmp.Priority, items[parent].Priority) > 0)
                {
                    items[i] = items[parent];
                    i = parent;
                    parent = (i - 1) / 2;
                }

                // if i == index, then we didn't move the item up
                if (i == index)
                {
                    // bubble down ...
                    while (i < (numItems) / 2)
                    {
                        int j = (2 * i) + 1;
                        if ((j < numItems - 1) && (compareFunc(items[j].Priority, items[j + 1].Priority) < 0))
                            ++j;
                        if (compareFunc(items[j].Priority, tmp.Priority) <= 0)
                            break;

                        items[i] = items[j];
                        i = j;
                    }
                }
                // Be sure to store the item in its place.
                items[i] = tmp;
            }

            return o;
        }


        /// <summary>
        /// Vrifie que les donnes de la pile sont cohrentes
        /// </summary>
        /// <returns>bool</returns>
        public bool VerifyQueue()
        {
            int i = 0;
            while (i < numItems / 2)
            {
                int leftChild = (2 * i) + 1;
                int rightChild = leftChild + 1;
                if (compareFunc(items[i].Priority, items[leftChild].Priority) < 0)
                    return false;
                if (rightChild < numItems && compareFunc(items[i].Priority, items[rightChild].Priority) < 0)
                    return false;
                ++i;
            }
            return true;
        }

        /// <summary>
        /// Permet d'obtenir un lement
        /// </summary>
        /// <returns>PriorityQueueItem</returns>
        public PriorityQueueItem<TValue, TPriority> Dequeue()
        {
            if (Count == 0)
                throw new InvalidOperationException("The queue is empty");
            return RemoveAt(0);
        }

        /// <summary>
        /// Removes the item with the specified value from the queue.
        /// The passed equality comparison is used.
        /// </summary>
        /// <param name="item">The item to be removed.</param>
        /// <param name="comparer">An object that implements the IEqualityComparer interface
        /// for the type of item in the collection.</param>
        public void Remove(TValue item, IEqualityComparer comparer)
        {
            // need to find the PriorityQueueItem that has the Data value of o
            for (int index = 0; index < numItems; ++index)
            {
                if (comparer.Equals(item, items[index].Value))
                {
                    RemoveAt(index);
                    return;
                }
            }
            throw new ApplicationException("The specified itemm is not in the queue.");
        }

        /// <summary>
        /// Removes the item with the specified value from the queue.
        /// The default type comparison function is used.
        /// </summary>
        /// <param name="item">The item to be removed.</param>
        public void Remove(TValue item)
        {
            Remove(item, EqualityComparer<TValue>.Default);
        }

        /// <summary>
        /// Permet d'obtenir le premier lement de la pile
        /// </summary>
        /// <returns>PriorityQueueItem</returns>
        public PriorityQueueItem<TValue, TPriority> Peek()
        {
            if (Count == 0)
                throw new InvalidOperationException("The queue is empty");
            return items[0];
        }

        /// <summary>
        /// Permet de vider la pile
        /// </summary>
        public void Clear()
        {
            for (int i = 0; i < numItems; ++i)
            {
                items[i] = default(PriorityQueueItem<TValue, TPriority>);
            }
            numItems = 0;
            TrimExcess();
        }

        /// <summary>
        /// Set the capacity to the actual number of items, if the current
        /// number of items is less than 90 percent of the current capacity.
        /// </summary>
        public void TrimExcess()
        {
            if (numItems < (float)0.9 * capacity)
            {
                SetCapacity(numItems);
            }
        }

        /// <summary>
        /// Permet de savoir si un lement existe dans la pile
        /// </summary>
        /// <param name="o">element a tester</param>
        /// <returns>bool</returns>
        public bool Contains(TValue o)
        {
            foreach (PriorityQueueItem<TValue, TPriority> x in items)
            {
                if (x.Value.Equals(o))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// Permet d'obtenir la priorit d'un element
        /// </summary>
        /// <param name="key">element dont on veut la priorit</param>
        /// <returns>TPriority</returns>
        public TPriority GetPriority(TValue key)
        {
            foreach (PriorityQueueItem<TValue, TPriority> x in items)
            {
                if (x.Value.Equals(key))
                    return x.Priority;
            }
            return default(TPriority);
        }

        /// <summary>
        /// Permet de changer la priorit d'un lment
        /// </summary>
        /// <param name="key">lement dont on veut changer la priorit</param>
        /// <param name="priority">nouvelle priorite</param>
        /// <returns>bool</returns>
        public bool SetPriority(TValue key, TPriority priority)
        {
            for (int i = 0; i < items.Length; i++)
            {
                PriorityQueueItem<TValue, TPriority> x = items[i];
                if (x.Value.Equals(key))
                {
                    Console.WriteLine(x.Value);
                    items[i].Priority = priority;
                    return true;
                }  
            }
            return false;
        }


        /// <summary>
        /// Permet de copier les lements de la pile dans un PriorityQueueItem
        /// </summary>
        /// <param name="array">PriorityQueueItem</param>
        /// <param name="arrayIndex">index de l'array a copier</param>
        public void CopyTo(PriorityQueueItem<TValue, TPriority>[] array, int arrayIndex)
        {
            if (array == null)
                throw new ArgumentNullException("array");
            if (arrayIndex < 0)
                throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex is less than 0.");
            if (array.Rank > 1)
                throw new ArgumentException("array is multidimensional.");
            if (numItems == 0)
                return;
            if (arrayIndex >= array.Length)
                throw new ArgumentException("arrayIndex is equal to or greater than the length of the array.");
            if (numItems > (array.Length - arrayIndex))
                throw new ArgumentException("The number of elements in the source ICollection is greater than the available space from arrayIndex to the end of the destination array.");

            for (int i = 0; i < numItems; i++)
            {
                array[arrayIndex + i] = items[i];
            }
        }

        #region ICollection Members

        /// <summary>
        /// Permet de copier a partir d'un Array
        /// </summary>
        /// <param name="array">pile source</param>
        /// <param name="index">index source</param>
        public void CopyTo(Array array, int index)
        {
            this.CopyTo((PriorityQueueItem<TValue, TPriority>[])array, index);
        }

        public bool IsSynchronized
        {
            get { return false; }
        }

        public object SyncRoot
        {
            get { return items.SyncRoot; }
        }

        #endregion

        #region IEnumerable<PriorityQueueItem<TValue,TPriority>> Members
        
        /// <summary>
        /// Enumrateur de la pile
        /// </summary>
        /// <returns>IEnumerator</returns>
        public IEnumerator<PriorityQueueItem<TValue, TPriority>> GetEnumerator()
        {
            for (int i = 0; i < numItems; i++)
            {
                yield return items[i];
            }
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        #endregion




        #region 'Save'

        /// <summary>
        /// Permet de sauvegarder la pile
        /// </summary>
        /// <returns>bool</returns>
        public bool Save ()
        {
            try
            {
                using (Stream stream = File.Open("QueuePriority.bin", FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    BinaryFormatter formatter = new BinaryFormatter();
                    formatter.Serialize(stream, items);
                    stream.Close();
                    stream.Dispose();
                }

                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Permet de restaures la pile de priorit
        /// </summary>
        /// <returns></returns>
        public bool Reload()
        {
            PriorityQueueItem<TValue, TPriority>[] temp;
            try
            {
                using (Stream stream = File.Open("QueuePriority.bin", FileMode.Open, FileAccess.Read, FileShare.None))
                {
                    BinaryFormatter formatter = new BinaryFormatter();
                    temp = (PriorityQueueItem<TValue, TPriority>[])formatter.Deserialize(stream);
                    stream.Close();
                    stream.Dispose();
                }

                if (temp.Length > 0)
                    items = (PriorityQueueItem<TValue, TPriority>[])temp.Clone();

                return true;
            }
            catch
            {
                return false;
            }
        }          

        #endregion

    }
}

   
    
    
  








Related examples in the same category

1.Put elements into a queue
2.Put user-defined objects to Queue collection
3.Implements the queue data type using an arrayImplements the queue data type using an array
4.A queue class for charactersA queue class for characters
5.illustrates the use of a Queueillustrates the use of a Queue
6.Queue testQueue test
7.Add exception handling to the queue classesAdd exception handling to the queue classes
8.Demonstrate the Queue classDemonstrate the Queue class
9.Queue(T) Class represents a first-in, first-out collection of objects.
10.Priority Queue (2)
11.Dequeue
12.Implements a non-locking queue
13.Task queue
14.Cyclic Queue
15.Syncronized Queue