Priority Queue (2) : Queue « Collections Data Structure « C# / C Sharp






Priority Queue (2)

       
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SQLToolbox.Lib
{
  /// <summary>
  /// Represents a strongly typed priority queue of objects. 
  /// Objects are ordered in the priority queue according to the provided ordering comparator 
  /// (from smallest to largest) and not by the order of the insertion as in the regular queue.
  /// Provides methods to add(enqueue) and remove(dequeue) object from ordered queue. 
  /// </summary>
  /// <remarks> PriorityQueue(Of T) is implemented on the basis of List(Of T) and intentionally does not 
  /// hide base class functions that can possibly invalidate the queue ordering. After operations 
  /// that manipulates with list objects of the list itself (adding/removing) You have to restore queue 
  /// ordering by using AdjustHeap methods.</remarks>
  public class PriorityQueue<T> : List<T>
  {
    /// <summary>
    /// Initializes a new instance of the PriorityQueue class that is empty, 
    /// has the default initial capacity, default comparator for the items.
    /// </summary>
    public PriorityQueue()
    {
      comparer = Comparer<T>.Default;
    }

    /// <summary>
    /// Initializes a new instance of the PriorityQueue class that is empty, 
    /// has the default initial capacity, and uses the specified IComparer. 
    /// </summary>
    /// <param name="comparer">The IComparer implementation to use when comparing items.</param>
    public PriorityQueue(IComparer<T> comparer)
    {
      this.comparer = comparer;
    }


    /// <summary>
    /// Initializes a new instance of the PriorityQueue class that is empty, 
    /// has the specified initial capacity and default comparator for the items.        
    /// </summary>
    /// <param name="capacity">The initial number of elements that the queue can contain.</param>
    public PriorityQueue(int capacity)
      : base(capacity)
    {
      comparer = Comparer<T>.Default;
    }

    /// <summary>
    /// Initializes a new instance of the PriorityQueue class that is empty, 
    /// has the specified initial capacity and comparator for the items.        
    /// </summary>
    /// <param name="capacity">The initial number of elements that the queue can contain.</param>
    /// <param name="comparer">The IComparer implementation to use when comparing items.</param>
    public PriorityQueue(int capacity, IComparer<T> comparer)
      : base(capacity)
    {
      this.comparer = comparer;
    }

    /// <summary>
    /// Returns the the smallest (first) object of the Queue without removing it. 
    /// </summary>
    /// <returns>The object at the beginning of the Queue.</returns>
    public T Peek()
    {
      return this[0];
    }

    /// <summary>
    /// Adds an object to the Priority Queue. 
    /// </summary>
    /// <param name="item">The object to add to the Queue.</param>
    public void Enqueue(T item)
    {
      Add(item);
      AdjustHeap(Count - 1);
    }

    /// <summary>
    /// Adds the elements of an ICollection to queue. 
    /// </summary>
    /// <param name="collection">The ICollection whose elements should be added to the queue</param>
    public void EnqueueRange(IEnumerable<T> collection)
    {
      int pcount = Count;
      AddRange(collection);
      AdjustHeap(pcount, Count - pcount);
    }

    /// <summary>
    /// Removes and returns the smallest object of the Queue. 
    /// </summary>
    /// <returns>The smallest object that is removed from the beginning of the Queue. </returns>
    public T Dequeue()
    {
      int last = Count - 1;
      swap(0, last);
      T res = this[last];

      this.RemoveAt(last);
      AdjustHeap(0);

      return res;
    }

    /// <summary>
    /// Rebuild heap after change of one heap element
    /// </summary>
    /// <param name="position">Position of changed item</param>
    public void AdjustHeap(int position)
    {
      int up = position;
      while (up > 0)
      {
        int parent = (up - 1) / 2;

        if (comparer.Compare(this[parent], this[up]) <= 0)
          break;

        swap(parent, up);
        up = parent;
      }
      if (up != position)
        return;

      int down = position;
      while (down * 2 + 1 < Count)
      {
        int child = down * 2 + 1;
        if (child + 1 < Count &&
          comparer.Compare(this[child + 1], this[child]) <= 0)
          child++;

        if (comparer.Compare(this[down], this[child]) <= 0)
          break;

        swap(child, down);
        down = child;
      }
    }

    /// <summary>
    /// Rebuild heap structure of the list after change of element range
    /// </summary>
    /// <remarks>Can be used to restore heap structure of the Priority Queue after changes were 
    /// made to part of the underlying array</remarks>
    public void AdjustHeap(int from, int count)
    {
      for (int i = 0; i < count; ++i)
        AdjustHeap(from + i);
    }

    /// <summary>
    /// Rebuild heap structure of the changed list
    /// </summary>
    /// <remarks>Can be used to restore heap structure of the Priority Queue after changes were 
    /// made to underlying array</remarks>
    public void AdjustHeap()
    {
      AdjustHeap(0, (Count + 1) / 2);
    }


    private void swap(int i, int j)
    {
      T t = this[i];
      this[i] = this[j];
      this[j] = t;
    }

    private readonly IComparer<T> comparer;

    /// <summary>
    /// Gets the IComparer for the queue. 
    /// </summary>
    public IComparer<T> Comparer
    {
      get { return comparer; }
    }
  }
}

