IntervalTree.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. using System;
  2. using System.Collections.Generic;
  3. namespace Ryujinx.Memory.WindowsShared
  4. {
  5. /// <summary>
  6. /// An Augmented Interval Tree based off of the "TreeDictionary"'s Red-Black Tree. Allows fast overlap checking of ranges.
  7. /// </summary>
  8. /// <typeparam name="K">Key</typeparam>
  9. /// <typeparam name="V">Value</typeparam>
  10. class IntervalTree<K, V> where K : IComparable<K>
  11. {
  12. private const int ArrayGrowthSize = 32;
  13. private const bool Black = true;
  14. private const bool Red = false;
  15. private IntervalTreeNode<K, V> _root = null;
  16. private int _count = 0;
  17. public int Count => _count;
  18. public IntervalTree() { }
  19. #region Public Methods
  20. /// <summary>
  21. /// Gets the values of the interval whose key is <paramref name="key"/>.
  22. /// </summary>
  23. /// <param name="key">Key of the node value to get</param>
  24. /// <param name="value">Value with the given <paramref name="key"/></param>
  25. /// <returns>True if the key is on the dictionary, false otherwise</returns>
  26. public bool TryGet(K key, out V value)
  27. {
  28. IntervalTreeNode<K, V> node = GetNode(key);
  29. if (node == null)
  30. {
  31. value = default;
  32. return false;
  33. }
  34. value = node.Value;
  35. return true;
  36. }
  37. /// <summary>
  38. /// Returns the start addresses of the intervals whose start and end keys overlap the given range.
  39. /// </summary>
  40. /// <param name="start">Start of the range</param>
  41. /// <param name="end">End of the range</param>
  42. /// <param name="overlaps">Overlaps array to place results in</param>
  43. /// <param name="overlapCount">Index to start writing results into the array. Defaults to 0</param>
  44. /// <returns>Number of intervals found</returns>
  45. public int Get(K start, K end, ref IntervalTreeNode<K, V>[] overlaps, int overlapCount = 0)
  46. {
  47. GetNodes(_root, start, end, ref overlaps, ref overlapCount);
  48. return overlapCount;
  49. }
  50. /// <summary>
  51. /// Adds a new interval into the tree whose start is <paramref name="start"/>, end is <paramref name="end"/> and value is <paramref name="value"/>.
  52. /// </summary>
  53. /// <param name="start">Start of the range to add</param>
  54. /// <param name="end">End of the range to insert</param>
  55. /// <param name="value">Value to add</param>
  56. /// <exception cref="ArgumentNullException"><paramref name="value"/> is null</exception>
  57. public void Add(K start, K end, V value)
  58. {
  59. if (value == null)
  60. {
  61. throw new ArgumentNullException(nameof(value));
  62. }
  63. BSTInsert(start, end, value, null, out _);
  64. }
  65. /// <summary>
  66. /// Removes a value from the tree, searching for it with <paramref name="key"/>.
  67. /// </summary>
  68. /// <param name="key">Key of the node to remove</param>
  69. /// <returns>Number of deleted values</returns>
  70. public int Remove(K key)
  71. {
  72. return Remove(GetNode(key));
  73. }
  74. /// <summary>
  75. /// Removes a value from the tree, searching for it with <paramref name="key"/>.
  76. /// </summary>
  77. /// <param name="nodeToDelete">Node to be removed</param>
  78. /// <returns>Number of deleted values</returns>
  79. public int Remove(IntervalTreeNode<K, V> nodeToDelete)
  80. {
  81. if (nodeToDelete == null)
  82. {
  83. return 0;
  84. }
  85. Delete(nodeToDelete);
  86. _count--;
  87. return 1;
  88. }
  89. /// <summary>
  90. /// Adds all the nodes in the dictionary into <paramref name="list"/>.
  91. /// </summary>
  92. /// <returns>A list of all values sorted by Key Order</returns>
  93. public List<V> AsList()
  94. {
  95. List<V> list = new List<V>();
  96. AddToList(_root, list);
  97. return list;
  98. }
  99. #endregion
  100. #region Private Methods (BST)
  101. /// <summary>
  102. /// Adds all values that are children of or contained within <paramref name="node"/> into <paramref name="list"/>, in Key Order.
  103. /// </summary>
  104. /// <param name="node">The node to search for values within</param>
  105. /// <param name="list">The list to add values to</param>
  106. private void AddToList(IntervalTreeNode<K, V> node, List<V> list)
  107. {
  108. if (node == null)
  109. {
  110. return;
  111. }
  112. AddToList(node.Left, list);
  113. list.Add(node.Value);
  114. AddToList(node.Right, list);
  115. }
  116. /// <summary>
  117. /// Retrieve the node reference whose key is <paramref name="key"/>, or null if no such node exists.
  118. /// </summary>
  119. /// <param name="key">Key of the node to get</param>
  120. /// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
  121. /// <returns>Node reference in the tree</returns>
  122. private IntervalTreeNode<K, V> GetNode(K key)
  123. {
  124. if (key == null)
  125. {
  126. throw new ArgumentNullException(nameof(key));
  127. }
  128. IntervalTreeNode<K, V> node = _root;
  129. while (node != null)
  130. {
  131. int cmp = key.CompareTo(node.Start);
  132. if (cmp < 0)
  133. {
  134. node = node.Left;
  135. }
  136. else if (cmp > 0)
  137. {
  138. node = node.Right;
  139. }
  140. else
  141. {
  142. return node;
  143. }
  144. }
  145. return null;
  146. }
  147. /// <summary>
  148. /// Retrieve all nodes that overlap the given start and end keys.
  149. /// </summary>
  150. /// <param name="start">Start of the range</param>
  151. /// <param name="end">End of the range</param>
  152. /// <param name="overlaps">Overlaps array to place results in</param>
  153. /// <param name="overlapCount">Overlaps count to update</param>
  154. private void GetNodes(IntervalTreeNode<K, V> node, K start, K end, ref IntervalTreeNode<K, V>[] overlaps, ref int overlapCount)
  155. {
  156. if (node == null || start.CompareTo(node.Max) >= 0)
  157. {
  158. return;
  159. }
  160. GetNodes(node.Left, start, end, ref overlaps, ref overlapCount);
  161. bool endsOnRight = end.CompareTo(node.Start) > 0;
  162. if (endsOnRight)
  163. {
  164. if (start.CompareTo(node.End) < 0)
  165. {
  166. if (overlaps.Length >= overlapCount)
  167. {
  168. Array.Resize(ref overlaps, overlapCount + ArrayGrowthSize);
  169. }
  170. overlaps[overlapCount++] = node;
  171. }
  172. GetNodes(node.Right, start, end, ref overlaps, ref overlapCount);
  173. }
  174. }
  175. /// <summary>
  176. /// Propagate an increase in max value starting at the given node, heading up the tree.
  177. /// This should only be called if the max increases - not for rebalancing or removals.
  178. /// </summary>
  179. /// <param name="node">The node to start propagating from</param>
  180. private void PropagateIncrease(IntervalTreeNode<K, V> node)
  181. {
  182. K max = node.Max;
  183. IntervalTreeNode<K, V> ptr = node;
  184. while ((ptr = ptr.Parent) != null)
  185. {
  186. if (max.CompareTo(ptr.Max) > 0)
  187. {
  188. ptr.Max = max;
  189. }
  190. else
  191. {
  192. break;
  193. }
  194. }
  195. }
  196. /// <summary>
  197. /// Propagate recalculating max value starting at the given node, heading up the tree.
  198. /// This fully recalculates the max value from all children when there is potential for it to decrease.
  199. /// </summary>
  200. /// <param name="node">The node to start propagating from</param>
  201. private void PropagateFull(IntervalTreeNode<K, V> node)
  202. {
  203. IntervalTreeNode<K, V> ptr = node;
  204. do
  205. {
  206. K max = ptr.End;
  207. if (ptr.Left != null && ptr.Left.Max.CompareTo(max) > 0)
  208. {
  209. max = ptr.Left.Max;
  210. }
  211. if (ptr.Right != null && ptr.Right.Max.CompareTo(max) > 0)
  212. {
  213. max = ptr.Right.Max;
  214. }
  215. ptr.Max = max;
  216. } while ((ptr = ptr.Parent) != null);
  217. }
  218. /// <summary>
  219. /// Insertion Mechanism for the interval tree. Similar to a BST insert, with the start of the range as the key.
  220. /// Iterates the tree starting from the root and inserts a new node where all children in the left subtree are less than <paramref name="start"/>, and all children in the right subtree are greater than <paramref name="start"/>.
  221. /// Each node can contain multiple values, and has an end address which is the maximum of all those values.
  222. /// Post insertion, the "max" value of the node and all parents are updated.
  223. /// </summary>
  224. /// <param name="start">Start of the range to insert</param>
  225. /// <param name="end">End of the range to insert</param>
  226. /// <param name="value">Value to insert</param>
  227. /// <param name="updateFactoryCallback">Optional factory used to create a new value if <paramref name="start"/> is already on the tree</param>
  228. /// <param name="outNode">Node that was inserted or modified</param>
  229. /// <returns>True if <paramref name="start"/> was not yet on the tree, false otherwise</returns>
  230. private bool BSTInsert(K start, K end, V value, Func<K, V, V> updateFactoryCallback, out IntervalTreeNode<K, V> outNode)
  231. {
  232. IntervalTreeNode<K, V> parent = null;
  233. IntervalTreeNode<K, V> node = _root;
  234. while (node != null)
  235. {
  236. parent = node;
  237. int cmp = start.CompareTo(node.Start);
  238. if (cmp < 0)
  239. {
  240. node = node.Left;
  241. }
  242. else if (cmp > 0)
  243. {
  244. node = node.Right;
  245. }
  246. else
  247. {
  248. outNode = node;
  249. if (updateFactoryCallback != null)
  250. {
  251. // Replace
  252. node.Value = updateFactoryCallback(start, node.Value);
  253. int endCmp = end.CompareTo(node.End);
  254. if (endCmp > 0)
  255. {
  256. node.End = end;
  257. if (end.CompareTo(node.Max) > 0)
  258. {
  259. node.Max = end;
  260. PropagateIncrease(node);
  261. RestoreBalanceAfterInsertion(node);
  262. }
  263. }
  264. else if (endCmp < 0)
  265. {
  266. node.End = end;
  267. PropagateFull(node);
  268. }
  269. }
  270. return false;
  271. }
  272. }
  273. IntervalTreeNode<K, V> newNode = new IntervalTreeNode<K, V>(start, end, value, parent);
  274. if (newNode.Parent == null)
  275. {
  276. _root = newNode;
  277. }
  278. else if (start.CompareTo(parent.Start) < 0)
  279. {
  280. parent.Left = newNode;
  281. }
  282. else
  283. {
  284. parent.Right = newNode;
  285. }
  286. PropagateIncrease(newNode);
  287. _count++;
  288. RestoreBalanceAfterInsertion(newNode);
  289. outNode = newNode;
  290. return true;
  291. }
  292. /// <summary>
  293. /// Removes the value from the dictionary after searching for it with <paramref name="key">.
  294. /// </summary>
  295. /// <param name="key">Tree node to be removed</param>
  296. private void Delete(IntervalTreeNode<K, V> nodeToDelete)
  297. {
  298. IntervalTreeNode<K, V> replacementNode;
  299. if (LeftOf(nodeToDelete) == null || RightOf(nodeToDelete) == null)
  300. {
  301. replacementNode = nodeToDelete;
  302. }
  303. else
  304. {
  305. replacementNode = PredecessorOf(nodeToDelete);
  306. }
  307. IntervalTreeNode<K, V> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
  308. if (tmp != null)
  309. {
  310. tmp.Parent = ParentOf(replacementNode);
  311. }
  312. if (ParentOf(replacementNode) == null)
  313. {
  314. _root = tmp;
  315. }
  316. else if (replacementNode == LeftOf(ParentOf(replacementNode)))
  317. {
  318. ParentOf(replacementNode).Left = tmp;
  319. }
  320. else
  321. {
  322. ParentOf(replacementNode).Right = tmp;
  323. }
  324. if (replacementNode != nodeToDelete)
  325. {
  326. nodeToDelete.Start = replacementNode.Start;
  327. nodeToDelete.Value = replacementNode.Value;
  328. nodeToDelete.End = replacementNode.End;
  329. nodeToDelete.Max = replacementNode.Max;
  330. }
  331. PropagateFull(replacementNode);
  332. if (tmp != null && ColorOf(replacementNode) == Black)
  333. {
  334. RestoreBalanceAfterRemoval(tmp);
  335. }
  336. }
  337. /// <summary>
  338. /// Returns the node with the largest key where <paramref name="node"/> is considered the root node.
  339. /// </summary>
  340. /// <param name="node">Root Node</param>
  341. /// <returns>Node with the maximum key in the tree of <paramref name="node"/></returns>
  342. private static IntervalTreeNode<K, V> Maximum(IntervalTreeNode<K, V> node)
  343. {
  344. IntervalTreeNode<K, V> tmp = node;
  345. while (tmp.Right != null)
  346. {
  347. tmp = tmp.Right;
  348. }
  349. return tmp;
  350. }
  351. /// <summary>
  352. /// Finds the node whose key is immediately less than <paramref name="node"/>.
  353. /// </summary>
  354. /// <param name="node">Node to find the predecessor of</param>
  355. /// <returns>Predecessor of <paramref name="node"/></returns>
  356. private static IntervalTreeNode<K, V> PredecessorOf(IntervalTreeNode<K, V> node)
  357. {
  358. if (node.Left != null)
  359. {
  360. return Maximum(node.Left);
  361. }
  362. IntervalTreeNode<K, V> parent = node.Parent;
  363. while (parent != null && node == parent.Left)
  364. {
  365. node = parent;
  366. parent = parent.Parent;
  367. }
  368. return parent;
  369. }
  370. #endregion
  371. #region Private Methods (RBL)
  372. private void RestoreBalanceAfterRemoval(IntervalTreeNode<K, V> balanceNode)
  373. {
  374. IntervalTreeNode<K, V> ptr = balanceNode;
  375. while (ptr != _root && ColorOf(ptr) == Black)
  376. {
  377. if (ptr == LeftOf(ParentOf(ptr)))
  378. {
  379. IntervalTreeNode<K, V> sibling = RightOf(ParentOf(ptr));
  380. if (ColorOf(sibling) == Red)
  381. {
  382. SetColor(sibling, Black);
  383. SetColor(ParentOf(ptr), Red);
  384. RotateLeft(ParentOf(ptr));
  385. sibling = RightOf(ParentOf(ptr));
  386. }
  387. if (ColorOf(LeftOf(sibling)) == Black && ColorOf(RightOf(sibling)) == Black)
  388. {
  389. SetColor(sibling, Red);
  390. ptr = ParentOf(ptr);
  391. }
  392. else
  393. {
  394. if (ColorOf(RightOf(sibling)) == Black)
  395. {
  396. SetColor(LeftOf(sibling), Black);
  397. SetColor(sibling, Red);
  398. RotateRight(sibling);
  399. sibling = RightOf(ParentOf(ptr));
  400. }
  401. SetColor(sibling, ColorOf(ParentOf(ptr)));
  402. SetColor(ParentOf(ptr), Black);
  403. SetColor(RightOf(sibling), Black);
  404. RotateLeft(ParentOf(ptr));
  405. ptr = _root;
  406. }
  407. }
  408. else
  409. {
  410. IntervalTreeNode<K, V> sibling = LeftOf(ParentOf(ptr));
  411. if (ColorOf(sibling) == Red)
  412. {
  413. SetColor(sibling, Black);
  414. SetColor(ParentOf(ptr), Red);
  415. RotateRight(ParentOf(ptr));
  416. sibling = LeftOf(ParentOf(ptr));
  417. }
  418. if (ColorOf(RightOf(sibling)) == Black && ColorOf(LeftOf(sibling)) == Black)
  419. {
  420. SetColor(sibling, Red);
  421. ptr = ParentOf(ptr);
  422. }
  423. else
  424. {
  425. if (ColorOf(LeftOf(sibling)) == Black)
  426. {
  427. SetColor(RightOf(sibling), Black);
  428. SetColor(sibling, Red);
  429. RotateLeft(sibling);
  430. sibling = LeftOf(ParentOf(ptr));
  431. }
  432. SetColor(sibling, ColorOf(ParentOf(ptr)));
  433. SetColor(ParentOf(ptr), Black);
  434. SetColor(LeftOf(sibling), Black);
  435. RotateRight(ParentOf(ptr));
  436. ptr = _root;
  437. }
  438. }
  439. }
  440. SetColor(ptr, Black);
  441. }
  442. private void RestoreBalanceAfterInsertion(IntervalTreeNode<K, V> balanceNode)
  443. {
  444. SetColor(balanceNode, Red);
  445. while (balanceNode != null && balanceNode != _root && ColorOf(ParentOf(balanceNode)) == Red)
  446. {
  447. if (ParentOf(balanceNode) == LeftOf(ParentOf(ParentOf(balanceNode))))
  448. {
  449. IntervalTreeNode<K, V> sibling = RightOf(ParentOf(ParentOf(balanceNode)));
  450. if (ColorOf(sibling) == Red)
  451. {
  452. SetColor(ParentOf(balanceNode), Black);
  453. SetColor(sibling, Black);
  454. SetColor(ParentOf(ParentOf(balanceNode)), Red);
  455. balanceNode = ParentOf(ParentOf(balanceNode));
  456. }
  457. else
  458. {
  459. if (balanceNode == RightOf(ParentOf(balanceNode)))
  460. {
  461. balanceNode = ParentOf(balanceNode);
  462. RotateLeft(balanceNode);
  463. }
  464. SetColor(ParentOf(balanceNode), Black);
  465. SetColor(ParentOf(ParentOf(balanceNode)), Red);
  466. RotateRight(ParentOf(ParentOf(balanceNode)));
  467. }
  468. }
  469. else
  470. {
  471. IntervalTreeNode<K, V> sibling = LeftOf(ParentOf(ParentOf(balanceNode)));
  472. if (ColorOf(sibling) == Red)
  473. {
  474. SetColor(ParentOf(balanceNode), Black);
  475. SetColor(sibling, Black);
  476. SetColor(ParentOf(ParentOf(balanceNode)), Red);
  477. balanceNode = ParentOf(ParentOf(balanceNode));
  478. }
  479. else
  480. {
  481. if (balanceNode == LeftOf(ParentOf(balanceNode)))
  482. {
  483. balanceNode = ParentOf(balanceNode);
  484. RotateRight(balanceNode);
  485. }
  486. SetColor(ParentOf(balanceNode), Black);
  487. SetColor(ParentOf(ParentOf(balanceNode)), Red);
  488. RotateLeft(ParentOf(ParentOf(balanceNode)));
  489. }
  490. }
  491. }
  492. SetColor(_root, Black);
  493. }
  494. private void RotateLeft(IntervalTreeNode<K, V> node)
  495. {
  496. if (node != null)
  497. {
  498. IntervalTreeNode<K, V> right = RightOf(node);
  499. node.Right = LeftOf(right);
  500. if (node.Right != null)
  501. {
  502. node.Right.Parent = node;
  503. }
  504. IntervalTreeNode<K, V> nodeParent = ParentOf(node);
  505. right.Parent = nodeParent;
  506. if (nodeParent == null)
  507. {
  508. _root = right;
  509. }
  510. else if (node == LeftOf(nodeParent))
  511. {
  512. nodeParent.Left = right;
  513. }
  514. else
  515. {
  516. nodeParent.Right = right;
  517. }
  518. right.Left = node;
  519. node.Parent = right;
  520. PropagateFull(node);
  521. }
  522. }
  523. private void RotateRight(IntervalTreeNode<K, V> node)
  524. {
  525. if (node != null)
  526. {
  527. IntervalTreeNode<K, V> left = LeftOf(node);
  528. node.Left = RightOf(left);
  529. if (node.Left != null)
  530. {
  531. node.Left.Parent = node;
  532. }
  533. IntervalTreeNode<K, V> nodeParent = ParentOf(node);
  534. left.Parent = nodeParent;
  535. if (nodeParent == null)
  536. {
  537. _root = left;
  538. }
  539. else if (node == RightOf(nodeParent))
  540. {
  541. nodeParent.Right = left;
  542. }
  543. else
  544. {
  545. nodeParent.Left = left;
  546. }
  547. left.Right = node;
  548. node.Parent = left;
  549. PropagateFull(node);
  550. }
  551. }
  552. #endregion
  553. #region Safety-Methods
  554. // These methods save memory by allowing us to forego sentinel nil nodes, as well as serve as protection against NullReferenceExceptions.
  555. /// <summary>
  556. /// Returns the color of <paramref name="node"/>, or Black if it is null.
  557. /// </summary>
  558. /// <param name="node">Node</param>
  559. /// <returns>The boolean color of <paramref name="node"/>, or black if null</returns>
  560. private static bool ColorOf(IntervalTreeNode<K, V> node)
  561. {
  562. return node == null || node.Color;
  563. }
  564. /// <summary>
  565. /// Sets the color of <paramref name="node"/> node to <paramref name="color"/>.
  566. /// <br></br>
  567. /// This method does nothing if <paramref name="node"/> is null.
  568. /// </summary>
  569. /// <param name="node">Node to set the color of</param>
  570. /// <param name="color">Color (Boolean)</param>
  571. private static void SetColor(IntervalTreeNode<K, V> node, bool color)
  572. {
  573. if (node != null)
  574. {
  575. node.Color = color;
  576. }
  577. }
  578. /// <summary>
  579. /// This method returns the left node of <paramref name="node"/>, or null if <paramref name="node"/> is null.
  580. /// </summary>
  581. /// <param name="node">Node to retrieve the left child from</param>
  582. /// <returns>Left child of <paramref name="node"/></returns>
  583. private static IntervalTreeNode<K, V> LeftOf(IntervalTreeNode<K, V> node)
  584. {
  585. return node?.Left;
  586. }
  587. /// <summary>
  588. /// This method returns the right node of <paramref name="node"/>, or null if <paramref name="node"/> is null.
  589. /// </summary>
  590. /// <param name="node">Node to retrieve the right child from</param>
  591. /// <returns>Right child of <paramref name="node"/></returns>
  592. private static IntervalTreeNode<K, V> RightOf(IntervalTreeNode<K, V> node)
  593. {
  594. return node?.Right;
  595. }
  596. /// <summary>
  597. /// Returns the parent node of <paramref name="node"/>, or null if <paramref name="node"/> is null.
  598. /// </summary>
  599. /// <param name="node">Node to retrieve the parent from</param>
  600. /// <returns>Parent of <paramref name="node"/></returns>
  601. private static IntervalTreeNode<K, V> ParentOf(IntervalTreeNode<K, V> node)
  602. {
  603. return node?.Parent;
  604. }
  605. #endregion
  606. public bool ContainsKey(K key)
  607. {
  608. return GetNode(key) != null;
  609. }
  610. public void Clear()
  611. {
  612. _root = null;
  613. _count = 0;
  614. }
  615. }
  616. /// <summary>
  617. /// Represents a node in the IntervalTree which contains start and end keys of type K, and a value of generic type V.
  618. /// </summary>
  619. /// <typeparam name="K">Key type of the node</typeparam>
  620. /// <typeparam name="V">Value type of the node</typeparam>
  621. class IntervalTreeNode<K, V>
  622. {
  623. public bool Color = true;
  624. public IntervalTreeNode<K, V> Left = null;
  625. public IntervalTreeNode<K, V> Right = null;
  626. public IntervalTreeNode<K, V> Parent = null;
  627. /// <summary>
  628. /// The start of the range.
  629. /// </summary>
  630. public K Start;
  631. /// <summary>
  632. /// The end of the range.
  633. /// </summary>
  634. public K End;
  635. /// <summary>
  636. /// The maximum end value of this node and all its children.
  637. /// </summary>
  638. public K Max;
  639. /// <summary>
  640. /// Value stored on this node.
  641. /// </summary>
  642. public V Value;
  643. public IntervalTreeNode(K start, K end, V value, IntervalTreeNode<K, V> parent)
  644. {
  645. Start = start;
  646. End = end;
  647. Max = end;
  648. Value = value;
  649. Parent = parent;
  650. }
  651. }
  652. }