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); }
private void UpdateStackProperties(int sizeDiff) { StackFrame frame = StackEnd(0); int sz = FrameCount; // Walk the stack from the end for (int i = 1; i < sz; ++i) { int childIndex = frame.ChildIndex; frame = StackEnd(i); NodeId nodeId = frame.NodeId; TreeBranch branch = (TreeBranch)FetchNode(nodeId); branch.SetChildLeafElementCount(branch.GetChildLeafElementCount(childIndex) + sizeDiff, childIndex); } }
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(); }
public void InsertLeaf(Key newLeafKey, TreeLeaf newLeaf, bool before) { int leafSize = newLeaf.Length; if (leafSize <= 0) { throw new ArgumentException("size <= 0"); } // The current absolute position and key Key newKey = newLeafKey; // The frame at the end of the stack, StackFrame frame = StackEnd(0); object[] info; object[] rInfo = new object[5]; Key leftKey; long curAbsolutePos; // If we are inserting the new leaf after, if (!before) { info = new object[] { currentLeaf.Id, (long)currentLeaf.Length, newLeafKey, newLeaf.Id, (long)newLeaf.Length }; leftKey = null; curAbsolutePos = frame.Offset + currentLeaf.Length; } // Otherwise we are inserting the new leaf before, else { // If before and current_leaf key is different than new_leaf key, we // generate an error if (!currentLeafKey.Equals(newLeafKey)) { throw new InvalidOperationException("Can't insert different new key before."); } info = new Object[] { newLeaf.Id, (long)newLeaf.Length, currentLeafKey, currentLeaf.Id, (long)currentLeaf.Length }; leftKey = newLeafKey; curAbsolutePos = frame.Offset - 1; } bool insertTwoNodes = true; int sz = FrameCount; // Walk the stack from the end for (int i = 1; i < sz; ++i) { // child_i is the previous frame's child_i int childIndex = frame.ChildIndex; frame = StackEnd(i); // The child ref of this stack element NodeId childId = frame.NodeId; // Fetch it TreeBranch branch = (TreeBranch)UnfreezeNode(FetchNode(childId)); // Do we have two nodes to insert into the branch? if (insertTwoNodes) { TreeBranch insertBranch; int insertIndex = childIndex; // If the branch is full, if (branch.IsFull) { // Create a new node, TreeBranch leftBranch = branch; TreeBranch rightBranch = CreateBranch(); // Split the branch, Key midpointKey = leftBranch.MidPointKey; // And move half of this branch into the new branch leftBranch.MoveLastHalfInto(rightBranch); // We split so we need to return a split flag, rInfo[0] = leftBranch.Id; rInfo[1] = leftBranch.LeafElementCount; rInfo[2] = midpointKey; rInfo[3] = rightBranch.Id; rInfo[4] = rightBranch.LeafElementCount; // Adjust insert_n and insert_branch if (insertIndex >= leftBranch.ChildCount) { insertIndex -= leftBranch.ChildCount; insertBranch = rightBranch; rInfo[4] = (long)rInfo[4] + newLeaf.Length; // If insert_n == 0, we change the midpoint value to the left // key value, if (insertIndex == 0 && leftKey != null) { rInfo[2] = leftKey; leftKey = null; } } else { insertBranch = leftBranch; rInfo[1] = (long)rInfo[1] + newLeaf.Length; } } // If it's not full, else { insertBranch = branch; rInfo[0] = insertBranch.Id; insertTwoNodes = false; } // Insert the two children nodes insertBranch.Insert((NodeId)info[0], (long)info[1], (Key)info[2], (NodeId)info[3], (long)info[4], insertIndex); // Copy r_nfo to nfo for (int p = 0; p < rInfo.Length; ++p) { info[p] = rInfo[p]; } // Adjust the left key reference if necessary if (leftKey != null && insertIndex > 0) { insertBranch.SetKeyToLeft(leftKey, insertIndex); leftKey = null; } } else { branch.SetChild((NodeId)info[0], childIndex); info[0] = branch.Id; branch.SetChildLeafElementCount( branch.GetChildLeafElementCount(childIndex) + leafSize, childIndex); // Adjust the left key reference if necessary if (leftKey != null && childIndex > 0) { branch.SetKeyToLeft(leftKey, childIndex); leftKey = null; } } } // For all elements in the stack, // At the end, if we still have a split then we make a new root and // adjust the stack accordingly if (insertTwoNodes) { TreeBranch newRoot = CreateBranch(); newRoot.Set((NodeId)info[0], (long)info[1], (Key)info[2], (NodeId)info[3], (long)info[4]); RootNodeId = newRoot.Id; if (TreeHeight != -1) { TreeHeight = TreeHeight + 1; } } else { RootNodeId = (NodeId)info[0]; } // Now reset the position, Reset(); SetupForPosition(newKey, curAbsolutePos); }
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; }