Ejemplo n.º 1
0
        /// <summary>
        /// 删除指定的键和关联的数据项。如果键未找到则抛出异常。
        /// </summary>
        /// <param name="key">被删除的键</param>
        public void RemoveKey(string key)
        {
            if (this.RootNode == null)
            {
                throw new BPlusTreeKeyNotFoundException("Tree is empty, cannot remove.");
            }

            bool          mergeMe;
            BPlusTreeNode root = this.RootNode;

            // 从根节点开始遍历删除
            root.Delete(key, out mergeMe);

            // 如果根节点不是一个叶节点,并且仅还有一个子节点,则重新设置根节点
            if (mergeMe && !this.RootNode.IsLeaf && this.RootNode.Count == 0)
            {
                this.RootNode            = this.RootNode.FirstChild();
                this.RootNodeBlockNumber = this.RootNode.MakeAsRoot();
                root.Free();
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 删除指定键的记录
        /// </summary>
        /// <param name="key">指定键</param>
        /// <param name="mergeMe">如果为真则意味着删除键后节点已经小于1/2满,需要合并</param>
        /// <returns>返回节点中最小的键,如无变化则返回空</returns>
        public string Delete(string key, out bool mergeMe)
        {
            // 如果是叶节点,则调用删除叶节点逻辑
            if (this.IsLeaf)
            {
                return(DeleteLeaf(key, out mergeMe));
            }

            // 假设我是不需要被合并的
            mergeMe = false;

            // 我是内部节点,找到指定键的位置
            int deletePosition = this.FindAtOrNextPosition(key, false);

            // 加载要被删除位置的子节点
            BPlusTreeNode deleteChildNode = LoadNodeAtPosition(deletePosition);

            // 从子节点中删除键
            bool   isChildNodeNeedMerge;
            string deletedChildKey = deleteChildNode.Delete(key, out isChildNodeNeedMerge);

            // 删除完毕,当前节点为脏节点
            this.Soil();

            // 发现子节点的最小键与被删除的键相同,则认为子节点已经没用了
            string result = null;

            if (deletedChildKey != null && this.Tree.CompareKey(deletedChildKey, key) == 0)
            {
                if (this.Capacity > 3)
                {
                    throw new BPlusTreeException(
                              string.Format("Deletion returned delete key for too large node size: {0}.",
                                            this.Capacity));
                }

                // 判断删除的是头或尾
                if (deletePosition == 0)
                {
                    result = this._childKeys[deletePosition];
                }
                else if (deletePosition == this.Capacity)
                {
                    this._childKeys[deletePosition - 1] = null;
                }
                else
                {
                    this._childKeys[deletePosition - 1] = this._childKeys[deletePosition];
                }

                if (result != null && this.Tree.CompareKey(result, key) == 0)
                {
                    this.LoadNodeAtPosition(1);
                    result = this._childNodes[1].LeastKey();
                }

                // 这个子节点彻底没用了,释放其空间
                deleteChildNode.Free();

                // 节点中键位置右侧全部左移 1 位
                OverwriteDeletePosition(deletePosition);

                // 如果节点的使用率小于一半,则需要合并节点
                if (this.Count < this.Capacity / 2)
                {
                    mergeMe = true;
                }

                // 重置子节点的父节点
                this.ResetAllChildrenParent();

                return(result);
            }

            if (deletePosition == 0)
            {
                result = deletedChildKey;
            }
            else if (deletedChildKey != null && deletePosition > 0)
            {
                if (this.Tree.CompareKey(deletedChildKey, key) != 0)
                {
                    this._childKeys[deletePosition - 1] = deletedChildKey;
                }
            }

            // 如果子节点需要合并
            if (isChildNodeNeedMerge)
            {
                int           leftIndex, rightIndex;
                BPlusTreeNode leftNode, rightNode;
                string        keyBetween;

                if (deletePosition == 0)
                {
                    // 和右侧兄弟节点合并
                    leftIndex  = deletePosition;
                    rightIndex = deletePosition + 1;
                    leftNode   = deleteChildNode;
                    rightNode  = this.LoadNodeAtPosition(rightIndex);
                }
                else
                {
                    // 和左侧兄弟节点合并
                    leftIndex  = deletePosition - 1;
                    rightIndex = deletePosition;
                    leftNode   = this.LoadNodeAtPosition(leftIndex);
                    rightNode  = deleteChildNode;
                }

                keyBetween = this._childKeys[leftIndex];

                // 合并节点
                string rightLeastKey;
                bool   isDeleteRight;
                MergeInternal(leftNode, keyBetween, rightNode, out rightLeastKey, out isDeleteRight);

                // 是否需要删除右节点
                if (isDeleteRight)
                {
                    for (int i = rightIndex; i < this.Capacity; i++)
                    {
                        this._childKeys[i - 1] = this._childKeys[i];
                        this._childValues[i]   = this._childValues[i + 1];
                        this._childNodes[i]    = this._childNodes[i + 1];
                    }
                    this._childKeys[this.Capacity - 1] = null;
                    this._childValues[this.Capacity]   = StorageConstants.NullBlockNumber;
                    this._childNodes[this.Capacity]    = null;

                    this.ResetAllChildrenParent();

                    rightNode.Free();

                    // 当前节点还需要再合并吗
                    if (this.Count < this.Capacity / 2)
                    {
                        mergeMe = true;
                    }
                }
                else
                {
                    this._childKeys[rightIndex - 1] = rightLeastKey;
                }
            }

            return(result);
        }
Ejemplo n.º 3
0
        public string Delete(string key, out bool mergeMe)
        {
            if (this.IsLeaf)
            {
                return(DeleteLeaf(key, out mergeMe));
            }

            mergeMe = false;

            int deletePosition = this.FindAtOrNextPosition(key, false);

            BPlusTreeNode deleteChildNode = LoadNodeAtPosition(deletePosition);

            bool   isChildNodeNeedMerge;
            string deletedChildKey = deleteChildNode.Delete(key, out isChildNodeNeedMerge);

            this.Soil();

            string result = null;

            if (deletedChildKey != null && this.Tree.CompareKey(deletedChildKey, key) == 0)
            {
                if (this.Capacity > 3)
                {
                    throw new BPlusTreeException(
                              string.Format("Deletion returned delete key for too large node size: {0}.",
                                            this.Capacity));
                }

                if (deletePosition == 0)
                {
                    result = this._childKeys[deletePosition];
                }
                else if (deletePosition == this.Capacity)
                {
                    this._childKeys[deletePosition - 1] = null;
                }
                else
                {
                    this._childKeys[deletePosition - 1] = this._childKeys[deletePosition];
                }

                if (result != null && this.Tree.CompareKey(result, key) == 0)
                {
                    this.LoadNodeAtPosition(1);
                    result = this._childNodes[1].LeastKey();
                }

                deleteChildNode.Free();

                OverwriteDeletePosition(deletePosition);

                if (this.Count < this.Capacity / 2)
                {
                    mergeMe = true;
                }

                this.ResetAllChildrenParent();

                return(result);
            }

            if (deletePosition == 0)
            {
                result = deletedChildKey;
            }
            else if (deletedChildKey != null && deletePosition > 0)
            {
                if (this.Tree.CompareKey(deletedChildKey, key) != 0)
                {
                    this._childKeys[deletePosition - 1] = deletedChildKey;
                }
            }

            if (isChildNodeNeedMerge)
            {
                int           leftIndex, rightIndex;
                BPlusTreeNode leftNode, rightNode;
                string        keyBetween;

                if (deletePosition == 0)
                {
                    leftIndex  = deletePosition;
                    rightIndex = deletePosition + 1;
                    leftNode   = deleteChildNode;
                    rightNode  = this.LoadNodeAtPosition(rightIndex);
                }
                else
                {
                    leftIndex  = deletePosition - 1;
                    rightIndex = deletePosition;
                    leftNode   = this.LoadNodeAtPosition(leftIndex);
                    rightNode  = deleteChildNode;
                }

                keyBetween = this._childKeys[leftIndex];

                string rightLeastKey;
                bool   isDeleteRight;
                MergeInternal(leftNode, keyBetween, rightNode, out rightLeastKey, out isDeleteRight);

                if (isDeleteRight)
                {
                    for (int i = rightIndex; i < this.Capacity; i++)
                    {
                        this._childKeys[i - 1] = this._childKeys[i];
                        this._childValues[i]   = this._childValues[i + 1];
                        this._childNodes[i]    = this._childNodes[i + 1];
                    }
                    this._childKeys[this.Capacity - 1] = null;
                    this._childValues[this.Capacity]   = StorageConstants.NullBlockNumber;
                    this._childNodes[this.Capacity]    = null;

                    this.ResetAllChildrenParent();

                    rightNode.Free();

                    if (this.Count < this.Capacity / 2)
                    {
                        mergeMe = true;
                    }
                }
                else
                {
                    this._childKeys[rightIndex - 1] = rightLeastKey;
                }
            }

            return(result);
        }