| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- using System;
- namespace Ryujinx.Common.Collections
- {
- /// <summary>
- /// 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.
- /// </summary>
- /// <typeparam name="T">Derived node type</typeparam>
- public class IntrusiveRedBlackTree<T> : IntrusiveRedBlackTreeImpl<T> where T : IntrusiveRedBlackTreeNode<T>, IComparable<T>
- {
- #region Public Methods
- /// <summary>
- /// Adds a new node into the tree.
- /// </summary>
- /// <param name="node">Node to be added</param>
- /// <exception cref="ArgumentNullException"><paramref name="node"/> is null</exception>
- public void Add(T node)
- {
- ArgumentNullException.ThrowIfNull(node);
- Insert(node);
- }
- /// <summary>
- /// Removes a node from the tree.
- /// </summary>
- /// <param name="node">Note to be removed</param>
- /// <exception cref="ArgumentNullException"><paramref name="node"/> is null</exception>
- public void Remove(T node)
- {
- ArgumentNullException.ThrowIfNull(node);
- if (Delete(node) != null)
- {
- Count--;
- }
- }
- /// <summary>
- /// Retrieve the node that is considered equal to the specified node by the comparator.
- /// </summary>
- /// <param name="searchNode">Node to compare with</param>
- /// <returns>Node that is equal to <paramref name="searchNode"/></returns>
- /// <exception cref="ArgumentNullException"><paramref name="searchNode"/> is null</exception>
- 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)
- /// <summary>
- /// Inserts a new node into the tree.
- /// </summary>
- /// <param name="node">Node to be inserted</param>
- private void Insert(T node)
- {
- T newNode = BSTInsert(node);
- RestoreBalanceAfterInsertion(newNode);
- }
- /// <summary>
- /// Insertion Mechanism for a Binary Search Tree (BST).
- /// <br></br>
- /// Iterates the tree starting from the root and inserts a new node
- /// where all children in the left subtree are less than <paramref name="newNode"/>,
- /// and all children in the right subtree are greater than <paramref name="newNode"/>.
- /// </summary>
- /// <param name="newNode">Node to be inserted</param>
- /// <returns>The inserted Node</returns>
- 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;
- }
- /// <summary>
- /// Removes <paramref name="nodeToDelete"/> from the tree, if it exists.
- /// </summary>
- /// <param name="nodeToDelete">Node to be removed</param>
- /// <returns>The deleted Node</returns>
- 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
- {
- /// <summary>
- /// Retrieve the node that is considered equal to the key by the comparator.
- /// </summary>
- /// <param name="tree">Tree to search at</param>
- /// <param name="key">Key of the node to be found</param>
- /// <returns>Node that is equal to <paramref name="key"/></returns>
- public static N GetNodeByKey<N, K>(this IntrusiveRedBlackTree<N> tree, K key)
- where N : IntrusiveRedBlackTreeNode<N>, IComparable<N>, IComparable<K>
- 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;
- }
- }
- }
|