private void Split(TwoFourTreeNode node) { var parent = node.Parent; Debug.Assert(node.IsKeyFull); var midKey = node.Items[1]; var newNode = node.Split(); if (node == _root) { Debug.Assert(parent == null); var newRoot = new TwoFourTreeNode(midKey, node, newNode); _root = newRoot; } else { Debug.Assert(parent != null); var nodeIndex = node.GetChildIndex(); Debug.Assert(parent.Children[nodeIndex] == node); parent.InsertItemChild(nodeIndex, midKey, newNode); } }
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!"); } }