PriorityQueue.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. //
  2. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  3. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  4. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  5. // PURPOSE. IT CAN BE DISTRIBUTED FREE OF CHARGE AS LONG AS THIS HEADER
  6. // REMAINS UNCHANGED.
  7. //
  8. // Email: gustavo_franco@hotmail.com
  9. //
  10. // Copyright (C) 2006 Franco, Gustavo
  11. //
  12. // EDIT 2010 by Christoph Husse: Update() method didn't work correctly. Also
  13. // each item is now carrying an index, so that updating can be performed
  14. // efficiently.
  15. //
  16. using System;
  17. using System.Collections;
  18. using System.Collections.Generic;
  19. using System.Diagnostics;
  20. internal class PriorityQueue<T> where T : IIndexedObject
  21. {
  22. protected List<T> InnerList = new List<T>();
  23. protected IComparer<T> mComparer;
  24. public PriorityQueue()
  25. {
  26. mComparer = Comparer<T>.Default;
  27. }
  28. public PriorityQueue(IComparer<T> comparer)
  29. {
  30. mComparer = comparer;
  31. }
  32. public PriorityQueue(IComparer<T> comparer, int capacity)
  33. {
  34. mComparer = comparer;
  35. InnerList.Capacity = capacity;
  36. }
  37. protected void SwitchElements(int i, int j)
  38. {
  39. T h = InnerList[i];
  40. InnerList[i] = InnerList[j];
  41. InnerList[j] = h;
  42. InnerList[i].Index = i;
  43. InnerList[j].Index = j;
  44. }
  45. protected virtual int OnCompare(int i, int j)
  46. {
  47. return mComparer.Compare(InnerList[i], InnerList[j]);
  48. }
  49. /// <summary>
  50. /// Push an object onto the PQ
  51. /// </summary>
  52. /// <param name="O">The new object</param>
  53. /// <returns>The index in the list where the object is _now_. This will change when objects are taken from or put onto the PQ.</returns>
  54. public int Push(T item)
  55. {
  56. int p = InnerList.Count, p2;
  57. item.Index = InnerList.Count;
  58. InnerList.Add(item); // E[p] = O
  59. do
  60. {
  61. if (p == 0)
  62. break;
  63. p2 = (p - 1) / 2;
  64. if (OnCompare(p, p2) < 0)
  65. {
  66. SwitchElements(p, p2);
  67. p = p2;
  68. }
  69. else
  70. break;
  71. } while (true);
  72. return p;
  73. }
  74. /// <summary>
  75. /// Get the smallest object and remove it.
  76. /// </summary>
  77. /// <returns>The smallest object</returns>
  78. public T Pop()
  79. {
  80. T result = InnerList[0];
  81. int p = 0, p1, p2, pn;
  82. InnerList[0] = InnerList[InnerList.Count - 1];
  83. InnerList[0].Index = 0;
  84. InnerList.RemoveAt(InnerList.Count - 1);
  85. result.Index = -1;
  86. do
  87. {
  88. pn = p;
  89. p1 = 2 * p + 1;
  90. p2 = 2 * p + 2;
  91. if (InnerList.Count > p1 && OnCompare(p, p1) > 0) // links kleiner
  92. p = p1;
  93. if (InnerList.Count > p2 && OnCompare(p, p2) > 0) // rechts noch kleiner
  94. p = p2;
  95. if (p == pn)
  96. break;
  97. SwitchElements(p, pn);
  98. } while (true);
  99. return result;
  100. }
  101. /// <summary>
  102. /// Notify the PQ that the object at position i has changed
  103. /// and the PQ needs to restore order.
  104. /// </summary>
  105. public void Update(T item)
  106. {
  107. int count = InnerList.Count;
  108. // usually we only need to switch some elements, since estimation won't change that much.
  109. while ((item.Index - 1 >= 0) && (OnCompare(item.Index - 1, item.Index) > 0))
  110. {
  111. SwitchElements(item.Index - 1, item.Index);
  112. }
  113. while ((item.Index + 1 < count) && (OnCompare(item.Index + 1, item.Index) < 0))
  114. {
  115. SwitchElements(item.Index + 1, item.Index);
  116. }
  117. }
  118. /// <summary>
  119. /// Get the smallest object without removing it.
  120. /// </summary>
  121. /// <returns>The smallest object</returns>
  122. public T Peek()
  123. {
  124. if (InnerList.Count > 0)
  125. return InnerList[0];
  126. return default(T);
  127. }
  128. public void Clear()
  129. {
  130. InnerList.Clear();
  131. }
  132. public int Count
  133. {
  134. get { return InnerList.Count; }
  135. }
  136. }