public void MergeWithRight(int rightIndex, TwoFourTreeNode right) { Debug.Assert(_keyNum == 0 && right._keyNum == 1 || _keyNum == 1 && right._keyNum == 0); Debug.Assert(Parent != null); Debug.Assert(Parent == right.Parent); Debug.Assert(Parent.Children[rightIndex] == right); var pair = Parent.RemoveItemChild(rightIndex - 1); AppendItemChild(pair.Item, IsLeafNode ? null : right._children[0]); if (right._keyNum != 0) { AppendItemChild(right._items[0], IsLeafNode ? null : right._children[1]); } right.Invalidate(); }
private void AdjustNodeWhenRemove(TwoFourTreeNode node) { var parent = node.Parent; Debug.Assert(parent != null); var childIndex = node.GetChildIndex(); var leftSiblingIndex = childIndex - 1; var rightSiblingIndex = childIndex + 1; // If a sibling on either side of this node is a 3-node or a 4-node (thus having more than 1 key) if (rightSiblingIndex <= parent.KeyNum && !parent.Children[rightSiblingIndex].IsKeyMin) { var sibling = parent.Children[rightSiblingIndex]; var pair = sibling.RemoveFirstItemChild(); node.AppendItemChild(parent.Items[childIndex], pair.Node); parent.Items[childIndex] = pair.Item; } else if (leftSiblingIndex >= 0 && !parent.Children[leftSiblingIndex].IsKeyMin) { var sibling = parent.Children[leftSiblingIndex]; var pair = sibling.RemoveLastItemChild(); node.PushFrontItemChild(parent.Items[leftSiblingIndex], pair.Node); parent.Items[leftSiblingIndex] = pair.Item; } // If all adjacent siblings are 2-nodes else if (rightSiblingIndex <= parent.KeyNum && parent.Children[rightSiblingIndex].IsKeyMin) { node.MergeWithRight(rightSiblingIndex, parent.Children[rightSiblingIndex]); if (parent.KeyNum == 0) { if (parent == _root) { _root.Invalidate(); _root = node; _root.Parent = null; } else { AdjustNodeWhenRemove(parent); } } } else if (leftSiblingIndex >= 0 && parent.Children[leftSiblingIndex].IsKeyMin) { var sibling = parent.Children[leftSiblingIndex]; sibling.MergeWithRight(childIndex, node); if (parent.KeyNum == 0) { if (parent == _root) { _root.Invalidate(); _root = sibling; _root.Parent = null; } else { AdjustNodeWhenRemove(parent); } } } else { throw new Exception("cannot reach here!"); } }