39 using System.Collections.Generic;
40 using System.Runtime.InteropServices;
41 using System.Diagnostics;
43 namespace Com.Mission_Base.Pbl
56 [DebuggerDisplay(
"Count = {Count}")]
57 public class PriorityQueue<T> : List<T>, IList<T> where T : IComparable<T>
59 private readonly
object _lock;
60 private readonly IComparer<T> _comparer;
64 private int CompareItems(T left, T right)
66 if (_comparer == null)
76 return left.CompareTo(right);
78 return _comparer.Compare(left, right);
81 private int LastParentIndex
91 private void EnsureHeapConditionDownward(
int index)
93 int lastParentIndex = LastParentIndex;
94 if (index <= lastParentIndex)
96 var entry = base[index];
100 while (index <= lastParentIndex)
104 int childIndex = 2 * index + 1;
106 var child = base[childIndex];
111 if (childIndex < Count - 1)
115 int rightChildIndex = childIndex + 1;
116 var rightChild = base[rightChildIndex];
118 if (CompareItems(rightChild, child) < 0)
123 childIndex = rightChildIndex;
127 if (CompareItems(entry, child) <= 0)
136 base[childIndex] = entry;
147 private int EnsureHeapConditionUpward(
int index)
151 var entry = base[index];
159 int parentIndex = (index - 1) / 2;
160 var parent =
this[parentIndex];
162 if (CompareItems(entry, parent) >= 0)
171 base[parentIndex] = entry;
172 base[index] = parent;
189 public void EnsureHeapCondition(
int index)
191 int rc = EnsureHeapConditionUpward(index);
194 EnsureHeapConditionDownward(index);
204 public void EnsureHeapCondition()
210 for (
int index = LastParentIndex; index >= 0; index--)
212 EnsureHeapConditionDownward(index);
216 private void HeapRemoveAt(
int index)
218 if (index < 0 || index >= Count)
220 throw new ArgumentOutOfRangeException(
string.Format(
"Index {0} is less than 0, or index is equal to or greater than priority queue count {1}.", index, Count));
222 else if (index == Count - 1)
224 base.RemoveAt(index);
230 base[index] = base[Count - 1];
231 base.RemoveAt(Count - 1);
238 EnsureHeapCondition(index);
248 public PriorityQueue()
250 _lock =
new object();
256 public PriorityQueue(IEnumerable<T> enumerable)
259 _lock =
new object();
260 EnsureHeapCondition();
266 public PriorityQueue(Int32 capacity)
269 _lock =
new object();
275 public PriorityQueue(IComparer<T> comparer)
277 _comparer = comparer;
278 _lock =
new object();
284 public PriorityQueue(IEnumerable<T> enumerable, IComparer<T> comparer)
287 _comparer = comparer;
288 _lock =
new object();
289 EnsureHeapCondition();
295 public PriorityQueue(Int32 capacity, IComparer<T> comparer)
298 _comparer = comparer;
299 _lock =
new object();
303 #region Queue methods
316 public void Enqueue(T item)
319 EnsureHeapConditionUpward(Count - 1);
337 throw new InvalidOperationException(
"The priority queue is empty.");
339 var result = base[0];
359 throw new InvalidOperationException(
"The priority queue is empty.");
381 public new T
this[
int index]
383 get {
return base[index]; }
387 EnsureHeapCondition(index);
402 public new void Add(T item)
416 public new void AddRange(IEnumerable<T> collection)
418 base.AddRange(collection);
419 EnsureHeapCondition();
438 public new void Insert(
int index, T item)
457 public new void InsertRange(
int index, IEnumerable<T> collection)
459 base.InsertRange(index, collection);
460 EnsureHeapCondition();
472 public new void RemoveAt(
int index)
489 public new bool Remove(T item)
491 int index = IndexOf(item);
512 public new int RemoveAll(Predicate<T> match)
514 var result = base.RemoveAll(match);
517 EnsureHeapCondition();
534 public new void RemoveRange(
int index,
int count)
536 base.RemoveRange(index, count);
537 if (index > LastParentIndex)
539 EnsureHeapCondition();
549 public new void Reverse()
553 throw new InvalidOperationException(
"A priority queue cannot be reversed.");
563 public new void Reverse(
int index,
int count)
565 if (index > LastParentIndex)
567 throw new InvalidOperationException(
"A priority queue cannot be partially reversed.");
569 base.Reverse(index, count);
580 public new void Sort()
584 if (_comparer != null)
586 base.Sort(_comparer);
601 public new void Sort(IComparer<T> comparer)
605 if (!ReferenceEquals(comparer, _comparer))
607 throw new InvalidOperationException(
"A priority queue cannot be sorted with a comparer other than the one specified for the priority queue.");
609 base.Sort(_comparer);
619 public new void Sort(
int index,
int count, IComparer<T> comparer)
623 if (!ReferenceEquals(comparer, _comparer) || index != 0 || count != Count)
625 throw new InvalidOperationException(
"A priority queue cannot be partially sorted.");
627 base.Sort(index, count, _comparer);
637 public new void Sort(Comparison<T> comparison)
641 throw new InvalidOperationException(
"A priority queue cannot be sorted with a comparison.");
654 public object SyncRoot
656 get {
return _lock; }
665 public bool IsSynchronized
667 get {
return false; }
676 public IComparer<T> Comparer {
get {
return _comparer; } }