internal T Get(Node node, CompareToKnownValue <T> compare) { int loc = 0; for (int i = 0; i < node.ItemCount; i++) { switch (compare(node.Items[i])) { case Less: loc++; continue; case Equal: goto break_for; case Greater: goto break_for; default: throw new NotImplementedException(); } } break_for: if (loc < node.ItemCount && compare(node.Items[loc]) == Equal) { return(node.Items[loc]); } if (node.ChildCount == 0) { throw new InvalidOperationException("getting a non-existing item"); } return(this.Get(node.Children[loc], compare)); }
private static int Binary <T>(GetIndex <T> get, int index, int length, CompareToKnownValue <T> compare) { int low = index; int hi = index + length - 1; while (low <= hi) { int median = low + (hi - low >> 1); switch (compare(get(median))) { case CompareResult.Equal: return(median); case CompareResult.Less: low = median + 1; break; case CompareResult.Greater: hi = median - 1; break; default: throw new NotImplementedException(); } } return(~low); }
internal void Remove(Node node, CompareToKnownValue <T> compare) { int loc = 0; for (int i = 0; i < node.ItemCount; i++) { switch (compare(node.Items[i])) { case Less: loc++; continue; case Equal: goto break_for; case Greater: goto break_for; default: throw new System.NotImplementedException(); } } break_for: if (loc < node.ItemCount && compare(node.Items[loc]) == Equal) { RemoveKeyFromNode(node, compare, loc); return; } if (!(node.ChildCount == 0)) { RemoveKeyFromSubtree(node, compare, loc); } }
/// <summary>Tries to remove a value.</summary> /// <param name="compare">The compare delegate.</param> /// <param name="exception">The exception that occurred if the remove failed.</param> /// <returns>True if the remove was successful or false if not.</returns> public bool TryRemove(CompareToKnownValue <T> compare, out Exception exception) { Node node; node = _root; while (node != _sentinelNode) { CompareResult compareResult = compare(node.Value); if (compareResult == Less) { node = node.LeftChild; } else if (compareResult == Greater) { node = node.RightChild; } else // (compareResult == Equal) { if (node == _sentinelNode) { exception = new ArgumentException("Attempting to remove a non-existing entry."); return(false); } Remove(node); _count -= 1; exception = null; return(true); } } exception = new ArgumentException("Attempting to remove a non-existing entry."); return(false); }
/// <summary>Tries to get a value.</summary> /// <param name="compare">The compare delegate.</param> /// <param name="value">The value if found or default.</param> /// <param name="exception">The exception that occurred if the get failed.</param> /// <returns>True if the get succeeded or false if not.</returns> /// <runtime>O(ln(Count)) Ω(1)</runtime> public bool TryGet(CompareToKnownValue <T> compare, out T value, out Exception exception) { Node node = _root; while (node != null) { CompareResult comparison = compare(node.Value); if (comparison == Less) { node = node.LeftChild; } else if (comparison == Greater) { node = node.RightChild; } else // (compareResult == Copmarison.Equal) { value = node.Value; exception = null; return(true); } } value = default; exception = new InvalidOperationException("Attempting to get a non-existing value from an AVL tree."); return(false); }
/// <summary>Tries to get a value.</summary> /// <param name="compare">The compare delegate.</param> /// <param name="value">The value if it was found or default.</param> /// <param name="exception">The exception that occurred if the get failed.</param> /// <returns>True if the value was found or false if not.</returns> public bool TryGet(CompareToKnownValue <T> compare, out T value, out Exception exception) { Node treeNode = _root; while (treeNode != _sentinelNode) { CompareResult compareResult = compare(treeNode.Value); if (compareResult == Greater) { treeNode = treeNode.RightChild; } else if (compareResult == Less) { treeNode = treeNode.LeftChild; } else { value = treeNode.Value; exception = null; return(true); } } value = default; exception = new ArgumentException("Attempting to get a non-existing value."); return(false); }
/// <summary>Determines if this structure contains an item by a given key.</summary> /// <param name="compare">The sorting technique (must synchronize with this structure's sorting).</param> /// <returns>True of contained, False if not.</returns> /// <runtime>O(ln(Count)) Ω(1)</runtime> public bool Contains(CompareToKnownValue <T> compare) { Node treeNode = _root; while (treeNode != _sentinelNode) { switch (compare(treeNode.Value)) { case Equal: return(true); case Greater: treeNode = treeNode.RightChild; break; case Less: treeNode = treeNode.LeftChild; break; default: throw new NotImplementedException(); } } return(false); }
/// <summary>Removes a value.</summary> /// <typeparam name="T">The type of value.</typeparam> /// <param name="tree">The tree to remove the value from.</param> /// <param name="compare">The compare delegate.</param> public static void Remove <T>(this ISortedBinaryTree <T> tree, CompareToKnownValue <T> compare) { if (!tree.TryRemove(compare, out Exception exception)) { throw exception; } }
// methods (internal) #region internal bool Contains<K>(Node node, K key, Compare<T, K> compare) internal bool Contains(Node node, CompareToKnownValue <T> compare) { int loc = 0; for (int i = 0; i < node.ItemCount; i++) { switch (compare(node.Items[i])) { case Less: loc++; continue; case Equal: goto break_for; case Greater: goto break_for; default: throw new System.NotImplementedException(); } } break_for: if (loc < node.ItemCount && compare(node.Items[loc]) == Equal) { return(true); } if (node.ChildCount == 0) { return(false); } return(this.Contains(node.Children[loc], compare)); }
internal static int Binary <T>(GetIndex <T> get, int index, int length, CompareToKnownValue <T> compare) { int low = index; int hi = index + length - 1; while (low <= hi) { int median = low + (hi - low >> 1); CompareResult compareResult = compare(get(median)); if (compareResult is Less) { low = median + 1; } else if (compareResult is Greater) { hi = median - 1; } else if (compareResult is Equal) { return(median); } else { throw new TowelBugException("Unhandled CompareResult."); } } return(~low); }
/// <summary>Gets a value.</summary> /// <typeparam name="T">The type of value.</typeparam> /// <param name="tree">The tree to get the value from.</param> /// <param name="compare">The compare delegate. This must match the compare that the Red-Black tree is sorted with.</param> /// <returns>The value.</returns> public static T Get <T>(this ISortedBinaryTree <T> tree, CompareToKnownValue <T> compare) { if (!tree.TryGet(compare, out T value, out Exception exception)) { throw exception; } return(value); }
/// <summary>Performs a binary search to find the index where a specific value fits in indexed, sorted items.</summary> /// <typeparam name="T">The generic type of the set of values.</typeparam> /// <param name="get">Indexer delegate.</param> /// <param name="length">The number of indexed items.</param> /// <param name="compare">Comparison delegate.</param> /// <returns>The index where the specific value fits into the index, sorted items.</returns> public static int Binary <T>(GetIndex <T> get, int length, CompareToKnownValue <T> compare) { _ = get ?? throw new ArgumentNullException(nameof(get)); _ = compare ?? throw new ArgumentNullException(nameof(compare)); if (length <= 0) { throw new ArgumentOutOfRangeException(nameof(length), length, "!(" + nameof(length) + " > 0)"); } return(Binary(get, 0, length, compare)); }
internal void RemoveKeyFromSubtree(Node parentNode, CompareToKnownValue <T> compare, int subtreeIndexInNode) { Node childNode = parentNode.Children[subtreeIndexInNode]; if (childNode.ItemCount == _node_size - 1) { int leftIndex = subtreeIndexInNode - 1; Node leftSibling = subtreeIndexInNode > 0 ? parentNode.Children[leftIndex] : null; int rightIndex = subtreeIndexInNode + 1; Node rightSibling = subtreeIndexInNode < parentNode.ChildCount - 1 ? parentNode.Children[rightIndex] : null; if (leftSibling is not null && leftSibling.ItemCount > _node_size - 1) { for (int i = childNode.ChildCount; i > -1; i--) { childNode.Items[i] = childNode.Items[i - 1]; } childNode.Items[0] = parentNode.Items[subtreeIndexInNode]; childNode.ItemCount++; parentNode.Items[subtreeIndexInNode] = leftSibling.Items[leftSibling.ItemCount - 1]; leftSibling.ItemCount--; if (!(leftSibling.ChildCount == 0)) { for (int i = childNode.ChildCount; i > -1; i--) { childNode.Children[i] = childNode.Children[i - 1]; } childNode.Children[0] = leftSibling.Children[leftSibling.ChildCount - 1]; leftSibling.ChildCount--; } } else if (rightSibling is not null && rightSibling.ItemCount > _node_size - 1) { childNode.Items[childNode.ItemCount] = parentNode.Items[subtreeIndexInNode]; childNode.ItemCount++; parentNode.Items[subtreeIndexInNode] = rightSibling.Items[0]; for (int i = 0; i < rightSibling.ItemCount; i++) { rightSibling.Items[i] = rightSibling.Items[i + 1]; } rightSibling.ItemCount--; if (!(rightSibling.ChildCount == 0)) { childNode.Children[childNode.ChildCount - 1] = rightSibling.Children[0]; childNode.ChildCount++; for (int i = 0; i < rightSibling.ChildCount; i++) { rightSibling.Items[i] = rightSibling.Items[i + 1]; } rightSibling.ChildCount--; } }
/// <summary>Wrapper for the remove function to handle exceptions.</summary> /// <typeparam name="T">The generic type of this data structure.</typeparam> /// <param name="avlTree">This structure.</param> /// <param name="compare">The sorting technique (must synchronize with this structure's sorting).</param> /// <returns>True if successful, False if not.</returns> public static bool TryRemove <T>(this IAvlTree <T> avlTree, CompareToKnownValue <T> compare) { try { avlTree.Remove(compare); return(true); } catch { return(false); } }
internal void RemoveKeyFromNode(Node node, CompareToKnownValue <T> compare, int keyIndexInNode) { if (node.ChildCount == 0) { for (int i = keyIndexInNode; i < node.ItemCount; i++) { node.Items[i] = node.Items[i + 1]; } node.ItemCount--; return; } Node predecessorChild = node.Children[keyIndexInNode]; if (predecessorChild.ItemCount >= _node_size) { T predecessor = RemovePredecessor(predecessorChild); node.Items[keyIndexInNode] = predecessor; } else { Node successorChild = node.Children[keyIndexInNode + 1]; if (successorChild.ItemCount >= _node_size) { T successor = RemoveSuccessor(predecessorChild); node.Items[keyIndexInNode] = successor; } else { predecessorChild.Items[predecessorChild.ItemCount++] = node.Items[keyIndexInNode]; for (int i = 0; i < successorChild.ItemCount; i++) { predecessorChild.Items[predecessorChild.ItemCount++] = successorChild.Items[i]; } for (int i = 0; i < successorChild.ChildCount; i++) { predecessorChild.Items[predecessorChild.ChildCount++] = successorChild.Items[i]; } for (int i = keyIndexInNode; i < node.ItemCount; i++) { node.Items[i] = node.Items[i + 1]; } node.ItemCount--; for (int i = keyIndexInNode + 1; i < node.ChildCount; i++) { node.Children[i] = node.Children[i + 1]; } node.ChildCount--; Remove(predecessorChild, compare); } } }
/// <summary>Wrapper for the get function to handle exceptions.</summary> /// <typeparam name="T">The generic type of this data structure.</typeparam> /// <param name="avlTree">This structure.</param> /// <param name="compare">The sorting technique (must synchronize with this structure's sorting).</param> /// <param name="item">The item if found.</param> /// <returns>True if successful, False if not.</returns> public static bool TryGet <T>(this IAvlTree <T> avlTree, CompareToKnownValue <T> compare, out T item) { try { item = avlTree.Get(compare); return(true); } catch { item = default(T); return(false); } }
/// <summary>Tries to remove a value.</summary> /// <param name="compare">The compare delegate.</param> /// <param name="exception">The exception that occurred if the remove failed.</param> /// <returns>True if the remove was successful or false if not.</returns> public bool TryRemove(CompareToKnownValue <T> compare, out Exception exception) { Exception capturedException = null; Node Remove(Node node) { if (node != null) { CompareResult compareResult = compare(node.Value); if (compareResult == Less) { node.RightChild = Remove(node.RightChild); } else if (compareResult == Greater) { node.LeftChild = Remove(node.LeftChild); } else // (compareResult == Comparison.Equal) { if (node.RightChild != null) { node.RightChild = RemoveLeftMost(node.RightChild, out Node leftMostOfRight); leftMostOfRight.RightChild = node.RightChild; leftMostOfRight.LeftChild = node.LeftChild; node = leftMostOfRight; } else if (node.LeftChild != null) { node.LeftChild = RemoveRightMost(node.LeftChild, out Node rightMostOfLeft); rightMostOfLeft.RightChild = node.RightChild; rightMostOfLeft.LeftChild = node.LeftChild; node = rightMostOfLeft; } else { return(null); } } SetHeight(node); return(Balance(node)); } capturedException = new ArgumentException("Attempting to remove a non-existing entry."); return(node); } _root = Remove(_root); exception = capturedException; _count--; return(exception is null); }
/// <summary>Removes an item from the structure based on a key.</summary> /// <param name="compare">The compareison technique (must synchronize with this structure's sorting).</param> public void Remove(CompareToKnownValue <T> compare) { this.Remove(_root, compare); if (_root.ItemCount == 0 && !(_root.ChildCount == 0)) { if (_root.ChildCount != 1) { throw new System.InvalidOperationException("this._root.ChildCount != 1"); } _root = _root.Children[0]; _height--; } _count--; }
/// <summary>Removes an item from this structure by a given key.</summary> /// <param name="compare">The sorting technique (must synchronize with the structure's sorting).</param> /// <runtime>O(ln(n))</runtime> public void Remove(CompareToKnownValue <T> compare) { Node REMOVE(CompareToKnownValue <T> COMPARE, Node NODE) { if (NODE != null) { CompareResult compareResult = COMPARE(NODE.Value); if (compareResult == CompareResult.Equal) { if (NODE.RightChild != null) { NODE.RightChild = RemoveLeftMost(NODE.RightChild, out Node leftMostOfRight); leftMostOfRight.RightChild = NODE.RightChild; leftMostOfRight.LeftChild = NODE.LeftChild; NODE = leftMostOfRight; } else if (NODE.LeftChild != null) { NODE.LeftChild = RemoveRightMost(NODE.LeftChild, out Node rightMostOfLeft); rightMostOfLeft.RightChild = NODE.RightChild; rightMostOfLeft.LeftChild = NODE.LeftChild; NODE = rightMostOfLeft; } else { return(null); } SetHeight(NODE); return(Balance(NODE)); } else if (compareResult == CompareResult.Greater) { NODE.LeftChild = REMOVE(COMPARE, NODE.LeftChild); } else // (compareResult == Comparison.Less) { NODE.RightChild = REMOVE(COMPARE, NODE.RightChild); } SetHeight(NODE); return(Balance(NODE)); } throw new InvalidOperationException("Attempting to remove a non-existing entry."); } _root = REMOVE(compare, _root); _count--; }
/// <summary>Determines if this structure contains an item by a given key.</summary> /// <param name="comparison">The sorting technique (must synchronize with this structure's sorting).</param> /// <returns>True of contained, False if not.</returns> /// <runtime>O(ln(Count)) Ω(1)</runtime> public bool Contains(CompareToKnownValue <T> comparison) { Node node = _root; while (node != null) { CompareResult compareResult = comparison(node.Value); if (compareResult == Less) { node = node.LeftChild; } else if (compareResult == Greater) { node = node.RightChild; } else // (compareResult == Copmarison.Equal) { return(true); } } return(false); }
/// <summary>Gets the item with the designated by the string.</summary> /// <param name="compare">The sorting technique (must synchronize with this structure's sorting).</param> /// <returns>The object with the desired string ID if it exists.</returns> /// <runtime>O(ln(Count)) Ω(1)</runtime> public T Get(CompareToKnownValue <T> compare) { Node node = _root; while (node != null) { CompareResult comparison = compare(node.Value); if (comparison == CompareResult.Equal) { return(node.Value); } else if (comparison == CompareResult.Greater) { node = node.LeftChild; } else // (compareResult == Copmarison.Less) { node = node.RightChild; } } throw new InvalidOperationException("Attempting to get a non-existing item."); }
/// <summary>Performs a binary search to find the index where a specific value fits in indexed, sorted items.</summary> /// <typeparam name="T">The generic type of the set of values.</typeparam> /// <param name="array">The array to binary search on.</param> /// <param name="compare">Comparison delegate.</param> /// <returns>The index where the specific value fits into the index, sorted items.</returns> public static int Binary <T>(T[] array, CompareToKnownValue <T> compare) => Binary(array.WrapGetIndex(), array.Length, compare);
/// <summary>Tries to get a value.</summary> /// <typeparam name="T">The type of value.</typeparam> /// <param name="tree">The tree to get the value from.</param> /// <param name="compare">The compare delegate. This must match the compare that the Red-Black tree is sorted with.</param> /// <param name="value">The value if it is found.</param> /// <returns>True if the value was found or false if not.</returns> public static bool TryGet <T>(this ISortedBinaryTree <T> tree, CompareToKnownValue <T> compare, out T value) => tree.TryGet(compare, out value, out _);
/// <summary>Gets a value.</summary> /// <typeparam name="T">The type of value.</typeparam> /// <param name="tree">The tree to get the value from.</param> /// <param name="compare">The compare delegate. This must match the compare that the Red-Black tree is sorted with.</param> /// <returns>The value.</returns> public static T Get <T>(this ISortedBinaryTree <T> tree, CompareToKnownValue <T> compare) => tree.TryGet(compare, out T value, out Exception exception)
/// <summary>Tries to remove a value.</summary> /// <typeparam name="T">The type of value.</typeparam> /// <param name="tree">The tree to remove the value from.</param> /// <param name="compare">The compare delegate.</param> /// <returns>True if the remove was successful or false if not.</returns> public static bool TryRemove <T>(this ISortedBinaryTree <T> tree, CompareToKnownValue <T> compare) { return(tree.TryRemove(compare, out _)); }
/// <summary>Determines if this structure contains a given item based on a given key.</summary> /// <param name="compare">The sorting technique (must synchronize with the sorting of this structure).</param> /// <returns>True if found, False if not.</returns> public bool Contains(CompareToKnownValue <T> compare) { return(Contains(_root, compare)); }
/// <summary>Gets an item from this structure based on a given key.</summary> /// <param name="compare">The comparison techmique (must synchronize with this structure's sorting).</param> /// <returns>Item is found.</returns> public T Get(CompareToKnownValue <T> compare) { return(Get(_root, compare)); }
internal void RemoveKeyFromSubtree(Node parentNode, CompareToKnownValue <T> compare, int subtreeIndexInNode) { Node childNode = parentNode.Children[subtreeIndexInNode]; if (childNode.ItemCount == _node_size - 1) { int leftIndex = subtreeIndexInNode - 1; Node leftSibling = subtreeIndexInNode > 0 ? parentNode.Children[leftIndex] : null; int rightIndex = subtreeIndexInNode + 1; Node rightSibling = subtreeIndexInNode < parentNode.ChildCount - 1 ? parentNode.Children[rightIndex] : null; if (leftSibling != null && leftSibling.ItemCount > _node_size - 1) { for (int i = childNode.ChildCount; i > -1; i--) { childNode.Items[i] = childNode.Items[i - 1]; } childNode.Items[0] = parentNode.Items[subtreeIndexInNode]; childNode.ItemCount++; parentNode.Items[subtreeIndexInNode] = leftSibling.Items[leftSibling.ItemCount - 1]; leftSibling.ItemCount--; if (!(leftSibling.ChildCount == 0)) { for (int i = childNode.ChildCount; i > -1; i--) { childNode.Children[i] = childNode.Children[i - 1]; } childNode.Children[0] = leftSibling.Children[leftSibling.ChildCount - 1]; leftSibling.ChildCount--; } } else if (rightSibling != null && rightSibling.ItemCount > _node_size - 1) { childNode.Items[childNode.ItemCount] = parentNode.Items[subtreeIndexInNode]; childNode.ItemCount++; parentNode.Items[subtreeIndexInNode] = rightSibling.Items[0]; for (int i = 0; i < rightSibling.ItemCount; i++) { rightSibling.Items[i] = rightSibling.Items[i + 1]; } rightSibling.ItemCount--; if (!(rightSibling.ChildCount == 0)) { childNode.Children[childNode.ChildCount - 1] = rightSibling.Children[0]; childNode.ChildCount++; for (int i = 0; i < rightSibling.ChildCount; i++) { rightSibling.Items[i] = rightSibling.Items[i + 1]; } rightSibling.ChildCount--; } } else { if (leftSibling != null) { for (int i = childNode.ItemCount; i > 0; i--) { childNode.Items[i] = childNode.Items[i - 1]; } childNode.Items[0] = parentNode.Items[subtreeIndexInNode]; childNode.ItemCount++; T[] oldEntries = childNode.Items; int oldEntries_count = childNode.ItemCount; childNode.Items = leftSibling.Items; childNode.ItemCount = leftSibling.ItemCount; for (int i = 0; i < oldEntries_count; i++) { childNode.Items[childNode.ItemCount - 1] = oldEntries[i]; childNode.ItemCount++; } if (!(leftSibling.ChildCount == 0)) { Node[] oldChildren = childNode.Children; int oldCildren_count = childNode.ChildCount; childNode.Children = leftSibling.Children; childNode.ChildCount = leftSibling.ChildCount; for (int i = 0; i < oldCildren_count; i++) { childNode.Children[childNode.ItemCount - 1] = oldChildren[i]; childNode.ChildCount++; } } for (int i = leftIndex; i < parentNode.ChildCount; i++) { parentNode.Children[i] = parentNode.Children[i + 1]; } parentNode.ChildCount--; for (int i = subtreeIndexInNode; i < parentNode.ItemCount - 1; i++) { parentNode.Items[i] = parentNode.Items[i + 1]; } parentNode.ItemCount--; } else { childNode.Items[childNode.ItemCount] = parentNode.Items[subtreeIndexInNode]; childNode.ItemCount++; for (int i = 0; i < rightSibling.ItemCount; i++) { childNode.Items[childNode.ItemCount] = rightSibling.Items[i]; childNode.ItemCount++; } if (!(rightSibling.ChildCount == 0)) { for (int i = 0; i < rightSibling.ChildCount; i++) { childNode.Children[childNode.ChildCount] = rightSibling.Children[i]; childNode.ChildCount++; } } for (int i = rightIndex; i < parentNode.ChildCount; i++) { parentNode.Children[i] = parentNode.Children[i + 1]; } parentNode.ChildCount--; for (int i = subtreeIndexInNode; i < parentNode.ItemCount; i++) { parentNode.Items[i] = parentNode.Items[i + 1]; } parentNode.ItemCount--; } } } this.Remove(childNode, compare); }