using System; namespace Ryujinx.Common.Collections { /// /// 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. /// /// Derived node type public class IntrusiveRedBlackTree : IntrusiveRedBlackTreeImpl where T : IntrusiveRedBlackTreeNode, IComparable { #region Public Methods /// /// Adds a new node into the tree. /// /// Node to be added /// is null public void Add(T node) { ArgumentNullException.ThrowIfNull(node); Insert(node); } /// /// Removes a node from the tree. /// /// Note to be removed /// is null public void Remove(T node) { ArgumentNullException.ThrowIfNull(node); if (Delete(node) != null) { Count--; } } /// /// Retrieve the node that is considered equal to the specified node by the comparator. /// /// Node to compare with /// Node that is equal to /// is null public T GetNode(T searchNode) { ArgumentNullException.ThrowIfNull(searchNode); T node = Root; while (node != null) { int cmp = searchNode.CompareTo(node); if (cmp < 0) { node = node.Left; } else if (cmp > 0) { node = node.Right; } else { return node; } } return null; } #endregion #region Private Methods (BST) /// /// Inserts a new node into the tree. /// /// Node to be inserted private void Insert(T node) { T newNode = BSTInsert(node); RestoreBalanceAfterInsertion(newNode); } /// /// Insertion Mechanism for a Binary Search Tree (BST). ///

/// Iterates the tree starting from the root and inserts a new node /// where all children in the left subtree are less than , /// and all children in the right subtree are greater than . ///
/// Node to be inserted /// The inserted Node private T BSTInsert(T newNode) { T parent = null; T node = Root; while (node != null) { parent = node; int cmp = newNode.CompareTo(node); if (cmp < 0) { node = node.Left; } else if (cmp > 0) { node = node.Right; } else { return node; } } newNode.Parent = parent; if (parent == null) { Root = newNode; } else if (newNode.CompareTo(parent) < 0) { parent.Left = newNode; } else { parent.Right = newNode; } Count++; return newNode; } /// /// Removes from the tree, if it exists. /// /// Node to be removed /// The deleted Node private T Delete(T nodeToDelete) { if (nodeToDelete == null) { return null; } T old = nodeToDelete; T child; T parent; bool color; if (LeftOf(nodeToDelete) == null) { child = RightOf(nodeToDelete); } else if (RightOf(nodeToDelete) == null) { child = LeftOf(nodeToDelete); } else { T element = Minimum(RightOf(nodeToDelete)); child = RightOf(element); parent = ParentOf(element); color = ColorOf(element); if (child != null) { child.Parent = parent; } if (parent == null) { Root = child; } else if (element == LeftOf(parent)) { parent.Left = child; } else { parent.Right = child; } if (ParentOf(element) == old) { parent = element; } element.Color = old.Color; element.Left = old.Left; element.Right = old.Right; element.Parent = old.Parent; if (ParentOf(old) == null) { Root = element; } else if (old == LeftOf(ParentOf(old))) { ParentOf(old).Left = element; } else { ParentOf(old).Right = element; } LeftOf(old).Parent = element; if (RightOf(old) != null) { RightOf(old).Parent = element; } if (child != null && color == Black) { RestoreBalanceAfterRemoval(child); } return old; } parent = ParentOf(nodeToDelete); color = ColorOf(nodeToDelete); if (child != null) { child.Parent = parent; } if (parent == null) { Root = child; } else if (nodeToDelete == LeftOf(parent)) { parent.Left = child; } else { parent.Right = child; } if (child != null && color == Black) { RestoreBalanceAfterRemoval(child); } return old; } #endregion } public static class IntrusiveRedBlackTreeExtensions { /// /// Retrieve the node that is considered equal to the key by the comparator. /// /// Tree to search at /// Key of the node to be found /// Node that is equal to public static N GetNodeByKey(this IntrusiveRedBlackTree tree, K key) where N : IntrusiveRedBlackTreeNode, IComparable, IComparable where K : struct { N node = tree.RootNode; while (node != null) { int cmp = node.CompareTo(key); if (cmp < 0) { node = node.Right; } else if (cmp > 0) { node = node.Left; } else { return node; } } return null; } } }