Ejemplo n.º 1
0
    /// <summary>
    /// 合并叶子节点,当节点的使用率不足50%时,则需要合并
    /// </summary>
    /// <param name="left">左节点</param>
    /// <param name="right">右节点</param>
    /// <param name="canDeleteRightNode">是否可以删除右节点</param>
    public static void MergeLeaves(BPlusTreeNode left, BPlusTreeNode right, out bool canDeleteRightNode)
    {
      if (left == null)
        throw new ArgumentNullException("left");
      if (right == null)
        throw new ArgumentNullException("right");

      canDeleteRightNode = false;

      string[] allKeys = new string[left.Capacity * 2];
      long[] allValues = new long[left.Capacity * 2];

      int index = 0;
      for (int i = 0; i < left.Capacity; i++)
      {
        if (left.ChildKeys[i] == null)
        {
          break;
        }
        allKeys[index] = left.ChildKeys[i];
        allValues[index] = left.ChildValues[i];
        index++;
      }

      for (int i = 0; i < right.Capacity; i++)
      {
        if (right.ChildKeys[i] == null)
        {
          break;
        }
        allKeys[index] = right.ChildKeys[i];
        allValues[index] = right.ChildValues[i];
        index++;
      }

      // 如果左节点的容量足够,则可删除右节点
      if (index <= left.Capacity)
      {
        canDeleteRightNode = true;

        left.Clear();
        
        for (int i = 0; i < index; i++)
        {
          left.ChildKeys[i] = allKeys[i];
          left.ChildValues[i] = allValues[i];
        }

        left.Soil();
        right.Free();        

        return;
      }

      // 左节点的容量不够了
      left.Clear();
      right.Clear();
      left.Soil();
      right.Soil();

      int rightContent = index / 2;
      int leftContent = index - rightContent;
      int newIndex = 0;
      for (int i = 0; i < leftContent; i++)
      {
        left.ChildKeys[i] = allKeys[newIndex];
        left.ChildValues[i] = allValues[newIndex];
        newIndex++;
      }
      for (int i = 0; i < rightContent; i++)
      {
        right.ChildKeys[i] = allKeys[newIndex];
        right.ChildValues[i] = allValues[newIndex];
        newIndex++;
      }
    }
Ejemplo n.º 2
0
    /// <summary>
    /// 合并节点,当节点的使用率不足50%时,则需要合并
    /// </summary>
    /// <param name="left">左节点</param>
    /// <param name="keyBetween">左右节点的中间键</param>
    /// <param name="right">右节点</param>
    /// <param name="rightLeastKey">合并后的键的最小值</param>
    /// <param name="canDeleteRightNode">是否可以删除右节点</param>
    public static void Merge(BPlusTreeNode left, string keyBetween, BPlusTreeNode right, out string rightLeastKey, out bool canDeleteRightNode)
    {
      if (left == null)
        throw new ArgumentNullException("left");
      if (right == null)
        throw new ArgumentNullException("right");

      rightLeastKey = null; // only if DeleteRight

      // 合并叶子节点
      if (left.IsLeaf || right.IsLeaf)
      {
        if (!(left.IsLeaf && right.IsLeaf))
        {
          throw new BPlusTreeException("can't merge leaf with non-leaf");
        }

        // 合并子节点
        MergeLeaves(left, right, out canDeleteRightNode);

        rightLeastKey = right.ChildKeys[0];

        return;
      }

      // 合并非叶子节点
      canDeleteRightNode = false;

      if (left.ChildValues[0] == StoredConstants.NullBlockNumber || right.ChildValues[0] == StoredConstants.NullBlockNumber)
      {
        throw new BPlusTreeException("cannot merge empty non-leaf with non-leaf");
      }

      string[] allKeys = new string[left.Capacity * 2 + 1];
      long[] allValues = new long[left.Capacity * 2 + 2];
      BPlusTreeNode[] allNodes = new BPlusTreeNode[left.Capacity * 2 + 2];

      // 拷贝左节点的数据
      int index = 0;
      allValues[0] = left.ChildValues[0];
      allNodes[0] = left.ChildNodes[0];
      for (int i = 0; i < left.Capacity; i++)
      {
        if (left.ChildKeys[i] == null)
        {
          break;
        }

        allKeys[index] = left.ChildKeys[i];
        allValues[index + 1] = left.ChildValues[i + 1];
        allNodes[index + 1] = left.ChildNodes[i + 1];

        index++;
      }

      // 拷贝中间键
      allKeys[index] = keyBetween;
      index++;

      // 拷贝右节点的数据
      allValues[index] = right.ChildValues[0];
      allNodes[index] = right.ChildNodes[0];
      int rightCount = 0;
      for (int i = 0; i < right.Capacity; i++)
      {
        if (right.ChildKeys[i] == null)
        {
          break;
        }

        allKeys[index] = right.ChildKeys[i];
        allValues[index + 1] = right.ChildValues[i + 1];
        allNodes[index + 1] = right.ChildNodes[i + 1];
        index++;

        rightCount++;
      }

      // 如果数量小于左节点的能力,则右节点可以删除掉
      if (index <= left.Capacity)
      {
        // it will all fit in one node
        canDeleteRightNode = true;

        for (int i = 0; i < index; i++)
        {
          left.ChildKeys[i] = allKeys[i];
          left.ChildValues[i] = allValues[i];
          left.ChildNodes[i] = allNodes[i];
        }

        left.ChildValues[index] = allValues[index];
        left.ChildNodes[index] = allNodes[index];

        left.ResetAllChildrenParent();
        left.Soil();

        right.Free();

        return;
      }

      // otherwise split the content between the nodes
      left.Clear();
      right.Clear();
      left.Soil();
      right.Soil();

      int leftContent = index / 2;
      int rightContent = index - leftContent - 1;

      rightLeastKey = allKeys[leftContent];

      int outputIndex = 0;
      for (int i = 0; i < leftContent; i++)
      {
        left.ChildKeys[i] = allKeys[outputIndex];
        left.ChildValues[i] = allValues[outputIndex];
        left.ChildNodes[i] = allNodes[outputIndex];
        outputIndex++;
      }

      rightLeastKey = allKeys[outputIndex];

      left.ChildValues[outputIndex] = allValues[outputIndex];
      left.ChildNodes[outputIndex] = allNodes[outputIndex];
      outputIndex++;

      rightCount = 0;
      for (int i = 0; i < rightContent; i++)
      {
        right.ChildKeys[i] = allKeys[outputIndex];
        right.ChildValues[i] = allValues[outputIndex];
        right.ChildNodes[i] = allNodes[outputIndex];
        outputIndex++;

        rightCount++;
      }

      right.ChildValues[rightCount] = allValues[outputIndex];
      right.ChildNodes[rightCount] = allNodes[outputIndex];

      left.ResetAllChildrenParent();
      right.ResetAllChildrenParent();
    }