Example #1
0
        /// <summary>
        /// Inserts an entry not present in the current version.
        /// </summary>
        /// <returns>New version with inserted vertex</returns>
        public Tree <K, V> Insert(K Key, V Value)
        {
            var newVersion = Version.GetSuccessor();
            // Key must not be present in tree!

            var n = new Node(Key, Value, newVersion).GetTemporaryAccessorForVersion(newVersion);

            if (Root is null)
            {
                var newRoot = n.GetPermanentAccessor();
                Node.RemoveListOfAccessors();
                return(new Tree <K, V> {
                    Root = newRoot, Version = newVersion
                });
            }

            var root = Root.Node.GetTemporaryAccessorForVersion(newVersion);

            var path = GetPath(Key, root);

            if (Key.CompareTo(path.Last().Key) < 0)
            {
                path.Last().Base.Left = n;
            }
            else
            {
                path.Last().Base.Right = n;
            }

            var top = BalancePath(path).GetPermanentAccessor();

            Node.RemoveListOfAccessors();

            FatNode.FinishUpdate();

            return(new Tree <K, V> {
                Root = top, Version = newVersion
            });
        }
Example #2
0
        /// <summary>
        /// Removes an element with specified key producing a new version.
        /// </summary>
        /// <returns>New version with deleted vertex.</returns>
        public Tree <K, V> Delete(K Key)
        {
            if (Root is null)
            {
                throw new InvalidOperationException("Cannot delete from empty tree.");
            }
            // If there is only one vertex return null.
            // This is a technical detail and behaviour may be changed to produce empty tree with a new version.
            if (Root.Left is null && Root.Right is null)
            {
                return(null);
            }

            // Key must be present in tree!

            var newVersion = Version.GetSuccessor();

            Node.NodeAccessor prev = null;

            var root = Root.Node.GetTemporaryAccessorForVersion(newVersion);

            var current = root;

            while (!current.Key.Equals(Key))
            {
                prev    = current;
                current = current.Key.CompareTo(Key) < 0 ?
                          current.Right : current.Left;
            }

            var sub = current;

            Node.NodeAccessor top;

            if (current.Left == null && current.Right == null)
            {
                // Leaf
                if (prev.Right == current)
                {
                    prev.Right = null;
                }
                else
                {
                    prev.Left = null;
                }

                top = BalancePath(GetPath(prev.Key, root));
            }

            // Switch key and value with a leaf vertex

            else if (current.Left == null)
            {
                SwapModPathEnds(current.Key, current.Right.Key);
                current.Key   = current.Right.Key;
                current.Value = current.Right.Value;
                current.Right = null;

                top = BalancePath(GetPath(current.Key, root));
            }

            else if (current.Right == null)
            {
                SwapModPathEnds(current.Key, current.Left.Key);
                current.Key   = current.Left.Key;
                current.Value = current.Left.Value;
                current.Left  = null;

                top = BalancePath(GetPath(current.Key, root));
            }

            else if (prev.Key.CompareTo(Key) > 0)
            {
                current = prev.Right;

                while (current.Right != null)
                {
                    prev = current; current = current.Right;
                }
                ;

                SwapModPathEnds(Key, current.Key);
                sub.Key   = current.Key;
                sub.Value = current.Value;

                if (current.Left == null)
                {
                    prev.Right = null;
                    top        = BalancePath(GetPath(prev.Key, root));
                }
                else
                {
                    SwapModPathEnds(Key, current.Left.Key);
                    current.Key   = current.Left.Key;
                    current.Value = current.Left.Value;
                    current.Left  = null;
                    top           = BalancePath(GetPath(current.Key, root));
                }
            }
            else
            {
                current = prev.Left;

                while (current.Left != null)
                {
                    prev = current; current = current.Left;
                }
                ;

                SwapModPathEnds(Key, current.Key);
                sub.Key   = current.Key;
                sub.Value = current.Value;

                if (current.Right == null)
                {
                    prev.Left = null;
                    top       = BalancePath(GetPath(prev.Key, root));
                }
                else
                {
                    SwapModPathEnds(Key, current.Right.Key);
                    current.Key   = current.Right.Key;
                    current.Value = current.Right.Value;
                    current.Right = null;
                    top           = BalancePath(GetPath(current.Key, root));
                }
            }

            var newRoot = top.GetPermanentAccessor();

            Node.RemoveListOfAccessors();

            FatNode.FinishUpdate();

            return(new Tree <K, V> {
                Root = newRoot, Version = newVersion
            });

            // Update the Key in all modifying paths that end with the vertex subject to key change.
            void SwapModPathEnds(K first, K second)
            {
                List <Node.NodeAccessor> nodes = new List <Node.NodeAccessor>(2);

                var c1 = Root;

                while (c1 != null)
                {
                    if (c1.ModPathEnd == second || c1.ModPathEnd2 == second)
                    {
                        nodes.Add(c1);
                    }
                    c1 = c1.Key.CompareTo(second) > 0 ? c1.Left : c1.Right;
                }

                c1 = Root;
                while (c1 != null)
                {
                    if (c1.ModPathEnd == first)
                    {
                        c1.ModPathEnd = second;
                    }
                    if (c1.ModPathEnd2 == first)
                    {
                        c1.ModPathEnd2 = second;
                    }
                    c1 = c1.Key.CompareTo(first) > 0 ? c1.Left : c1.Right;
                }

                foreach (var node in nodes)
                {
                    if (c1.ModPathEnd == second)
                    {
                        c1.ModPathEnd = first;
                    }
                    if (c1.ModPathEnd2 == second)
                    {
                        c1.ModPathEnd2 = first;
                    }
                }
            }
        }