PriorityQueue.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. using System;
  2. using System.Collections;
  3. namespace BenTools.Data
  4. {
  5. public interface IPriorityQueue : ICollection, ICloneable, IList
  6. {
  7. int Push(object O);
  8. object Pop();
  9. object Peek();
  10. void Update(int i);
  11. }
  12. public class BinaryPriorityQueue : IPriorityQueue, ICollection, ICloneable, IList
  13. {
  14. protected ArrayList InnerList = new ArrayList();
  15. protected IComparer Comparer;
  16. #region contructors
  17. public BinaryPriorityQueue() : this(System.Collections.Comparer.Default)
  18. {}
  19. public BinaryPriorityQueue(IComparer c)
  20. {
  21. Comparer = c;
  22. }
  23. public BinaryPriorityQueue(int C) : this(System.Collections.Comparer.Default,C)
  24. {}
  25. public BinaryPriorityQueue(IComparer c, int Capacity)
  26. {
  27. Comparer = c;
  28. InnerList.Capacity = Capacity;
  29. }
  30. protected BinaryPriorityQueue(ArrayList Core, IComparer Comp, bool Copy)
  31. {
  32. if(Copy)
  33. InnerList = Core.Clone() as ArrayList;
  34. else
  35. InnerList = Core;
  36. Comparer = Comp;
  37. }
  38. #endregion
  39. protected void SwitchElements(int i, int j)
  40. {
  41. object h = InnerList[i];
  42. InnerList[i] = InnerList[j];
  43. InnerList[j] = h;
  44. }
  45. protected virtual int OnCompare(int i, int j)
  46. {
  47. return Comparer.Compare(InnerList[i],InnerList[j]);
  48. }
  49. #region public methods
  50. /// <summary>
  51. /// Push an object onto the PQ
  52. /// </summary>
  53. /// <param name="O">The new object</param>
  54. /// <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>
  55. public int Push(object O)
  56. {
  57. int p = InnerList.Count,p2;
  58. InnerList.Add(O); // 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 object Pop()
  79. {
  80. object result = InnerList[0];
  81. int p = 0,p1,p2,pn;
  82. InnerList[0] = InnerList[InnerList.Count-1];
  83. InnerList.RemoveAt(InnerList.Count-1);
  84. do
  85. {
  86. pn = p;
  87. p1 = 2*p+1;
  88. p2 = 2*p+2;
  89. if(InnerList.Count>p1 && OnCompare(p,p1)>0) // links kleiner
  90. p = p1;
  91. if(InnerList.Count>p2 && OnCompare(p,p2)>0) // rechts noch kleiner
  92. p = p2;
  93. if(p==pn)
  94. break;
  95. SwitchElements(p,pn);
  96. }while(true);
  97. return result;
  98. }
  99. /// <summary>
  100. /// Notify the PQ that the object at position i has changed
  101. /// and the PQ needs to restore order.
  102. /// Since you dont have access to any indexes (except by using the
  103. /// explicit IList.this) you should not call this function without knowing exactly
  104. /// what you do.
  105. /// </summary>
  106. /// <param name="i">The index of the changed object.</param>
  107. public void Update(int i)
  108. {
  109. int p = i,pn;
  110. int p1,p2;
  111. do // aufsteigen
  112. {
  113. if(p==0)
  114. break;
  115. p2 = (p-1)/2;
  116. if(OnCompare(p,p2)<0)
  117. {
  118. SwitchElements(p,p2);
  119. p = p2;
  120. }
  121. else
  122. break;
  123. }while(true);
  124. if(p<i)
  125. return;
  126. do // absteigen
  127. {
  128. pn = p;
  129. p1 = 2*p+1;
  130. p2 = 2*p+2;
  131. if(InnerList.Count>p1 && OnCompare(p,p1)>0) // links kleiner
  132. p = p1;
  133. if(InnerList.Count>p2 && OnCompare(p,p2)>0) // rechts noch kleiner
  134. p = p2;
  135. if(p==pn)
  136. break;
  137. SwitchElements(p,pn);
  138. }while(true);
  139. }
  140. /// <summary>
  141. /// Get the smallest object without removing it.
  142. /// </summary>
  143. /// <returns>The smallest object</returns>
  144. public object Peek()
  145. {
  146. if(InnerList.Count>0)
  147. return InnerList[0];
  148. return null;
  149. }
  150. public bool Contains(object value)
  151. {
  152. return InnerList.Contains(value);
  153. }
  154. public void Clear()
  155. {
  156. InnerList.Clear();
  157. }
  158. public int Count
  159. {
  160. get
  161. {
  162. return InnerList.Count;
  163. }
  164. }
  165. IEnumerator IEnumerable.GetEnumerator()
  166. {
  167. return InnerList.GetEnumerator();
  168. }
  169. public void CopyTo(Array array, int index)
  170. {
  171. InnerList.CopyTo(array,index);
  172. }
  173. public object Clone()
  174. {
  175. return new BinaryPriorityQueue(InnerList,Comparer,true);
  176. }
  177. public bool IsSynchronized
  178. {
  179. get
  180. {
  181. return InnerList.IsSynchronized;
  182. }
  183. }
  184. public object SyncRoot
  185. {
  186. get
  187. {
  188. return this;
  189. }
  190. }
  191. #endregion
  192. #region explicit implementation
  193. bool IList.IsReadOnly
  194. {
  195. get
  196. {
  197. return false;
  198. }
  199. }
  200. object IList.this[int index]
  201. {
  202. get
  203. {
  204. return InnerList[index];
  205. }
  206. set
  207. {
  208. InnerList[index] = value;
  209. Update(index);
  210. }
  211. }
  212. int IList.Add(object o)
  213. {
  214. return Push(o);
  215. }
  216. void IList.RemoveAt(int index)
  217. {
  218. throw new NotSupportedException();
  219. }
  220. void IList.Insert(int index, object value)
  221. {
  222. throw new NotSupportedException();
  223. }
  224. void IList.Remove(object value)
  225. {
  226. throw new NotSupportedException();
  227. }
  228. int IList.IndexOf(object value)
  229. {
  230. throw new NotSupportedException();
  231. }
  232. bool IList.IsFixedSize
  233. {
  234. get
  235. {
  236. return false;
  237. }
  238. }
  239. public static BinaryPriorityQueue Syncronized(BinaryPriorityQueue P)
  240. {
  241. return new BinaryPriorityQueue(ArrayList.Synchronized(P.InnerList),P.Comparer,false);
  242. }
  243. public static BinaryPriorityQueue ReadOnly(BinaryPriorityQueue P)
  244. {
  245. return new BinaryPriorityQueue(ArrayList.ReadOnly(P.InnerList),P.Comparer,false);
  246. }
  247. #endregion
  248. }
  249. }