Exemplo n.º 1
0
        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");
            }
        }
Exemplo n.º 2
0
        /// <summary>
        ///   Can only merge node without intersection =&gt; 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);
        }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
0
        /// <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));
        }
Exemplo n.º 5
0
        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");
        }
Exemplo n.º 6
0
        /// <summary>
        ///   Can only merge node without intersection =&gt; 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);
        }