Exemple #1
0
 public AvlTree <K, V> RemoveOrUpdate(K key, UpdateValueInstead updateValue = null)
 {
     return(RemoveOrUpdate(key.GetHashCode(), key, updateValue));
 }
Exemple #2
0
        private AvlTree <K, V> RemoveOrUpdate(int hash, K key, UpdateValueInstead updateValueInstead = null, bool ignoreKey = false)
        {
            if (Height == 0)
            {
                return(this);
            }

            AvlTree <K, V> result;

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

                        if (Conflicts != null)
                        {
                            if (Conflicts.Length == 1)
                            {
                                return(new AvlTree <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 AvlTree <K, V>(Hash, Conflicts[0].Key, Conflicts[0].Value, shrinkedConflicts, Left, Right));
                        }
                    }

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

                    if (Right.IsEmpty)
                    {
                        result = Left;
                    }
                    else if (Left.IsEmpty)
                    {
                        result = Right;
                    }
                    else
                    {
                        // We have two children. 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   newValue;
                    var conflict = Conflicts[index];
                    if (updateValueInstead != null && updateValueInstead(conflict.Key, conflict.Value, out newValue))
                    {
                        var updatedConflicts = new KV <K, V> [Conflicts.Length];
                        Array.Copy(Conflicts, 0, updatedConflicts, 0, updatedConflicts.Length);
                        updatedConflicts[index] = new KV <K, V>(conflict.Key, newValue);
                        return(new AvlTree <K, V>(Hash, Key, Value, updatedConflicts, Left, Right));
                    }

                    if (Conflicts.Length == 1)
                    {
                        return(new AvlTree <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 AvlTree <K, V>(Hash, Key, Value, shrinkedConflicts, Left, Right));
                }
                else  // key is not matching and no conflicts to lookup - just return
                {
                    return(this);
                }
            }
            else if (hash < Hash)
            {
                result = With(Left.RemoveOrUpdate(hash, key, updateValueInstead, ignoreKey), Right);
            }
            else
            {
                result = With(Left, Right.RemoveOrUpdate(hash, key, updateValueInstead, ignoreKey));
            }
            return(result.KeepBalanced());
        }