/// <summary> /// Propagates resizing of the nodes upwards. Additionally, performs /// any splitting of nodes along the way if a node needed to split. /// Returns whether the root node was split. /// </summary> /// <param name="adjustPath">Path along which the nodes need be adjusted</param> /// <param name="node">Node above which needs to be adjusted</param> /// <param name="splitNode">Node that needs to be inserted.</param> /// <returns>True if the root node was split</returns> private bool adjustTree(List <NodeRecord <T> > adjustPath, NodeRecord <T> node, ref NodeRecord <T> splitNode) { // AT1. NodeRecord <T> N = node; NodeRecord <T> NN = splitNode; while (true) { // AT2. if (N == root) { return(NN != null); } // AT3. N.ResizeBBox(); // AT4. // Try to add the extra node to this parent node. // If the parent has no more room, split the parent, // and propagate the split node upwards to continue // looking for an insertion point. int level = adjustPath.IndexOf(N); NodeRecord <T> P = adjustPath[level - 1]; if (NN != null) { if (!P.TryInsert(NN)) { NodeRecord <T> PP = P.Split(NN); NN = PP; } else { NN = null; } } N = P; } }
/// <summary> /// Performs the insertion algorithm. /// </summary> /// <param name="item">Item to insert</param> public void Insert(LeafRecord <T> item) { List <NodeRecord <T> > leafPath = new List <NodeRecord <T> >(); // I1. // Track the nodes traversed to get to the point that we // want to add the node. This list of nodes will be used // to propagate changes up the tree. NodeRecord <T> insertNode = chooseLeaf(item, leafPath); NodeRecord <T> splitNode = null; // I2. // Attempts to insert the item in the given node. // If it fails, we split the node. Store the new // node in splitNode, so it can be propagated up // later. if (!insertNode.TryInsert(item)) { // Split. splitNode = insertNode.Split(item); } // I3. // Propagate resizing up the tree. Propagate split node // if necessary. if (adjustTree(leafPath, insertNode, ref splitNode)) { // I4. // Create a new root if the root was split. This new root is not a leaf. NodeRecord <T> newRoot = new NodeRecord <T>() { Node = new RTreeNode <T>(Leaf: false) }; newRoot.TryInsert(root); newRoot.TryInsert(splitNode); root = newRoot; } }