/*
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;


//documentation warning - no need to document unit tests
#pragma warning disable 1591
namespace SQLToolbox.Lib.UnitTests
{
  /// <summary>
  /// Write the summary for the test class here.
  /// </summary>
  [TestFixture]
  public class PriorityQueueTest
  {

    public bool peek_checkPQ<T>(PriorityQueue<T> pq)
    {
      IComparer<T> c = pq.Comparer;

      for (int i = 0; i < pq.Count; i++)
      {
        int child = 2 * i + 1;
        if (child >= pq.Count)
          break;

        if (c.Compare(pq[i], pq[child]) > 0)
          return false;

        ++child;
        if (child >= pq.Count)
          break;

        if (c.Compare(pq[i], pq[child]) > 0)
          return false;
      }
      return true;
    }

    public bool pop_checkPQ<T>(PriorityQueue<T> pq)
    {
      IComparer<T> c = pq.Comparer;

      while (pq.Count > 1)
      {
        T pop = pq.Dequeue();
        if (c.Compare(pop, pq.Peek()) > 0)
          return false;
      }

      return true;
    }

    public bool pop_fullcheckPQ<T>(PriorityQueue<T> pq)
    {
      IComparer<T> c = pq.Comparer;

      while (pq.Count > 1)
      {
        T pop = pq.Dequeue();
        for (int i = 0; i < pq.Count; ++i)
        {
          if (c.Compare(pop, pq[i]) > 0)
            return false;
        }
      }

      return true;
    }

    public class abscomparer : IComparer<int>
    {
      public int Compare(int x, int y)
      {
        return Math.Abs(x) - Math.Abs(y);
      }
    }

    [Test]
    public void p1()
    {

      PriorityQueue<int> pq = new PriorityQueue<int>(new abscomparer());
      int s = 0;
      pq.Enqueue(3); s++;
      pq.Enqueue(2); s++;
      pq.Enqueue(2); s++;
      pq.Enqueue(4); s++;
      pq.Enqueue(1); s++;
      pq.Enqueue(-5); s++;
      pq.Enqueue(-3); s++;

      pq.Sort(new abscomparer());
      pq.AdjustHeap();

      pq.Sort();
      pq.AdjustHeap();

      pq.EnqueueRange(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
      s += 10;

      Assert.AreEqual(s, pq.Count);

      Assert.IsTrue(pq.Contains(2));
      Assert.IsTrue(pq.Contains(4));
      Assert.IsTrue(pq.Contains(-5));
      Assert.AreEqual(0, pq.IndexOf(1));

      Assert.IsTrue(peek_checkPQ(pq));
      Assert.IsTrue(pop_fullcheckPQ(pq));
    }

    [Test]
    public void longRandomTest()
    {
      for (int longloop = 0; longloop < 2; longloop++)
      {

        PriorityQueue<int> pq = new PriorityQueue<int>();

        Random rnd = new Random();


        int num = rnd.Next(2000, 4000);

        for (int i = 0; i < num; ++i)
          pq.Enqueue(rnd.Next(-1000, 1000));


        Assert.AreEqual(num, pq.Count);
        Assert.IsTrue(peek_checkPQ(pq));
        Assert.AreEqual(num, pq.Count);
        Assert.IsTrue(pop_checkPQ(pq));

        //System.Diagnostics.Trace.WriteLine("loop:" + longloop.ToString());
      }
    }

    [Test]
    public void DynamicTest()
    {
      PriorityQueue<int> pq = new PriorityQueue<int>();

      Random rnd = new Random();

      int num = rnd.Next(1000);

      for (int i = 0; i < num; ++i)
        pq.Enqueue(rnd.Next(-1000, 1000));

      for (int i = 0; i < 1000; ++i)
      {
        pq.Enqueue(rnd.Next(-1000, 1000));
        int pop = pq.Dequeue();
        Assert.IsTrue(pop <= pq.Peek());
        Assert.AreEqual(num, pq.Count);
        Assert.IsTrue(peek_checkPQ(pq));
      }
    }
  }
}

*/

   
    
    
    
    
    
    
  








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.Priority Queue
10.Queue(T) Class represents a first-in, first-out collection of objects.
11.Dequeue
12.Implements a non-locking queue
13.Task queue
14.Cyclic Queue
15.Syncronized Queue