private bool RedistributeBranchElements(TreeBranch branch, int childIndex, TreeBranch child) { // We distribute the nodes in the child branch with the branch // immediately to the right. If that's not possible, then we distribute // with the left. // If branch has only a single value, return immediately int branchSize = branch.ChildCount; if (branchSize == 1) { return(false); } int leftI, rightI; TreeBranch left, right; if (childIndex < branchSize - 1) { // Distribute with the right leftI = childIndex; rightI = childIndex + 1; left = child; right = (TreeBranch)UnfreezeNode(FetchNode(branch.GetChild(childIndex + 1))); branch.SetChild(right.Id, childIndex + 1); } else { // Distribute with the left leftI = childIndex - 1; rightI = childIndex; left = (TreeBranch)UnfreezeNode(FetchNode(branch.GetChild(childIndex - 1))); right = child; branch.SetChild(left.Id, childIndex - 1); } // Get the mid value key reference Key midKey = branch.GetKey(rightI); // Perform the merge, Key newMidKey = left.Merge(right, midKey); // Reset the leaf element count branch.SetChildLeafElementCount(left.LeafElementCount, leftI); branch.SetChildLeafElementCount(right.LeafElementCount, rightI); // If after the merge the right branch is empty, we need to remove it if (right.IsEmpty) { // Delete the node DeleteNode(right.Id); // And remove it from the branch, branch.RemoveChild(rightI); return(true); } // Otherwise set the key reference branch.SetKeyToLeft(newMidKey, rightI); return(false); }
public void DeleteLeaf(Key key) { // Set up the state StackFrame frame = StackEnd(0); NodeId thisRef = frame.NodeId; TreeBranch branchNode = null; int deleteNodeSize = -1; Key leftKey = null; // Walk back through the rest of the stack int sz = FrameCount; for (int i = 1; i < sz; ++i) { // Find the child_i for the child // This is the child_i of the child in the current branch int childIndex = frame.ChildIndex; // Move the stack frame, frame = StackEnd(i); NodeId childId = thisRef; thisRef = frame.NodeId; TreeBranch childBranch = branchNode; branchNode = (TreeBranch)UnfreezeNode(FetchNode(thisRef)); if (deleteNodeSize == -1) { deleteNodeSize = (int)branchNode.GetChildLeafElementCount(childIndex); } // If the child branch is empty, if (childBranch == null || childBranch.IsEmpty) { // Delete the reference to it, if (childIndex == 0 && branchNode.ChildCount > 1) { leftKey = branchNode.GetKey(1); } branchNode.RemoveChild(childIndex); // Delete the child branch, DeleteNode(childId); } // Not empty, else { // Replace with the new child node reference branchNode.SetChild(childBranch.Id, childIndex); // Set the element count long newChildSize = branchNode.GetChildLeafElementCount(childIndex) - deleteNodeSize; branchNode.SetChildLeafElementCount(newChildSize, childIndex); // Can we set the left key reference? if (childIndex > 0 && leftKey != null) { branchNode.SetKeyToLeft(leftKey, childIndex); leftKey = null; } // Has the size of the child reached the lower threshold? if (childBranch.ChildCount <= 2) { // If it has, we need to redistribute the children, RedistributeBranchElements(branchNode, childIndex, childBranch); } } } // Finally, set the root node // If the branch node is a single element, we set the root as the child, if (branchNode.ChildCount == 1) { // This shrinks the height of the tree, RootNodeId = branchNode.GetChild(0); DeleteNode(branchNode.Id); if (TreeHeight != -1) { TreeHeight = TreeHeight - 1; } } else { // Otherwise, we set the branch node. RootNodeId = branchNode.Id; } // Reset the object Reset(); }
private bool RedistributeBranchElements(TreeBranch branch, int childIndex, TreeBranch child) { // We distribute the nodes in the child branch with the branch // immediately to the right. If that's not possible, then we distribute // with the left. // If branch has only a single value, return immediately int branchSize = branch.ChildCount; if (branchSize == 1) { return false; } int leftI, rightI; TreeBranch left, right; if (childIndex < branchSize - 1) { // Distribute with the right leftI = childIndex; rightI = childIndex + 1; left = child; right = (TreeBranch)UnfreezeNode(FetchNode(branch.GetChild(childIndex + 1))); branch.SetChild(right.Id, childIndex + 1); } else { // Distribute with the left leftI = childIndex - 1; rightI = childIndex; left = (TreeBranch)UnfreezeNode(FetchNode(branch.GetChild(childIndex - 1))); right = child; branch.SetChild(left.Id, childIndex - 1); } // Get the mid value key reference Key midKey = branch.GetKey(rightI); // Perform the merge, Key newMidKey = left.Merge(right, midKey); // Reset the leaf element count branch.SetChildLeafElementCount(left.LeafElementCount, leftI); branch.SetChildLeafElementCount(right.LeafElementCount, rightI); // If after the merge the right branch is empty, we need to remove it if (right.IsEmpty) { // Delete the node DeleteNode(right.Id); // And remove it from the branch, branch.RemoveChild(rightI); return true; } // Otherwise set the key reference branch.SetKeyToLeft(newMidKey, rightI); return false; }