StablePriorityQueue.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. namespace IFramework.Queue
  5. {
  6. /// <summary>
  7. /// 稳定优先级队列
  8. /// </summary>
  9. /// <typeparam name="T">节点元素类型</typeparam>
  10. public sealed class StablePriorityQueue<T> : IFixedSizePriorityQueue<T, float> where T : StablePriorityQueueNode
  11. {
  12. private int _numNodes;
  13. private T[] _nodes;
  14. private long _numNodesEverEnqueued;
  15. /// <summary>
  16. /// Ctor
  17. /// </summary>
  18. /// <param name="capicty">允许入队的最大数量(如果超过将导致未定义的操作)</param>
  19. public StablePriorityQueue(int capicty = 4)
  20. {
  21. #if DEBUG
  22. if (capicty <= 0)
  23. {
  24. throw new InvalidOperationException("New queue size cannot be smaller than 1");
  25. }
  26. #endif
  27. _numNodes = 0;
  28. _nodes = new T[capicty + 1];
  29. _numNodesEverEnqueued = 0;
  30. }
  31. /// <summary>
  32. /// 返回队列里的元素数量<br />
  33. /// O(1)
  34. /// </summary>
  35. public int count
  36. {
  37. get
  38. {
  39. return _numNodes;
  40. }
  41. }
  42. /// <summary>
  43. /// 队列中可以入队的最大数量<br />
  44. /// 如果入队数量超过队列的大小(Count == MaxSize时Enqueue()),会导致未定义的操作<br />
  45. /// O(1)
  46. /// </summary>
  47. public int capcity
  48. {
  49. get
  50. {
  51. return _nodes.Length - 1;
  52. }
  53. }
  54. /// <summary>
  55. /// 移除队列里的所有元素<br />
  56. /// O(n) (因此请勿频繁使用此方法)
  57. /// </summary>
  58. #if NET_VERSION_4_5
  59. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  60. #endif
  61. public void Clear()
  62. {
  63. Array.Clear(_nodes, 1, _numNodes);
  64. _numNodes = 0;
  65. }
  66. /// <summary>
  67. /// 判断当前元素是否在队列中<br />
  68. /// 如果元素被添加到其他的队列,则结果是不确定的,
  69. /// 除非调用了之前队列的ResetNode(node)方法<br />
  70. /// O(1)
  71. /// </summary>
  72. /// <param name="node">需要判断的元素</param>
  73. /// <returns>如果队列包含这个元素则返回true 否则为false</returns>
  74. #if NET_VERSION_4_5
  75. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  76. #endif
  77. public bool Contains(T node)
  78. {
  79. #if DEBUG
  80. if (node == null)
  81. {
  82. throw new ArgumentNullException("node");
  83. }
  84. if (node.position < 0 || node.position >= _nodes.Length)
  85. {
  86. throw new InvalidOperationException("node.position has been corrupted. Did you change it manually?");
  87. }
  88. #endif
  89. return (_nodes[node.position] == node);
  90. }
  91. /// <summary>
  92. /// 将优先级节点入队,优先级值小的将会排在队列前面,优先级相同的节点以先进先出排序<br />
  93. /// 如果队列是满的,则执行未定义的操作<br />
  94. /// 如果节点元素已经入队了,则执行未定义的操作<br />
  95. /// 如果节点已经在队列中了,除非在此之前调用了之前队列的ResetNode(node)方法,否则结果是未定义的<br />
  96. /// O(log n)
  97. /// </summary>
  98. #if NET_VERSION_4_5
  99. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  100. #endif
  101. public void Enqueue(T node, float priority)
  102. {
  103. #if DEBUG
  104. if (node == null)
  105. {
  106. throw new ArgumentNullException("node");
  107. }
  108. if (_numNodes >= _nodes.Length - 1)
  109. {
  110. throw new InvalidOperationException($"Queue is full - node cannot be added: {node}");
  111. }
  112. if (Contains(node))
  113. {
  114. throw new InvalidOperationException($"Node is already enqueued: {node}");
  115. }
  116. #endif
  117. node.priority = priority;
  118. _numNodes++;
  119. _nodes[_numNodes] = node;
  120. node.position = _numNodes;
  121. node.insertPosition = _numNodesEverEnqueued++;
  122. CascadeUp(node);
  123. }
  124. #if NET_VERSION_4_5
  125. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  126. #endif
  127. private void CascadeUp(T node)
  128. {
  129. int parent;
  130. if (node.position > 1)
  131. {
  132. parent = node.position >> 1;
  133. T parentNode = _nodes[parent];
  134. if (HasHigherPriority(parentNode, node))
  135. return;
  136. _nodes[node.position] = parentNode;
  137. parentNode.position = node.position;
  138. node.position = parent;
  139. }
  140. else
  141. {
  142. return;
  143. }
  144. while (parent > 1)
  145. {
  146. parent >>= 1;
  147. T parentNode = _nodes[parent];
  148. if (HasHigherPriority(parentNode, node))
  149. break;
  150. _nodes[node.position] = parentNode;
  151. parentNode.position = node.position;
  152. node.position = parent;
  153. }
  154. _nodes[node.position] = node;
  155. }
  156. #if NET_VERSION_4_5
  157. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  158. #endif
  159. private void CascadeDown(T node)
  160. {
  161. int finalQueueIndex = node.position;
  162. int childLeftIndex = 2 * finalQueueIndex;
  163. if (childLeftIndex > _numNodes)
  164. {
  165. return;
  166. }
  167. int childRightIndex = childLeftIndex + 1;
  168. T childLeft = _nodes[childLeftIndex];
  169. if (HasHigherPriority(childLeft, node))
  170. {
  171. if (childRightIndex > _numNodes)
  172. {
  173. node.position = childLeftIndex;
  174. childLeft.position = finalQueueIndex;
  175. _nodes[finalQueueIndex] = childLeft;
  176. _nodes[childLeftIndex] = node;
  177. return;
  178. }
  179. T childRight = _nodes[childRightIndex];
  180. if (HasHigherPriority(childLeft, childRight))
  181. {
  182. childLeft.position = finalQueueIndex;
  183. _nodes[finalQueueIndex] = childLeft;
  184. finalQueueIndex = childLeftIndex;
  185. }
  186. else
  187. {
  188. childRight.position = finalQueueIndex;
  189. _nodes[finalQueueIndex] = childRight;
  190. finalQueueIndex = childRightIndex;
  191. }
  192. }
  193. else if (childRightIndex > _numNodes)
  194. {
  195. return;
  196. }
  197. else
  198. {
  199. T childRight = _nodes[childRightIndex];
  200. if (HasHigherPriority(childRight, node))
  201. {
  202. childRight.position = finalQueueIndex;
  203. _nodes[finalQueueIndex] = childRight;
  204. finalQueueIndex = childRightIndex;
  205. }
  206. else
  207. {
  208. return;
  209. }
  210. }
  211. while (true)
  212. {
  213. childLeftIndex = 2 * finalQueueIndex;
  214. if (childLeftIndex > _numNodes)
  215. {
  216. node.position = finalQueueIndex;
  217. _nodes[finalQueueIndex] = node;
  218. break;
  219. }
  220. childRightIndex = childLeftIndex + 1;
  221. childLeft = _nodes[childLeftIndex];
  222. if (HasHigherPriority(childLeft, node))
  223. {
  224. if (childRightIndex > _numNodes)
  225. {
  226. node.position = childLeftIndex;
  227. childLeft.position = finalQueueIndex;
  228. _nodes[finalQueueIndex] = childLeft;
  229. _nodes[childLeftIndex] = node;
  230. break;
  231. }
  232. T childRight = _nodes[childRightIndex];
  233. if (HasHigherPriority(childLeft, childRight))
  234. {
  235. childLeft.position = finalQueueIndex;
  236. _nodes[finalQueueIndex] = childLeft;
  237. finalQueueIndex = childLeftIndex;
  238. }
  239. else
  240. {
  241. childRight.position = finalQueueIndex;
  242. _nodes[finalQueueIndex] = childRight;
  243. finalQueueIndex = childRightIndex;
  244. }
  245. }
  246. else if (childRightIndex > _numNodes)
  247. {
  248. node.position = finalQueueIndex;
  249. _nodes[finalQueueIndex] = node;
  250. break;
  251. }
  252. else
  253. {
  254. T childRight = _nodes[childRightIndex];
  255. if (HasHigherPriority(childRight, node))
  256. {
  257. childRight.position = finalQueueIndex;
  258. _nodes[finalQueueIndex] = childRight;
  259. finalQueueIndex = childRightIndex;
  260. }
  261. else
  262. {
  263. node.position = finalQueueIndex;
  264. _nodes[finalQueueIndex] = node;
  265. break;
  266. }
  267. }
  268. }
  269. }
  270. /// <summary>
  271. /// 对两个参数的优先级进行比较
  272. /// </summary>
  273. /// <param name="higher">第一个参数</param>
  274. /// <param name="lower">第二个参数</param>
  275. /// <returns>
  276. /// 如果第一个参数的优先级大于第二个参数则返回true,否则返回false<br />
  277. /// 如果两个参数为同一个节点,返回false
  278. /// </returns>
  279. #if NET_VERSION_4_5
  280. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  281. #endif
  282. private bool HasHigherPriority(T higher, T lower)
  283. {
  284. return (higher.priority < lower.priority ||
  285. (higher.priority == lower.priority && higher.insertPosition < lower.insertPosition));
  286. }
  287. /// <summary>
  288. /// 队列头部出队
  289. /// 如果队列为空则执行未定义的操作<br />
  290. /// O(log n)
  291. /// </summary>
  292. /// <returns>出队的元素</returns>
  293. #if NET_VERSION_4_5
  294. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  295. #endif
  296. public T Dequeue()
  297. {
  298. #if DEBUG
  299. if (_numNodes <= 0)
  300. {
  301. throw new InvalidOperationException("Cannot call Dequeue() on an empty queue");
  302. }
  303. #endif
  304. T returnMe = _nodes[1];
  305. //如果节点元素已经是最后一个节点,则直接移除
  306. if (_numNodes == 1)
  307. {
  308. _nodes[1] = null;
  309. _numNodes = 0;
  310. return returnMe;
  311. }
  312. //将节点与最后一个节点对换
  313. T formerLastNode = _nodes[_numNodes];
  314. _nodes[1] = formerLastNode;
  315. formerLastNode.position = 1;
  316. _nodes[_numNodes] = null;
  317. _numNodes--;
  318. //将formerLastNode (不再是最后一个节点)向下冒泡
  319. CascadeDown(formerLastNode);
  320. return returnMe;
  321. }
  322. /// <summary>
  323. /// 重新设置队列的大小,使其可以容纳更多的节点,当前的所有节点都会保留<br />
  324. /// 如果试图将队列大小设置成比当前队列中的数量小时,会执行未定义的操作<br />
  325. /// O(n)
  326. /// </summary>
  327. public void Resize(int maxNodes)
  328. {
  329. #if DEBUG
  330. if (maxNodes <= 0)
  331. {
  332. throw new InvalidOperationException("Queue size cannot be smaller than 1");
  333. }
  334. if (maxNodes < _numNodes)
  335. {
  336. throw new InvalidOperationException($"Called Resize({ maxNodes }), but current queue contains { _numNodes } nodes");
  337. }
  338. #endif
  339. T[] newArray = new T[maxNodes + 1];
  340. int highestIndexToCopy = Math.Min(maxNodes, _numNodes);
  341. Array.Copy(_nodes, newArray, highestIndexToCopy + 1);
  342. _nodes = newArray;
  343. }
  344. /// <summary>
  345. /// 队列的第一个元素<br />
  346. /// 如果队列为空,则执行未定义的操作<br />
  347. /// O(1)
  348. /// </summary>
  349. public T first
  350. {
  351. get
  352. {
  353. #if DEBUG
  354. if (_numNodes <= 0)
  355. {
  356. throw new InvalidOperationException("Cannot call .first on an empty queue");
  357. }
  358. #endif
  359. return _nodes[1];
  360. }
  361. }
  362. /// <summary>
  363. /// 更改队列里某个节点的优先级<br />
  364. /// <b>忘记调用这个方法会导致队列损坏!</b><br />
  365. /// 对不在这个队列中的节点元素调用这个方法会执行未定义的行为<br />
  366. /// O(log n)
  367. /// </summary>
  368. #if NET_VERSION_4_5
  369. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  370. #endif
  371. public void UpdatePriority(T node, float priority)
  372. {
  373. #if DEBUG
  374. if (node == null)
  375. {
  376. throw new ArgumentNullException("node");
  377. }
  378. if (!Contains(node))
  379. {
  380. throw new InvalidOperationException($"Cannot call UpdatePriority() on a node which is not enqueued: {node}");
  381. }
  382. #endif
  383. node.priority = priority;
  384. OnNodeUpdated(node);
  385. }
  386. #if NET_VERSION_4_5
  387. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  388. #endif
  389. private void OnNodeUpdated(T node)
  390. {
  391. //按需向上或向下冒泡更新节点
  392. int parentIndex = node.position >> 1;
  393. if (parentIndex > 0 && HasHigherPriority(node, _nodes[parentIndex]))
  394. {
  395. CascadeUp(node);
  396. }
  397. else
  398. {
  399. //如果 parentNode == node(node是根节点) 则会调用CascadeDown
  400. CascadeDown(node);
  401. }
  402. }
  403. /// <summary>
  404. /// 从队列中删除给定节点元素,这个节点不一定是队列的头<br />
  405. /// 如果节点并未在队列中,结果是未定义的,如果不确定,则先使用Contains()确认<br />
  406. /// O(log n)
  407. /// </summary>
  408. #if NET_VERSION_4_5
  409. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  410. #endif
  411. public void Remove(T node)
  412. {
  413. #if DEBUG
  414. if (node == null)
  415. {
  416. throw new ArgumentNullException("node");
  417. }
  418. if (!Contains(node))
  419. {
  420. throw new InvalidOperationException($"Cannot call Remove() on a node which is not enqueued: {node}");
  421. }
  422. #endif
  423. //如果节点元素已经是最后一个节点,则直接移除
  424. if (node.position == _numNodes)
  425. {
  426. _nodes[_numNodes] = null;
  427. _numNodes--;
  428. return;
  429. }
  430. //将节点与最后一个节点对换
  431. T formerLastNode = _nodes[_numNodes];
  432. _nodes[node.position] = formerLastNode;
  433. formerLastNode.position = node.position;
  434. _nodes[_numNodes] = null;
  435. _numNodes--;
  436. //将formerLastNode (不再是最后一个节点)按需向上或者向下冒泡排序
  437. OnNodeUpdated(formerLastNode);
  438. }
  439. /// <summary>
  440. /// 默认情况下有加入过一个队列的节点元素不能添加到另一个队列<br />
  441. /// 如果需要这么做,则在添加到另一个队列前调用当前队列的此方法<br />
  442. /// 如果节点当前在节点中或者属于其他队列,则结果是未定义的
  443. /// </summary>
  444. #if NET_VERSION_4_5
  445. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  446. #endif
  447. public void ResetNode(T node)
  448. {
  449. #if DEBUG
  450. if (node == null)
  451. {
  452. throw new ArgumentNullException("node");
  453. }
  454. if (Contains(node))
  455. {
  456. throw new InvalidOperationException("node.ResetNode was called on a node that is still in the queue");
  457. }
  458. #endif
  459. node.position = 0;
  460. }
  461. /// <summary>
  462. /// 迭代器
  463. /// </summary>
  464. /// <returns>迭代器</returns>
  465. public IEnumerator<T> GetEnumerator()
  466. {
  467. #if NET_VERSION_4_5 // ArraySegment在4.5之前没有 实现IEnumerable接口
  468. IEnumerable<T> e = new ArraySegment<T>(_nodes, 1, _numNodes);
  469. return e.GetEnumerator();
  470. #else
  471. for (int i = 1; i <= _numNodes; i++)
  472. yield return _nodes[i];
  473. #endif
  474. }
  475. IEnumerator IEnumerable.GetEnumerator()
  476. {
  477. return GetEnumerator();
  478. }
  479. }
  480. }