IntrusiveRedBlackTreeImpl.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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. if (node == null)
  87. {
  88. throw new ArgumentNullException(nameof(node));
  89. }
  90. T tmp = node;
  91. while (tmp.Left != null)
  92. {
  93. tmp = tmp.Left;
  94. }
  95. return tmp;
  96. }
  97. protected void RestoreBalanceAfterRemoval(T balanceNode)
  98. {
  99. T ptr = balanceNode;
  100. while (ptr != Root && ColorOf(ptr) == Black)
  101. {
  102. if (ptr == LeftOf(ParentOf(ptr)))
  103. {
  104. T sibling = RightOf(ParentOf(ptr));
  105. if (ColorOf(sibling) == Red)
  106. {
  107. SetColor(sibling, Black);
  108. SetColor(ParentOf(ptr), Red);
  109. RotateLeft(ParentOf(ptr));
  110. sibling = RightOf(ParentOf(ptr));
  111. }
  112. if (ColorOf(LeftOf(sibling)) == Black && ColorOf(RightOf(sibling)) == Black)
  113. {
  114. SetColor(sibling, Red);
  115. ptr = ParentOf(ptr);
  116. }
  117. else
  118. {
  119. if (ColorOf(RightOf(sibling)) == Black)
  120. {
  121. SetColor(LeftOf(sibling), Black);
  122. SetColor(sibling, Red);
  123. RotateRight(sibling);
  124. sibling = RightOf(ParentOf(ptr));
  125. }
  126. SetColor(sibling, ColorOf(ParentOf(ptr)));
  127. SetColor(ParentOf(ptr), Black);
  128. SetColor(RightOf(sibling), Black);
  129. RotateLeft(ParentOf(ptr));
  130. ptr = Root;
  131. }
  132. }
  133. else
  134. {
  135. T sibling = LeftOf(ParentOf(ptr));
  136. if (ColorOf(sibling) == Red)
  137. {
  138. SetColor(sibling, Black);
  139. SetColor(ParentOf(ptr), Red);
  140. RotateRight(ParentOf(ptr));
  141. sibling = LeftOf(ParentOf(ptr));
  142. }
  143. if (ColorOf(RightOf(sibling)) == Black && ColorOf(LeftOf(sibling)) == Black)
  144. {
  145. SetColor(sibling, Red);
  146. ptr = ParentOf(ptr);
  147. }
  148. else
  149. {
  150. if (ColorOf(LeftOf(sibling)) == Black)
  151. {
  152. SetColor(RightOf(sibling), Black);
  153. SetColor(sibling, Red);
  154. RotateLeft(sibling);
  155. sibling = LeftOf(ParentOf(ptr));
  156. }
  157. SetColor(sibling, ColorOf(ParentOf(ptr)));
  158. SetColor(ParentOf(ptr), Black);
  159. SetColor(LeftOf(sibling), Black);
  160. RotateRight(ParentOf(ptr));
  161. ptr = Root;
  162. }
  163. }
  164. }
  165. SetColor(ptr, Black);
  166. }
  167. protected void RestoreBalanceAfterInsertion(T balanceNode)
  168. {
  169. SetColor(balanceNode, Red);
  170. while (balanceNode != null && balanceNode != Root && ColorOf(ParentOf(balanceNode)) == Red)
  171. {
  172. if (ParentOf(balanceNode) == LeftOf(ParentOf(ParentOf(balanceNode))))
  173. {
  174. T sibling = RightOf(ParentOf(ParentOf(balanceNode)));
  175. if (ColorOf(sibling) == Red)
  176. {
  177. SetColor(ParentOf(balanceNode), Black);
  178. SetColor(sibling, Black);
  179. SetColor(ParentOf(ParentOf(balanceNode)), Red);
  180. balanceNode = ParentOf(ParentOf(balanceNode));
  181. }
  182. else
  183. {
  184. if (balanceNode == RightOf(ParentOf(balanceNode)))
  185. {
  186. balanceNode = ParentOf(balanceNode);
  187. RotateLeft(balanceNode);
  188. }
  189. SetColor(ParentOf(balanceNode), Black);
  190. SetColor(ParentOf(ParentOf(balanceNode)), Red);
  191. RotateRight(ParentOf(ParentOf(balanceNode)));
  192. }
  193. }
  194. else
  195. {
  196. T sibling = LeftOf(ParentOf(ParentOf(balanceNode)));
  197. if (ColorOf(sibling) == Red)
  198. {
  199. SetColor(ParentOf(balanceNode), Black);
  200. SetColor(sibling, Black);
  201. SetColor(ParentOf(ParentOf(balanceNode)), Red);
  202. balanceNode = ParentOf(ParentOf(balanceNode));
  203. }
  204. else
  205. {
  206. if (balanceNode == LeftOf(ParentOf(balanceNode)))
  207. {
  208. balanceNode = ParentOf(balanceNode);
  209. RotateRight(balanceNode);
  210. }
  211. SetColor(ParentOf(balanceNode), Black);
  212. SetColor(ParentOf(ParentOf(balanceNode)), Red);
  213. RotateLeft(ParentOf(ParentOf(balanceNode)));
  214. }
  215. }
  216. }
  217. SetColor(Root, Black);
  218. }
  219. protected virtual void RotateLeft(T node)
  220. {
  221. if (node != null)
  222. {
  223. T right = RightOf(node);
  224. node.Right = LeftOf(right);
  225. if (node.Right != null)
  226. {
  227. node.Right.Parent = node;
  228. }
  229. T nodeParent = ParentOf(node);
  230. right.Parent = nodeParent;
  231. if (nodeParent == null)
  232. {
  233. Root = right;
  234. }
  235. else if (node == LeftOf(nodeParent))
  236. {
  237. nodeParent.Left = right;
  238. }
  239. else
  240. {
  241. nodeParent.Right = right;
  242. }
  243. right.Left = node;
  244. node.Parent = right;
  245. }
  246. }
  247. protected virtual void RotateRight(T node)
  248. {
  249. if (node != null)
  250. {
  251. T left = LeftOf(node);
  252. node.Left = RightOf(left);
  253. if (node.Left != null)
  254. {
  255. node.Left.Parent = node;
  256. }
  257. T nodeParent = ParentOf(node);
  258. left.Parent = nodeParent;
  259. if (nodeParent == null)
  260. {
  261. Root = left;
  262. }
  263. else if (node == RightOf(nodeParent))
  264. {
  265. nodeParent.Right = left;
  266. }
  267. else
  268. {
  269. nodeParent.Left = left;
  270. }
  271. left.Right = node;
  272. node.Parent = left;
  273. }
  274. }
  275. #region Safety-Methods
  276. // These methods save memory by allowing us to forego sentinel nil nodes, as well as serve as protection against NullReferenceExceptions.
  277. /// <summary>
  278. /// Returns the color of <paramref name="node"/>, or Black if it is null.
  279. /// </summary>
  280. /// <param name="node">Node</param>
  281. /// <returns>The boolean color of <paramref name="node"/>, or black if null</returns>
  282. protected static bool ColorOf(T node)
  283. {
  284. return node == null || node.Color;
  285. }
  286. /// <summary>
  287. /// Sets the color of <paramref name="node"/> node to <paramref name="color"/>.
  288. /// <br></br>
  289. /// This method does nothing if <paramref name="node"/> is null.
  290. /// </summary>
  291. /// <param name="node">Node to set the color of</param>
  292. /// <param name="color">Color (Boolean)</param>
  293. protected static void SetColor(T node, bool color)
  294. {
  295. if (node != null)
  296. {
  297. node.Color = color;
  298. }
  299. }
  300. /// <summary>
  301. /// This method returns the left node of <paramref name="node"/>, or null if <paramref name="node"/> is null.
  302. /// </summary>
  303. /// <param name="node">Node to retrieve the left child from</param>
  304. /// <returns>Left child of <paramref name="node"/></returns>
  305. protected static T LeftOf(T node)
  306. {
  307. return node?.Left;
  308. }
  309. /// <summary>
  310. /// This method returns the right node of <paramref name="node"/>, or null if <paramref name="node"/> is null.
  311. /// </summary>
  312. /// <param name="node">Node to retrieve the right child from</param>
  313. /// <returns>Right child of <paramref name="node"/></returns>
  314. protected static T RightOf(T node)
  315. {
  316. return node?.Right;
  317. }
  318. /// <summary>
  319. /// Returns the parent node of <paramref name="node"/>, or null if <paramref name="node"/> is null.
  320. /// </summary>
  321. /// <param name="node">Node to retrieve the parent from</param>
  322. /// <returns>Parent of <paramref name="node"/></returns>
  323. protected static T ParentOf(T node)
  324. {
  325. return node?.Parent;
  326. }
  327. #endregion
  328. }
  329. }