Exemplo n.º 1
0
        /// <summary>
        /// Splits this node to left and right nodes.
        /// </summary>
        public void Split(out TreeNode <K, V> leftNode, out TreeNode <K, V> rightNode)
        {
            Debug.Assert(IsOverflow, "This node is not yet overflowing.");

            bool isLeaf      = IsLeaf;
            var  halfCount   = nodeManager.MinEntriesPerNode;
            var  middleEntry = entries[halfCount];

            // Get larger entries and children for new node.
            var largeEntries = new Tuple <K, V> [halfCount];

            uint[] largeChildren = null;
            // Copy larger entries to newer node.
            entries.CopyTo(halfCount + 1, largeEntries, 0, halfCount);
            // Copy child node ids if not a leaf.
            if (!isLeaf)
            {
                largeChildren = new uint[halfCount + 1];
                childrenIds.CopyTo(halfCount + 1, largeChildren, 0, halfCount);
            }

            // Create larger node
            var largeNode = nodeManager.Create(largeEntries, largeChildren);

            // All child nodes moved to newer node must refresh their parentId.
            if (!isLeaf)
            {
                for (int i = 0; i < largeChildren.Length; i++)
                {
                    nodeManager.Find(largeChildren[i]).ParentId = largeNode.id;
                }
            }

            // Remove all large entries and children ids from this node.
            // Entries list must also remove the middle entry because it will go to the parent node.
            entries.RemoveRange(halfCount);
            if (!isLeaf)
            {
                childrenIds.RemoveRange(halfCount + 1);
            }

            // Try getting parent node
            var parentNode = parentId == 0 ? null : nodeManager.Find(parentId);

            // If no parent, create a new parent node with the middle entry
            if (parentNode == null)
            {
                parentNode = nodeManager.CreateNewRoot(
                    middleEntry.Item1,
                    middleEntry.Item2,
                    id,
                    largeNode.id
                    );

                // Reassign parent id
                this.ParentId      = parentNode.id;
                largeNode.ParentId = parentNode.id;
            }
            // Move the middle element to the parent node.
            else
            {
                int insertIndex = 0;
                parentNode.InsertAsParent(
                    middleEntry.Item1,
                    middleEntry.Item2,
                    id,
                    largeNode.id,
                    out insertIndex
                    );

                // Reassign parent id for large node only because this node's already been set.
                largeNode.ParentId = parentNode.id;

                // Split parent node if overflowing.
                if (parentNode.IsOverflow)
                {
                    Split();
                }
            }

            // Output nodes
            leftNode  = this;
            rightNode = largeNode;

            // Mark this node dirty
            nodeManager.MarkAsChanged(this);
        }