public ITwoThree <T> Insert(T item, IComparer <T> comparer, out ITwoThree <T> splitLeft, out ITwoThree <T> splitRight, out T splitValue)
        {
            // Default split values.
            splitLeft  = splitRight = null;
            splitValue = default(T);

            // Get side to insert node.
            var side = GetSide(item, comparer);

            // Values are equal, no need to change tree.
            if (IsSame(side))
            {
                return(this);
            }

            // Insert value into proper node.
            T             pv;
            ITwoThree <T> pl, pr;
            var           child = GetChild(side);
            var           node  = child.Insert(item, comparer, out pl, out pr, out pv);

            // Insert propagated single node.
            if (node != null)
            {
                return(node == child ? this : NewChangedNode(node, side));
            }

            // Insert propagated two nodes and value, meaning it split.
            // Sinde this is 3-node, we are at full capacity and need to split too.
            switch (side)
            {
            case Side.Left:
                splitLeft  = new TwoNode <T>(pv, pl, pr);
                splitRight = new TwoNode <T>(Second, Middle, Right);
                splitValue = First;
                break;

            case Side.Middle:
                splitLeft  = new TwoNode <T>(First, Left, pl);
                splitRight = new TwoNode <T>(Second, pr, Right);
                splitValue = pv;
                break;

            case Side.Right:
                splitLeft  = new TwoNode <T>(First, Left, Middle);
                splitRight = new TwoNode <T>(pv, pl, pr);
                splitValue = Second;
                break;
            }

            return(null);
        }
Exemple #2
0
        private ITwoThree <T> RedistributeOrMerge(T value, ITwoThree <T> left, ITwoThree <T> right, Side removedSide, out bool removed)
        {
            removed = false;

            if (removedSide == Side.Right)
            {
                if (left is ThreeNode <T> )
                {
                    // Right redistribute case.

                    var red = (ThreeNode <T>)left;
                    var l   = new TwoNode <T>(red.First, red.Left, red.Middle);
                    var r   = new TwoNode <T>(value, red.Right, right);

                    return(new TwoNode <T>(red.Second, l, r));
                }

                // Right merge case.

                var m = (TwoNode <T>)left;

                removed = true;
                return(new ThreeNode <T>(m.Value, value, m.Left, m.Right, right));
            }

            if (removedSide == Side.Left)
            {
                if (right is ThreeNode <T> )
                {
                    // Left redistribute case.

                    var led = (ThreeNode <T>)right;
                    var l   = new TwoNode <T>(value, left, led.Left);
                    var r   = new TwoNode <T>(led.Second, led.Middle, led.Right);

                    return(new TwoNode <T>(led.First, l, r));
                }

                // Left merge case.

                var m = (TwoNode <T>)right;

                removed = true;
                return(new ThreeNode <T>(value, m.Value, left, m.Left, m.Right));
            }

            throw new InvalidOperationException();
        }
        private static ITwoThree <T> RedistributeRight(T first, T second, ITwoThree <T> left, ITwoThree <T> middle, ITwoThree <T> right)
        {
            // Case A
            if (left is TwoNode <T> && middle is TwoNode <T> )
            {
                var sm = (TwoNode <T>)middle;

                var l = left;
                var r = new ThreeNode <T>(sm.Value, second, sm.Left, sm.Right, right);

                return(new TwoNode <T>(first, l, r));
            }

            // Case B
            if (middle is ThreeNode <T> )
            {
                var sm = (ThreeNode <T>)middle;

                var l = left;
                var m = new TwoNode <T>(sm.First, sm.Left, sm.Middle);
                var r = new TwoNode <T>(second, sm.Right, right);

                return(new ThreeNode <T>(first, sm.Second, l, m, r));
            }

            // Case C
            if (left is ThreeNode <T> && middle is TwoNode <T> )
            {
                var sl = (ThreeNode <T>)left;
                var sm = (TwoNode <T>)middle;

                var l = new TwoNode <T>(sl.First, sl.Left, sl.Middle);
                var m = new TwoNode <T>(first, sl.Right, sm.Left);
                var r = new TwoNode <T>(second, sm.Right, right);

                return(new ThreeNode <T>(sl.Second, sm.Value, l, m, r));
            }

            throw new InvalidOperationException();
        }
        private static ITwoThree <T> RedistributeMiddle(T first, T second, ITwoThree <T> left, ITwoThree <T> middle, ITwoThree <T> right)
        {
            // Case A
            if (left is TwoNode <T> && right is TwoNode <T> )
            {
                var sl = (TwoNode <T>)left;

                var l = new ThreeNode <T>(sl.Value, first, sl.Left, sl.Right, middle);
                var r = right;

                return(new TwoNode <T>(second, l, r));
            }

            // Case B
            if (right is ThreeNode <T> )
            {
                var sr = (ThreeNode <T>)right;

                var l = left;
                var m = new TwoNode <T>(second, middle, sr.Left);
                var r = new TwoNode <T>(sr.Second, sr.Middle, sr.Right);

                return(new ThreeNode <T>(first, sr.First, l, m, r));
            }

            // Case C
            if (left is ThreeNode <T> && right is TwoNode <T> )
            {
                var sl = (ThreeNode <T>)left;

                var l = new TwoNode <T>(sl.First, sl.Left, sl.Middle);
                var m = new TwoNode <T>(first, sl.Right, middle);
                var r = right;

                return(new ThreeNode <T>(sl.Second, second, l, m, r));
            }

            throw new InvalidOperationException();
        }