IntrusiveRedBlackTreeImpl.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. using System;
  2. namespace Ryujinx.Common.Collections
  3. {
  4. /// <summary>
  5. /// Tree that provides the ability for O(logN) lookups for keys that exist in the tree, and O(logN) lookups for keys immediately greater than or less than a specified key.
  6. /// </summary>
  7. /// <typeparam name="T">Derived node type</typeparam>
  8. public class IntrusiveRedBlackTreeImpl<T> where T : IntrusiveRedBlackTreeNode<T>
  9. {
  10. protected const bool Black = true;
  11. protected const bool Red = false;
  12. protected T Root = null;
  13. internal T RootNode => Root;
  14. /// <summary>
  15. /// Number of nodes on the tree.
  16. /// </summary>
  17. public int Count { get; protected set; }
  18. /// <summary>
  19. /// Removes all nodes on the tree.
  20. /// </summary>
  21. public void Clear()
  22. {
  23. Root = null;
  24. Count = 0;
  25. }
  26. /// <summary>
  27. /// Finds the node whose key is immediately greater than <paramref name="node"/>.
  28. /// </summary>
  29. /// <param name="node">Node to find the successor of</param>
  30. /// <returns>Successor of <paramref name="node"/></returns>
  31. internal static T SuccessorOf(T node)
  32. {
  33. if (node.Right != null)
  34. {
  35. return Minimum(node.Right);
  36. }
  37. T parent = node.Parent;
  38. while (parent != null && node == parent.Right)
  39. {
  40. node = parent;
  41. parent = parent.Parent;
  42. }
  43. return parent;
  44. }
  45. /// <summary>
  46. /// Finds the node whose key is immediately less than <paramref name="node"/>.
  47. /// </summary>
  48. /// <param name="node">Node to find the predecessor of</param>
  49. /// <returns>Predecessor of <paramref name="node"/></returns>
  50. internal static T PredecessorOf(T node)
  51. {
  52. if (node.Left != null)
  53. {
  54. return Maximum(node.Left);
  55. }
  56. T parent = node.Parent;
  57. while (parent != null && node == parent.Left)
  58. {
  59. node = parent;
  60. parent = parent.Parent;
  61. }
  62. return parent;
  63. }
  64. /// <summary>
  65. /// Returns the node with the largest key where <paramref name="node"/> is considered the root node.
  66. /// </summary>
  67. /// <param name="node">Root node</param>
  68. /// <returns>Node with the maximum key in the tree of <paramref name="node"/></returns>
  69. protected static T Maximum(T node)
  70. {
  71. T tmp = node;
  72. while (tmp.Right != null)
  73. {
  74. tmp = tmp.Right;
  75. }
  76. return tmp;
  77. }
  78. /// <summary>
  79. /// Returns the node with the smallest key where <paramref name="node"/> is considered the root node.
  80. /// </summary>
  81. /// <param name="node">Root node</param>
  82. /// <returns>Node with the minimum key in the tree of <paramref name="node"/></returns>
  83. /// <exception cref="ArgumentNullException"><paramref name="node"/> is null</exception>
  84. protected static T Minimum(T node)
  85. {
  86. ArgumentNullException.ThrowIfNull(node);
  87. T tmp = node;
  88. while (tmp.Left != null)
  89. {
  90. tmp = tmp.Left;
  91. }
  92. return tmp;
  93. }
  94. protected void RestoreBalanceAfterRemoval(T balanceNode)
  95. {
  96. T ptr = balanceNode;
  97. while (ptr != Root && ColorOf(ptr) == Black)
  98. {
  99. if (ptr == LeftOf(ParentOf(ptr)))
  100. {
  101. T sibling = RightOf(ParentOf(ptr));
  102. if (ColorOf(sibling) == Red)
  103. {
  104. SetColor(sibling, Black);
  105. SetColor(ParentOf(ptr), Red);
  106. RotateLeft(ParentOf(ptr));
  107. sibling = RightOf(ParentOf(ptr));
  108. }
  109. if (ColorOf(LeftOf(sibling)) == Black && ColorOf(RightOf(sibling)) == Black)
  110. {
  111. SetColor(sibling, Red);
  112. ptr = ParentOf(ptr);
  113. }
  114. else
  115. {
  116. if (ColorOf(RightOf(sibling)) == Black)
  117. {
  118. SetColor(LeftOf(sibling), Black);
  119. SetColor(sibling, Red);
  120. RotateRight(sibling);
  121. sibling = RightOf(ParentOf(ptr));
  122. }
  123. SetColor(sibling, ColorOf(ParentOf(ptr)));
  124. SetColor(ParentOf(ptr), Black);
  125. SetColor(RightOf(sibling), Black);
  126. RotateLeft(ParentOf(ptr));
  127. ptr = Root;
  128. }
  129. }
  130. else
  131. {
  132. T sibling = LeftOf(ParentOf(ptr));
  133. if (ColorOf(sibling) == Red)
  134. {
  135. SetColor(sibling, Black);
  136. SetColor(ParentOf(ptr), Red);
  137. RotateRight(ParentOf(ptr));
  138. sibling = LeftOf(ParentOf(ptr));
  139. }
  140. if (ColorOf(RightOf(sibling)) == Black && ColorOf(LeftOf(sibling)) == Black)
  141. {
  142. SetColor(sibling, Red);
  143. ptr = ParentOf(ptr);
  144. }
  145. else
  146. {
  147. if (ColorOf(LeftOf(sibling)) == Black)
  148. {
  149. SetColor(RightOf(sibling), Black);
  150. SetColor(sibling, Red);
  151. RotateLeft(sibling);
  152. sibling = LeftOf(ParentOf(ptr));
  153. }
  154. SetColor(sibling, ColorOf(ParentOf(ptr)));
  155. SetColor(ParentOf(ptr), Black);
  156. SetColor(LeftOf(sibling), Black);
  157. RotateRight(ParentOf(ptr));
  158. ptr = Root;
  159. }
  160. }
  161. }
  162. SetColor(ptr, Black);
  163. }
  164. protected void RestoreBalanceAfterInsertion(T balanceNode)
  165. {
  166. SetColor(balanceNode, Red);
  167. while (balanceNode != null && balanceNode != Root && ColorOf(ParentOf(balanceNode)) == Red)
  168. {
  169. if (ParentOf(balanceNode) == LeftOf(ParentOf(ParentOf(balanceNode))))
  170. {
  171. T sibling = RightOf(ParentOf(ParentOf(balanceNode)));
  172. if (ColorOf(sibling) == Red)
  173. {
  174. SetColor(ParentOf(balanceNode), Black);
  175. SetColor(sibling, Black);
  176. SetColor(ParentOf(ParentOf(balanceNode)), Red);
  177. balanceNode = ParentOf(ParentOf(balanceNode));
  178. }
  179. else
  180. {
  181. if (balanceNode == RightOf(ParentOf(balanceNode)))
  182. {
  183. balanceNode = ParentOf(balanceNode);
  184. RotateLeft(balanceNode);
  185. }
  186. SetColor(ParentOf(balanceNode), Black);
  187. SetColor(ParentOf(ParentOf(balanceNode)), Red);
  188. RotateRight(ParentOf(ParentOf(balanceNode)));
  189. }
  190. }
  191. else
  192. {
  193. T sibling = LeftOf(ParentOf(ParentOf(balanceNode)));
  194. if (ColorOf(sibling) == Red)
  195. {
  196. SetColor(ParentOf(balanceNode), Black);
  197. SetColor(sibling, Black);
  198. SetColor(ParentOf(ParentOf(balanceNode)), Red);
  199. balanceNode = ParentOf(ParentOf(balanceNode));
  200. }
  201. else
  202. {
  203. if (balanceNode == LeftOf(ParentOf(balanceNode)))
  204. {
  205. balanceNode = ParentOf(balanceNode);
  206. RotateRight(balanceNode);
  207. }
  208. SetColor(ParentOf(balanceNode), Black);
  209. SetColor(ParentOf(ParentOf(balanceNode)), Red);
  210. RotateLeft(ParentOf(ParentOf(balanceNode)));
  211. }
  212. }
  213. }
  214. SetColor(Root, Black);
  215. }
  216. protected virtual void RotateLeft(T node)
  217. {
  218. if (node != null)
  219. {
  220. T right = RightOf(node);
  221. node.Right = LeftOf(right);
  222. if (node.Right != null)
  223. {
  224. node.Right.Parent = node;
  225. }
  226. T nodeParent = ParentOf(node);
  227. right.Parent = nodeParent;
  228. if (nodeParent == null)
  229. {
  230. Root = right;
  231. }
  232. else if (node == LeftOf(nodeParent))
  233. {
  234. nodeParent.Left = right;
  235. }
  236. else
  237. {
  238. nodeParent.Right = right;
  239. }
  240. right.Left = node;
  241. node.Parent = right;
  242. }
  243. }
  244. protected virtual void RotateRight(T node)
  245. {
  246. if (node != null)
  247. {
  248. T left = LeftOf(node);
  249. node.Left = RightOf(left);
  250. if (node.Left != null)
  251. {
  252. node.Left.Parent = node;
  253. }
  254. T nodeParent = ParentOf(node);
  255. left.Parent = nodeParent;
  256. if (nodeParent == null)
  257. {
  258. Root = left;
  259. }
  260. else if (node == RightOf(nodeParent))
  261. {
  262. nodeParent.Right = left;
  263. }
  264. else
  265. {
  266. nodeParent.Left = left;
  267. }
  268. left.Right = node;
  269. node.Parent = left;
  270. }
  271. }
  272. #region Safety-Methods
  273. // These methods save memory by allowing us to forego sentinel nil nodes, as well as serve as protection against NullReferenceExceptions.
  274. /// <summary>
  275. /// Returns the color of <paramref name="node"/>, or Black if it is null.
  276. /// </summary>
  277. /// <param name="node">Node</param>
  278. /// <returns>The boolean color of <paramref name="node"/>, or black if null</returns>
  279. protected static bool ColorOf(T node)
  280. {
  281. return node == null || node.Color;
  282. }
  283. /// <summary>
  284. /// Sets the color of <paramref name="node"/> node to <paramref name="color"/>.
  285. /// <br></br>
  286. /// This method does nothing if <paramref name="node"/> is null.
  287. /// </summary>
  288. /// <param name="node">Node to set the color of</param>
  289. /// <param name="color">Color (Boolean)</param>
  290. protected static void SetColor(T node, bool color)
  291. {
  292. if (node != null)
  293. {
  294. node.Color = color;
  295. }
  296. }
  297. /// <summary>
  298. /// This method returns the left node of <paramref name="node"/>, or null if <paramref name="node"/> is null.
  299. /// </summary>
  300. /// <param name="node">Node to retrieve the left child from</param>
  301. /// <returns>Left child of <paramref name="node"/></returns>
  302. protected static T LeftOf(T node)
  303. {
  304. return node?.Left;
  305. }
  306. /// <summary>
  307. /// This method returns the right node of <paramref name="node"/>, or null if <paramref name="node"/> is null.
  308. /// </summary>
  309. /// <param name="node">Node to retrieve the right child from</param>
  310. /// <returns>Right child of <paramref name="node"/></returns>
  311. protected static T RightOf(T node)
  312. {
  313. return node?.Right;
  314. }
  315. /// <summary>
  316. /// Returns the parent node of <paramref name="node"/>, or null if <paramref name="node"/> is null.
  317. /// </summary>
  318. /// <param name="node">Node to retrieve the parent from</param>
  319. /// <returns>Parent of <paramref name="node"/></returns>
  320. protected static T ParentOf(T node)
  321. {
  322. return node?.Parent;
  323. }
  324. #endregion
  325. }
  326. }