Exemple #1
0
            private bool BalanceBranch2(Branch left)
            {
                var right = (Branch)TopNode;

                if (left.KeyCount + right.KeyCount < tree.maxKeyCount)
                {
                    // Coalesce left: move pivot and right sibling nodes.
                    left.AddKey(GetPivot());

                    for (int ix1 = 0; ; ++ix1)
                    {
                        left.Add(right.GetChild(ix1));
                        if (ix1 >= right.KeyCount)
                        {
                            break;
                        }
                        left.AddKey(right.GetKey(ix1));
                    }
                    left.AdjustWeight(+right.Weight);
                    TiltLeft(+right.Weight);

                    // Pivot must still be removed.
                    return(true);
                }

                // Branch underflow?
                if (tree.IsUnderflow(left.ChildCount))
                {
                    // Balance branches to keep ratio.  Rotate thru the pivot.
                    int shifts = (left.KeyCount + right.KeyCount - 1) / 2 - left.KeyCount;
                    left.AddKey(GetPivot());

                    int delta = 0;
                    for (int ix2 = 0; ; ++ix2)
                    {
                        left.Add(right.GetChild(ix2));
                        delta += right.GetChild(ix2).Weight;

                        if (ix2 >= shifts)
                        {
                            break;
                        }

                        left.AddKey(right.GetKey(ix2));
                    }

                    SetPivot(right.GetKey(shifts));
                    right.Remove(0, shifts + 1);
                    left.AdjustWeight(+delta);
                    right.AdjustWeight(-delta);
                    TiltLeft(delta);
                }

                return(false);
            }
Exemple #2
0
            // Leaf or branch has been split so insert the new anchor into a branch.
            public void Promote(T key, Node newNode, bool isAppend)
            {
                for (;;)
                {
                    if (Height == 1)
                    {
                        // Graft new root.
                        Debug.Assert(tree.root == TopNode);
                        tree.root = new Branch(tree.maxKeyCount, TopNode, TopNode.Weight + newNode.Weight);
                        ((Branch)tree.root).Add(key, newNode);
                        break;
                    }

                    Pop();
                    var branch      = (Branch)TopNode;
                    int branchIndex = TopIndex;

                    if (branch.KeyCount < tree.maxKeyCount)
                    {
                        // Typical case where branch has room.
                        branch.InsertKey(branchIndex, key);
                        branch.Insert(branchIndex + 1, newNode);
                        break;
                    }

                    // Branch is full so right split a new branch.
                    var newBranch  = new Branch(tree.maxKeyCount);
                    int splitIndex = isAppend ? branch.KeyCount - 1 : (branch.KeyCount + 1) / 2;

                    if (branchIndex < splitIndex)
                    {
                        // Split branch with left-side insert.
                        for (int ix = splitIndex; ; ++ix)
                        {
                            newBranch.AdjustWeight(+branch.GetChild(ix).Weight);
                            if (ix >= branch.KeyCount)
                            {
                                newBranch.Add(branch.GetChild(ix));
                                break;
                            }
                            newBranch.Add(branch.GetKey(ix), branch.GetChild(ix));
                        }

                        T newPromotion = branch.GetKey(splitIndex - 1);
                        branch.Truncate(splitIndex - 1);
                        branch.InsertKey(branchIndex, key);
                        branch.Insert(branchIndex + 1, newNode);
                        key = newPromotion;
                        branch.AdjustWeight(-newBranch.Weight);
                    }
                    else
                    {
                        // Split branch with right-side insert (or cascade promote).
                        int leftIndex = splitIndex;
                        newBranch.AdjustWeight(newNode.Weight);

                        if (branchIndex > splitIndex)
                        {
                            for (;;)
                            {
                                ++leftIndex;
                                newBranch.Add(branch.GetChild(leftIndex));
                                newBranch.AdjustWeight(+branch.GetChild(leftIndex).Weight);
                                if (leftIndex >= branchIndex)
                                {
                                    break;
                                }
                                newBranch.AddKey(branch.GetKey(leftIndex));
                            }
                            newBranch.AddKey(key);
                            key = branch.GetKey(splitIndex);
                        }

                        newBranch.Add(newNode);

                        while (leftIndex < branch.KeyCount)
                        {
                            newBranch.AddKey(branch.GetKey(leftIndex));
                            ++leftIndex;
                            newBranch.Add(branch.GetChild(leftIndex));
                            newBranch.AdjustWeight(+branch.GetChild(leftIndex).Weight);
                        }

                        branch.Truncate(splitIndex);
                        branch.AdjustWeight(-newBranch.Weight);
                    }

                    newNode = newBranch;
                }
            }