internal override (Node currentNode, Node?splitNode) Insert(bool isAppend, int index, T item) { if (_count < _data.Length) { LeafNode mutableNode = AsMutable(); if (index < _count) { mutableNode._data.Copy(index, ref mutableNode._data, index + 1, _count - index); } mutableNode._data[index] = item; mutableNode._count++; return(currentNode : mutableNode, splitNode : null); } if (isAppend) { // optimize the case of adding at the end of the overall list var(splitNode, _) = Empty.Insert(isAppend, 0, item); return(currentNode : this, splitNode); } else { return(AsMutable().InsertWithSplit(isAppend, index, item)); } }
internal override Node Insert(int branchingFactor, bool isAppend, int index, T item) { if (_count < _data.Length) { if (index < _count) { Array.Copy(_data, index, _data, index + 1, _count - index); } _data[index] = item; _count++; return(null); } if (isAppend) { // optimize the case of adding at the end of the overall list var result = (LeafNode)Empty.Insert(branchingFactor, isAppend, 0, item); _next = result; return(result); } else { // split the node LeafNode splitNode = new LeafNode(branchingFactor); int splitPoint = _count / 2; bool forceNext = false; if ((_count + 1) / 2 > splitPoint && index > splitPoint) { // When splitting a node with an odd branching factor, prior to insertion one split node will // have (b-1)/2 nodes and the other will have (b+1)/2 nodes. Since the minimum number of nodes // after insertion is (b+1)/2, the split point uniquely determines the insertion point. This // block handles the case where the insertion point is index (b+1)/2 by forcing it to the first // node of the next page instead of adding it (where it fits) at the end of the first page. splitPoint++; forceNext = true; } Array.Copy(_data, splitPoint, splitNode._data, 0, _count - splitPoint); Array.Clear(_data, splitPoint, _count - splitPoint); splitNode._count = _count - splitPoint; _count = splitPoint; // insert the new element into the correct half if (!forceNext && index <= splitPoint) { Insert(branchingFactor, false, index, item); } else { splitNode.Insert(branchingFactor, false, index - splitPoint, item); } splitNode._next = _next; _next = splitNode; return(splitNode); } }