Beispiel #1
0
        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));
        }
Beispiel #2
0
        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));
        }
Beispiel #3
0
 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)));
 }
Beispiel #4
0
 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));
 }
Beispiel #5
0
 /// <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;
 }
Beispiel #6
0
        /// <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();
        }
Beispiel #7
0
        /// <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));
        }
Beispiel #8
0
        /// <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));
                }
            }
        }
Beispiel #9
0
 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)));
 }