private void CheckIfCanMergeWith(IBTreeNode node) { if (NbKeys + node.GetNbKeys() > _maxNbKeys) { var errorMessage = string.Concat("Trying to merge two nodes with too many keys ", NbKeys.ToString(), " + ", node.GetNbKeys().ToString(), " > ", _maxNbKeys.ToString()); throw new BTreeException(errorMessage); } if (NbKeys > 0) { var greatestOfThis = Keys[NbKeys - 1]; var smallestOfOther = node.GetKeyAt(0); if (greatestOfThis.CompareTo(smallestOfOther) >= 0) { var errorMessage = string.Format("Trying to merge two nodes that have intersections : {0} / {1}", ToString(), node); throw new BTreeNodeValidationException(errorMessage); } } if (NbKeys < NbChildren) { throw new BTreeNodeValidationException("Trying to merge two nodes where the first one has more children than keys"); } }
/// <summary> /// Can only merge node without intersection => the greater key of this must be smaller than the smallest key of the node /// </summary> public virtual void MergeWith(IBTreeNode node) { BTreeValidator.ValidateNode(this); BTreeValidator.ValidateNode(node); CheckIfCanMergeWith(node); var j = NbKeys; for (var i = 0; i < node.GetNbKeys(); i++) { SetKeyAndValueAt(node.GetKeyAt(i), node.GetValueAsObjectAt(i), j, false, false); SetChildAt(node, i, j, false); j++; } // in this, we have to take the last child if (node.GetNbChildren() > node.GetNbKeys()) { SetChildAt(node, node.GetNbChildren() - 1, j, true); } NbKeys += node.GetNbKeys(); NbChildren += node.GetNbChildren(); BTreeValidator.ValidateNode(this); }
private void InsertNonFull(IBTreeNode node, IComparable key, object value) { if (node.IsLeaf()) { node.InsertKeyAndValue(key, value); _persister.SaveNode(node); return; } var position = node.GetPositionOfKey(key); // return an index starting // from 1 instead of 0 var realPosition = -position - 1; // If position is positive, the key must be inserted in this node if (position >= 0) { node.InsertKeyAndValue(key, value); _persister.SaveNode(node); return; } // descend var nodeToDescend = node.GetChildAt(realPosition, true); if (nodeToDescend.IsFull()) { Split(node, nodeToDescend, realPosition); if (node.GetKeyAt(realPosition).CompareTo(key) < 0) { nodeToDescend = node.GetChildAt(realPosition + 1, true); } } InsertNonFull(nodeToDescend, key, value); }
/// <summary> /// Returns the value of the deleted key /// </summary> /// <param name="node"> </param> /// <param name="keyAndValue"> </param> /// <returns> </returns> /// <exception cref="System.Exception">System.Exception</exception> private object InternalDelete(IBTreeNode node, IKeyAndValue keyAndValue) { var positionOfKey = node.GetPositionOfKey(keyAndValue.GetKey()); var keyIsHere = positionOfKey > 0; if (node.IsLeaf()) { if (keyIsHere) { var deletedValue = node.DeleteKeyForLeafNode(keyAndValue); GetPersister().SaveNode(node); return(deletedValue); } // key does not exist return(null); } int realPosition; if (!keyIsHere) { // descend realPosition = -positionOfKey - 1; var childTreeNode = node.GetChildAt(realPosition, true); if (childTreeNode.GetNbKeys() == _degree - 1) { node = PrepareForDelete(node, childTreeNode, realPosition); return(InternalDelete(node, keyAndValue)); } return(InternalDelete(childTreeNode, keyAndValue)); } // Here,the node is not a leaf and contains the key realPosition = positionOfKey - 1; var currentKey = node.GetKeyAt(realPosition); var currentValue = node.GetValueAsObjectAt(realPosition); // case 2a var leftNode = node.GetChildAt(realPosition, true); if (leftNode.GetNbKeys() >= _degree) { var prevKeyAndValue = GetBiggest(leftNode, true); node.SetKeyAndValueAt(prevKeyAndValue, realPosition); BTreeValidator.ValidateNode(node, node == _root); GetPersister().SaveNode(node); return(currentValue); } // case 2b var rightNode = node.GetChildAt(realPosition + 1, true); if (rightNode.GetNbKeys() >= _degree) { var nextKeyAndValue = GetSmallest(rightNode, true); node.SetKeyAndValueAt(nextKeyAndValue, realPosition); BTreeValidator.ValidateNode(node, node == _root); GetPersister().SaveNode(node); return(currentValue); } // case 2c // Here, both left and right part have degree-1 keys // remove the element to be deleted from node (shifting left all // right // elements, link to right link does not exist anymore) // insert the key to be deleted in left child and merge the 2 nodes. // rightNode should be deleted // if node is root, then leftNode becomes the new root and node // should be deleted // node.DeleteKeyAndValueAt(realPosition, true); leftNode.InsertKeyAndValue(currentKey, currentValue); leftNode.MergeWith(rightNode); // If node is the root and is empty if (!node.HasParent() && node.GetNbKeys() == 0) { _persister.DeleteNode(node); _root = leftNode; leftNode.SetParent(null); // The height has been decreased. No need to save btree here. // The calling delete method will save it. _height--; } else { node.SetChildAt(leftNode, realPosition); // Node must only be validated if it is not the root BTreeValidator.ValidateNode(node, node == _root); } _persister.DeleteNode(rightNode); BTreeValidator.ValidateNode(leftNode, leftNode == _root); GetPersister().SaveNode(node); GetPersister().SaveNode(leftNode); return(InternalDelete(leftNode, keyAndValue)); }
private void CheckIfCanMergeWith(IBTreeNode node) { if (NbKeys + node.GetNbKeys() > _maxNbKeys) { var errorMessage = string.Concat("Trying to merge two nodes with too many keys ", NbKeys.ToString(), " + ", node.GetNbKeys().ToString(), " > ", _maxNbKeys.ToString()); throw new BTreeException(errorMessage); } if (NbKeys > 0) { var greatestOfThis = Keys[NbKeys - 1]; var smallestOfOther = node.GetKeyAt(0); if (greatestOfThis.CompareTo(smallestOfOther) >= 0) { var errorMessage = string.Format("Trying to merge two nodes that have intersections : {0} / {1}", ToString(), node); throw new BTreeNodeValidationException(errorMessage); } } if (NbKeys < NbChildren) throw new BTreeNodeValidationException("Trying to merge two nodes where the first one has more children than keys"); }
/// <summary> /// Can only merge node without intersection => the greater key of this must be smaller than the smallest key of the node /// </summary> public virtual void MergeWith(IBTreeNode node) { BTreeValidator.ValidateNode(this); BTreeValidator.ValidateNode(node); CheckIfCanMergeWith(node); var j = NbKeys; for (var i = 0; i < node.GetNbKeys(); i++) { SetKeyAndValueAt(node.GetKeyAt(i), node.GetValueAsObjectAt(i), j, false, false); SetChildAt(node, i, j, false); j++; } // in this, we have to take the last child if (node.GetNbChildren() > node.GetNbKeys()) SetChildAt(node, node.GetNbChildren() - 1, j, true); NbKeys += node.GetNbKeys(); NbChildren += node.GetNbChildren(); BTreeValidator.ValidateNode(this); }