public static TValue Search <TKey, TValue>(this ImmutableHashTree <TKey, TValue> tree, TKey key) { int hashCode = key.GetHashCode(); while (tree.Height != 0 && tree.HashCode != hashCode) { tree = hashCode < tree.HashCode ? tree.Left : tree.Right; } if (!tree.IsEmpty && (ReferenceEquals(tree.Key, key) || Equals(tree.Key, key))) { return(tree.Value); } if (tree.Duplicates.Items.Length > 0) { foreach (var keyValue in tree.Duplicates.Items) { if (ReferenceEquals(keyValue.Key, key) || Equals(keyValue.Key, key)) { return(keyValue.Value); } } } return(default(TValue)); }
internal static GetInstanceDelegate Search(this ImmutableHashTable <Type, GetInstanceDelegate> hashTable, Type key) { var hashCode = key.GetHashCode(); var bucketIndex = hashCode & (hashTable.Divisor - 1); ImmutableHashTree <Type, GetInstanceDelegate> tree = hashTable.Buckets[bucketIndex]; while (tree.Height != 0 && tree.HashCode != hashCode) { tree = hashCode < tree.HashCode ? tree.Left : tree.Right; } if (tree.Height != 0 && ReferenceEquals(tree.Key, key)) { return(tree.Value); } if (tree.Duplicates.Items.Length > 0) { foreach (var keyValue in tree.Duplicates.Items) { if (ReferenceEquals(keyValue.Key, key)) { return(keyValue.Value); } } } return(default(GetInstanceDelegate)); }
private static ImmutableHashTree <TKey, TValue> RotateRight(ImmutableHashTree <TKey, TValue> right) { return(new ImmutableHashTree <TKey, TValue>( right.Left.Key, right.Left.Value, right.Left.Left, new ImmutableHashTree <TKey, TValue>(right.Key, right.Value, right.Left.Right, right.Right))); }
private static ImmutableHashTree <TKey, TValue> RotateLeft(ImmutableHashTree <TKey, TValue> left) { return(new ImmutableHashTree <TKey, TValue>( left.Right.Key, left.Right.Value, new ImmutableHashTree <TKey, TValue>(left.Key, left.Value, left.Right.Left, left.Left), left.Right.Right)); }
/// <summary> /// Initializes a new instance of the <see cref="ImmutableHashTree{TKey,TValue}"/> class /// and adds a new entry in the <see cref="Duplicates"/> list. /// </summary> /// <param name="key">The key for this node.</param> /// <param name="value">The value for this node.</param> /// <param name="hashTree">The <see cref="ImmutableHashTree{TKey,TValue}"/> that contains existing duplicates.</param> public ImmutableHashTree(TKey key, TValue value, ImmutableHashTree <TKey, TValue> hashTree) { Duplicates = hashTree.Duplicates.Add(new KeyValue <TKey, TValue>(key, value)); Key = hashTree.Key; Value = hashTree.Value; Height = hashTree.Height; HashCode = hashTree.HashCode; Left = hashTree.Left; Right = hashTree.Right; }
/// <summary> /// Initializes a new instance of the <see cref="ImmutableHashTree{TKey,TValue}"/> class. /// </summary> /// <param name="key">The key for this node.</param> /// <param name="value">The value for this node.</param> /// <param name="left">The left node.</param> /// <param name="right">The right node.</param> public ImmutableHashTree(TKey key, TValue value, ImmutableHashTree <TKey, TValue> left, ImmutableHashTree <TKey, TValue> right) { var balance = left.Height - right.Height; if (balance == -2) { if (right.IsLeftHeavy()) { right = RotateRight(right); } // Rotate left Key = right.Key; Value = right.Value; Left = new ImmutableHashTree <TKey, TValue>(key, value, left, right.Left); Right = right.Right; } else if (balance == 2) { if (left.IsRightHeavy()) { left = RotateLeft(left); } // Rotate right Key = left.Key; Value = left.Value; Right = new ImmutableHashTree <TKey, TValue>(key, value, left.Right, right); Left = left.Left; } else { Key = key; Value = value; Left = left; Right = right; } Height = 1 + Math.Max(Left.Height, Right.Height); Duplicates = ImmutableList <KeyValue <TKey, TValue> > .Empty; HashCode = Key.GetHashCode(); }
/// <summary> /// Adds a new element to the <see cref="ImmutableHashTree{TKey,TValue}"/>. /// </summary> /// <typeparam name="TKey">The type of the key.</typeparam> /// <typeparam name="TValue">The type of the value.</typeparam> /// <param name="tree">The target <see cref="ImmutableHashTree{TKey,TValue}"/>.</param> /// <param name="key">The key to be associated with the value.</param> /// <param name="value">The value to be added to the tree.</param> /// <returns>A new <see cref="ImmutableHashTree{TKey,TValue}"/> that contains the new key/value pair.</returns> public static ImmutableHashTree <TKey, TValue> Add <TKey, TValue>(this ImmutableHashTree <TKey, TValue> tree, TKey key, TValue value) { if (tree.IsEmpty) { return(new ImmutableHashTree <TKey, TValue>(key, value, tree, tree)); } int hashCode = key.GetHashCode(); if (hashCode > tree.HashCode) { return(AddToRightBranch(tree, key, value)); } if (hashCode < tree.HashCode) { return(AddToLeftBranch(tree, key, value)); } return(new ImmutableHashTree <TKey, TValue>(key, value, tree)); }
/// <summary> /// Returns the nodes in the tree using in order traversal. /// </summary> /// <typeparam name="TKey">The type of the key.</typeparam> /// <typeparam name="TValue">The type of the value.</typeparam> /// <param name="hashTree">The target <see cref="ImmutableHashTree{TKey,TValue}"/>.</param> /// <returns>The nodes using in order traversal.</returns> public static IEnumerable <KeyValue <TKey, TValue> > InOrder <TKey, TValue>( this ImmutableHashTree <TKey, TValue> hashTree) { if (!hashTree.IsEmpty) { foreach (var left in InOrder(hashTree.Left)) { yield return(new KeyValue <TKey, TValue>(left.Key, left.Value)); } yield return(new KeyValue <TKey, TValue>(hashTree.Key, hashTree.Value)); for (int i = 0; i < hashTree.Duplicates.Items.Length; i++) { yield return(hashTree.Duplicates.Items[i]); } foreach (var right in InOrder(hashTree.Right)) { yield return(new KeyValue <TKey, TValue>(right.Key, right.Value)); } } }
private static ImmutableHashTree <TKey, TValue> AddToRightBranch <TKey, TValue>(ImmutableHashTree <TKey, TValue> tree, TKey key, TValue value) { return(new ImmutableHashTree <TKey, TValue>(tree.Key, tree.Value, tree.Left, tree.Right.Add(key, value))); }