/// <summary> /// 分割当前节点 /// </summary> /// <param name="splitFirstKey">新分割节点的第一个键,也就是最小的键</param> /// <param name="splitNode">新分割节点</param> private void SplitLeaf(ref string splitFirstKey, ref BPlusTreeNode splitNode) { // 从中间开始分割 int splitPoint = this._childKeys.Length / 2; int splitLength = this._childKeys.Length - splitPoint; // 新创建的分割出的节点 splitNode = new BPlusTreeNode(this.Tree, this.Parent, -1, this.IsLeaf); // 将指定分割点右侧的数据拷贝至新的节点,新节点为当前节点的右兄弟节点 Array.Copy(this._childKeys, splitPoint, splitNode._childKeys, 0, splitLength); Array.Copy(this._childValues, splitPoint, splitNode._childValues, 0, splitLength); Array.Copy(this._childNodes, splitPoint, splitNode._childNodes, 0, splitLength); // 记录分割节点的第一个键 splitFirstKey = splitNode._childKeys[0]; // 存储新节点至块文件 splitNode.DumpToNewBlock(); // 分割完毕,当前节点恢复之前的扩容,处理分割点左侧数据 RepairAfterSplit(splitPoint); // 我可以被释放掉 this.Tree.RecordTerminalNode(splitNode); // 新节点及其父节点需要标记为脏节点 splitNode.Soil(); }
/// <summary> /// 分割当前节点 /// </summary> /// <param name="splitFirstKey">新分割节点的第一个键,也就是最小的键</param> /// <param name="splitNode">新分割节点</param> private void SplitInternal(ref string splitFirstKey, ref BPlusTreeNode splitNode) { // 从中间开始分割 int splitPoint = this._childNodes.Length / 2 - 1; // 分割出的新节点的第一个键 splitFirstKey = this._childKeys[splitPoint]; // 新建节点,包含分割点右侧所有数据 splitNode = new BPlusTreeNode(this.Tree, this.Parent, -1, this.IsLeaf); splitNode.Clear(); // redundant. // 记录已经扩充的数据结构 long[] values = this._childValues; string[] keys = this._childKeys; BPlusTreeNode[] nodes = this._childNodes; // 重置和清空数据 this.Clear(); // 将分割点左侧的数据拷贝至此节点 Array.Copy(keys, 0, this._childKeys, 0, splitPoint); Array.Copy(values, 0, this._childValues, 0, splitPoint + 1); Array.Copy(nodes, 0, this._childNodes, 0, splitPoint + 1); // 将分割点右侧的数据拷贝至新的分割节点 int remainingKeys = this.Capacity - splitPoint; Array.Copy(keys, splitPoint + 1, splitNode._childKeys, 0, remainingKeys); Array.Copy(values, splitPoint + 1, splitNode._childValues, 0, remainingKeys + 1); Array.Copy(nodes, splitPoint + 1, splitNode._childNodes, 0, remainingKeys + 1); // 重置新节点中所有的子节点的父节点 splitNode.ResetAllChildrenParent(); // 存储新节点 splitNode.DumpToNewBlock(); splitNode.CheckIfTerminal(); splitNode.Soil(); this.CheckIfTerminal(); }