Example #1
0
        private bool RemoveItemFromNode(BPlusNode <TItem> node, TItem itemToDelete, int itemIndexInNode)
        {
            // if leaf, just remove it from the list of entries (we're guaranteed to have
            // at least "degree" # of entries, to BTree property is maintained
            if (node.IsLeaf)
            {
                node.RemoveItem(itemIndexInNode);
                return(true);
            }

            var predecessorChild = node.Nodes[itemIndexInNode];

            if (predecessorChild.Items.Count >= _degree)
            {
                var predecessor = RemovePredecessor(predecessorChild);
                node.Items[itemIndexInNode] = predecessor;
            }
            else
            {
                var successorChild = node.Nodes[itemIndexInNode + 1];
                if (successorChild.Items.Count >= _degree)
                {
                    var successor = RemoveSuccessor(predecessorChild);
                    node.Items[itemIndexInNode] = successor;
                }
                else
                {
                    predecessorChild.InsertItem(node.Items[itemIndexInNode]);

                    predecessorChild.InsertItems(successorChild.Items);
                    predecessorChild.InsertNodes(successorChild.Nodes);

                    node.RemoveItem(itemIndexInNode);
                    node.RemoveNode(itemIndexInNode + 1);

                    return(RemoveInternal(predecessorChild, itemToDelete));
                }
            }

            return(false);
        }
Example #2
0
        private bool RemoveItemFromSubTree(BPlusNode <TItem> parentNode, TItem itemToDelete, int subTreeIndex)
        {
            var childNode = parentNode.Nodes[subTreeIndex];

            // node has reached min # of entries, and removing any from it will break the btree property,
            // so this block makes sure that the "child" has at least "degree" # of nodes by moving an
            // entry from a sibling node or merging nodes
            if (childNode.HasReachedMinSize)
            {
                var leftIndex   = subTreeIndex - 1;
                var leftSibling = subTreeIndex > 0 ? parentNode.Nodes[leftIndex] : null;

                var rightIndex   = subTreeIndex + 1;
                var rightSibling = subTreeIndex < parentNode.Nodes.Count - 1 ? parentNode.Nodes[rightIndex] : null;

                if (leftSibling != null && leftSibling.Items.Count > _degree - 1)
                {
                    // left sibling has a node to spare, so this moves one node from left sibling
                    // into parent's node and one node from parent into this current node ("child")
                    childNode.InsertItem(0, parentNode.Items[subTreeIndex]);
                    parentNode.Items[subTreeIndex] = leftSibling.Items[leftSibling.Items.Count - 1];
                    leftSibling.RemoveItem(leftSibling.Items.Count - 1);

                    if (!leftSibling.IsLeaf)
                    {
                        childNode.InsertNode(0, leftSibling.Nodes[leftSibling.Nodes.Count - 1]);
                        leftSibling.RemoveNode(leftSibling.Nodes.Count - 1);
                    }
                }
                else if (rightSibling != null && rightSibling.Items.Count > _degree - 1)
                {
                    // right sibling has a node to spare, so this moves one node from right sibling
                    // into parent's node and one node from parent into this current node ("child")
                    childNode.InsertItem(parentNode.Items[subTreeIndex]);
                    parentNode.Items[subTreeIndex] = rightSibling.Items[0];
                    rightSibling.RemoveItem(0);

                    if (!rightSibling.IsLeaf)
                    {
                        childNode.InsertNode(rightSibling.Nodes[0]);
                        rightSibling.RemoveNode(0);
                    }
                }
                else
                {
                    // this block merges either left or right sibling into the current node "child"
                    if (leftSibling != null)
                    {
                        childNode.InsertItem(0, parentNode.Items[subTreeIndex]);

                        var oldEntries = childNode.Items;

                        childNode.Items = leftSibling.Items;
                        childNode.InsertItems(oldEntries);

                        if (!leftSibling.IsLeaf)
                        {
                            var oldChildren = childNode.Nodes;

                            childNode.Nodes = leftSibling.Nodes;
                            childNode.InsertNodes(oldChildren);
                        }

                        parentNode.RemoveNode(leftIndex);
                        parentNode.RemoveItem(subTreeIndex);
                    }
                    else
                    {
                        childNode.InsertItem(parentNode.Items[subTreeIndex]);
                        childNode.InsertItems(rightSibling.Items);

                        if (!rightSibling.IsLeaf)
                        {
                            childNode.InsertNodes(rightSibling.Nodes);
                        }

                        parentNode.RemoveNode(rightIndex);
                        parentNode.RemoveItem(subTreeIndex);
                    }
                }
            }

            // at this point, we know that "child" has at least "degree" nodes, so we can
            // move on - this guarantees that if any node needs to be removed from it to
            // guarantee BTree's property, we will be fine with that
            return(RemoveInternal(childNode, itemToDelete));
        }