private void RemoveItem(TwoFourTreeNode node, int index) { /* * To remove a value from the 2–3–4 tree: * 1. Find the element to be deleted. * • If the element is not in a leaf node, remember its location and continue searching until a leaf, which will contain the element’s successor, is reached. * The successor can be either the largest key that is smaller than the one to be removed, or the smallest key that is larger than the one to be removed. * It is simplest to make adjustments to the tree from the top down such that the leaf node found is not a 2-node. That way, after the swap, there will not be an empty leaf node. * • If the element is in a 2-node leaf, just make the adjustments below. * Make the following adjustments when a 2-node – except the root node – is encountered on the way to the leaf we want to remove: * 1. If a sibling on either side of this node is a 3-node or a 4-node (thus having more than 1 key), perform a rotation with that sibling: * • The key from the other sibling closest to this node moves up to the parent key that overlooks the two nodes. * • The parent key moves down to this node to form a 3-node. * • The child that was originally with the rotated sibling key is now this node's additional child. * 2. If the parent is a 2-node and the sibling is also a 2-node, combine all three elements to form a new 4-node and shorten the tree. (This rule can only trigger if the parent 2-node is the root, * since all other 2-nodes along the way will have been modified to not be 2-nodes. This is why "shorten the tree" here preserves balance; this is also an important assumption for the fusion operation.) * 3. If the parent is a 3-node or a 4-node and all adjacent siblings are 2-nodes, do a fusion operation with the parent and an adjacent sibling: * • The adjacent sibling and the parent key overlooking the two sibling nodes come together to form a 4-node. * • Transfer the sibling's children to this node. * Once the sought value is reached, it can now be placed at the removed entry's location without a problem because we have ensured that the leaf node has more than 1 key. */ if (node.IsLeafNode) { node.RemoveItem(index); if (node.KeyNum == 0 && node != _root) { Debug.Assert(node.Parent != null); AdjustNodeWhenRemove(node); // if (node.GetChildIndex() < 0) node.Invalidate(); } _count--; _version++; } else { var successor = node.Children[index].GetMaxLeafNode(); var item = successor.Items[successor.KeyNum - 1]; node.Items[index] = item; RemoveItem(successor, successor.KeyNum - 1); } }