示例#1
0
        private HashTree <K, V> RemoveOrUpdate(int hash, K key, IsUpdated <V> isUpdated = null, bool ignoreKey = false)
        {
            if (Height == 0)
            {
                return(this);
            }

            HashTree <K, V> result;

            if (hash == Hash) // found matched Node
            {
                if (ignoreKey || Equals(Key, key))
                {
                    if (!ignoreKey)
                    {
                        V updatedValue;
                        if (isUpdated != null && isUpdated(Value, out updatedValue))
                        {
                            return(new HashTree <K, V>(Hash, Key, updatedValue, Conflicts, Left, Right));
                        }

                        if (Conflicts != null)
                        {
                            if (Conflicts.Length == 1)
                            {
                                return(new HashTree <K, V>(Hash, Conflicts[0].Key, Conflicts[0].Value, null, Left, Right));
                            }
                            var shrinkedConflicts = new KV <K, V> [Conflicts.Length - 1];
                            Array.Copy(Conflicts, 1, shrinkedConflicts, 0, shrinkedConflicts.Length);
                            return(new HashTree <K, V>(Hash, Conflicts[0].Key, Conflicts[0].Value, shrinkedConflicts, Left, Right));
                        }
                    }

                    if (Height == 1) // remove node
                    {
                        return(Empty);
                    }

                    if (Right.IsEmpty)
                    {
                        result = Left;
                    }
                    else if (Left.IsEmpty)
                    {
                        result = Right;
                    }
                    else
                    {
                        // we have two children, so remove the next highest node and replace this node with it.
                        var successor = Right;
                        while (!successor.Left.IsEmpty)
                        {
                            successor = successor.Left;
                        }
                        result = successor.With(Left, Right.RemoveOrUpdate(successor.Hash, default(K), ignoreKey: true));
                    }
                }
                else if (Conflicts != null)
                {
                    var index = Conflicts.Length - 1;
                    while (index >= 0 && !Equals(Conflicts[index].Key, key))
                    {
                        --index;
                    }
                    if (index == -1)        // key is not found in conflicts - just return
                    {
                        return(this);
                    }

                    V   updatedValue;
                    var conflict = Conflicts[index];
                    if (isUpdated != null && isUpdated(conflict.Value, out updatedValue))
                    {
                        var updatedConflicts = new KV <K, V> [Conflicts.Length];
                        Array.Copy(Conflicts, 0, updatedConflicts, 0, updatedConflicts.Length);
                        updatedConflicts[index] = new KV <K, V>(conflict.Key, updatedValue);
                        return(new HashTree <K, V>(Hash, Key, Value, updatedConflicts, Left, Right));
                    }

                    if (Conflicts.Length == 1)
                    {
                        return(new HashTree <K, V>(Hash, Key, Value, null, Left, Right));
                    }
                    var shrinkedConflicts = new KV <K, V> [Conflicts.Length - 1];
                    var newIndex          = 0;
                    for (var i = 0; i < Conflicts.Length; ++i)
                    {
                        if (i != index)
                        {
                            shrinkedConflicts[newIndex++] = Conflicts[i];
                        }
                    }
                    return(new HashTree <K, V>(Hash, Key, Value, shrinkedConflicts, Left, Right));
                }
                else
                {
                    return(this); // if key is not matching and no conflicts to lookup - just return
                }
            }
            else if (hash < Hash)
            {
                result = With(Left.RemoveOrUpdate(hash, key, isUpdated, ignoreKey), Right);
            }
            else
            {
                result = With(Left, Right.RemoveOrUpdate(hash, key, isUpdated, ignoreKey));
            }
            return(result.KeepBalanced());
        }
示例#2
0
 /// <summary>Removes or updates value for specified key, or does nothing if key is not found.
 /// Based on Eric Lippert http://blogs.msdn.com/b/ericlippert/archive/2008/01/21/immutability-in-c-part-nine-academic-plus-my-avl-tree-implementation.aspx </summary>
 /// <param name="key">Key to look for.</param> <param name="isUpdated">(optional) Delegate to update value, return true from delegate if value is updated.</param>
 /// <returns>New tree with removed or updated value.</returns>
 public HashTree <K, V> RemoveOrUpdate(K key, IsUpdated <V> isUpdated = null)
 {
     return(RemoveOrUpdate(key.GetHashCode(), key, isUpdated));
 }