PriorityQueue.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. using System.Text;
  2. namespace System.Collections.Generic
  3. {
  4. /// <summary>
  5. /// Generic class for priority queue, it is based on a limited sorted array
  6. /// </summary>
  7. /// <typeparam name="TObj">Type of data object, must implement IComparable interface</typeparam>
  8. /// <remarks>Lower weights in queue has higher priority</remarks>
  9. class PriorityQueue<TObj>
  10. {
  11. /// <summary>
  12. /// Sorted list of objects, acts like a binary tree
  13. /// </summary>
  14. private List<TObj> Queue = null;
  15. /// <summary>
  16. /// Returns count of elements in queue
  17. /// </summary>
  18. public int Count
  19. {
  20. get { return Queue.Count; }
  21. }
  22. /// <summary>
  23. /// Public constructor
  24. /// </summary>
  25. /// <param name="_queueSize">Maximum size of queue</param>
  26. /// <exception cref="System.Exception">Throws when TObj does not implement IComparable interface</exception>
  27. public PriorityQueue(int _queueSize)
  28. {
  29. if (typeof(TObj).GetInterface("IComparable") == null)
  30. throw new Exception("PriorityQueue: Templated class " + typeof(TObj) + " does not implement IComparable.");
  31. Queue = new List<TObj>(_queueSize);
  32. }
  33. public override string ToString()
  34. {
  35. StringBuilder result = new StringBuilder();
  36. for (int i = this.Count-1; i >= 0; i--)
  37. {
  38. if (i < this.Count-1)
  39. result.Append(',');
  40. result.Append(Queue[i]);
  41. }
  42. return result.ToString();
  43. }
  44. /// <summary>
  45. /// Clears all elements in the queue
  46. /// </summary>
  47. public void Clear()
  48. {
  49. Queue.Clear();
  50. }
  51. /// <summary>
  52. /// Inserts an element in the queue, in the proper position according with weight
  53. /// </summary>
  54. /// <param name="_obj">Object to enqueue, ignores if it is null</param>
  55. public void Enqueue(TObj _obj)
  56. {
  57. if (_obj == null)
  58. return;
  59. if (Queue.Count == 0) // Fast special case for empty queue
  60. {
  61. Queue.Add(_obj);
  62. return;
  63. }
  64. // BinarySearch for element or best position
  65. int posNew = Queue.BinarySearch(_obj);
  66. // Inserts element in proper sorted position
  67. if (posNew >= 0) // Similar element exists on queue, inserts new before
  68. Queue.Insert(posNew, _obj);
  69. else
  70. {
  71. posNew = ~posNew; // Binary invertion, as specified in BinarySearch() method help
  72. if (posNew == Queue.Count)
  73. Queue.Add(_obj);
  74. else
  75. Queue.Insert(posNew, _obj);
  76. }
  77. }
  78. /// <summary>
  79. /// Extracts element from start of the queue
  80. /// </summary>
  81. /// <returns>Reference to enqueued object, null if queue is empty</returns>
  82. public TObj Dequeue()
  83. {
  84. if (Queue.Count == 0)
  85. return default(TObj);
  86. TObj _obj = Queue[0];
  87. Queue.RemoveAt(0);
  88. return _obj;
  89. }
  90. /// <summary>
  91. /// Returns a reference to element from start of queue, without removing it
  92. /// </summary>
  93. /// <returns>Reference to enqueued object, null if queue is empty</returns>
  94. public TObj Root()
  95. {
  96. if (Queue.Count == 0)
  97. return default(TObj);
  98. return Queue[0];
  99. }
  100. }
  101. }