예제 #1
0
        /// <summary>
        /// Tries moving to next entry by ascending order.
        /// </summary>
        bool Ascend()
        {
            curIndex++;

            if (curNode.IsLeaf)
            {
                while (true)
                {
                    // If a valid entry in node was found, return it.
                    if (curIndex < curNode.EntryCount)
                    {
                        curEntry = curNode.GetEntry(curIndex);
                        return(true);
                    }
                    // Else if no valid entry in node and there is a parent node
                    else if (curNode.ParentId != 0)
                    {
                        // Adjust index to point to current node in parent.
                        curIndex = curNode.IndexInParent();
                        // Set target node one level up.
                        curNode = nodeManager.Find(curNode.ParentId);

                        // Validate parent
                        if (curIndex < 0 || curNode == null)
                        {
                            throw new Exception("An error in BTree was detected.");
                        }
                    }
                    // No more parent nodes and valid entries. We should just finish off here
                    else
                    {
                        curEntry   = null;
                        isFinished = true;
                        return(false);
                    }
                }
            }
            else
            {
                do
                {
                    // Get the next child node on first iteration,
                    // or the first child node on further iterations.
                    curNode = curNode.GetChildNode(curIndex);
                    // Reset index to 0 to indicate first child and entry in the newly found node.
                    curIndex = 0;

                    // Validate new node
                    if (curNode == null)
                    {
                        throw new Exception("An error in BTree was detected.");
                    }
                }while(!curNode.IsLeaf);

                curEntry = curNode.GetEntry(curIndex);
                return(true);
            }
        }
예제 #2
0
        bool MoveForward()
        {
            // Leaf node, either move right or up
            if (currentNode.IsLeaf)
            {
                // First, move right
                currentEntry++;

                while (true)
                {
                    // If currentEntry is valid
                    // then we are done here.
                    if (currentEntry < currentNode.EntriesCount)
                    {
                        current = currentNode.GetEntry(currentEntry);
                        return(true);
                    }
                    // If can't move right then move up
                    else if (currentNode.ParentId != 0)
                    {
                        currentEntry = currentNode.IndexInParent();
                        currentNode  = nodeManager.Find(currentNode.ParentId);

                        // Validate move up result
                        if ((currentEntry < 0) || (currentNode == null))
                        {
                            throw new Exception("Something gone wrong with the BTree");
                        }
                    }
                    // If can't move up when we are done iterating
                    else
                    {
                        current       = null;
                        doneIterating = true;
                        return(false);
                    }
                }
            }
            // Parent node, always move right down
            else
            {
                currentEntry++;                 // Increase currentEntry, this make firstCall to nodeManager.Find
                                                // to return the right node, but does not affect subsequence calls

                do
                {
                    currentNode  = currentNode.GetChildNode(currentEntry);
                    currentEntry = 0;
                } while (false == currentNode.IsLeaf);

                current = currentNode.GetEntry(currentEntry);
                return(true);
            }
        }
예제 #3
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);
        }
예제 #4
0
        //
        // Public Methods
        //

        /// <summary>
        /// Remove an entry from this instance.
        /// </summary>
        public void Remove(int removeAt)
        {
            // Validate argument
            if (false == (removeAt >= 0) && (removeAt < this.entries.Count))
            {
                throw new ArgumentOutOfRangeException();
            }

            // http://webdocs.cs.ualberta.ca/~holte/T26/del-b-tree.html
            // https://en.wikipedia.org/wiki/B-tree#Deletion
            // If this is a node leave, flagged entry will be removed
            if (IsLeaf)
            {
                // Step 1: Remove X from the current node.
                // Being a leaf node there are no subtrees to worry about.
                entries.RemoveAt(removeAt);
                nodeManager.MarkAsChanged(this);

                // If the removal does not cause underflow then we are done here
                if ((EntriesCount >= nodeManager.MinEntriesPerNode) || (parentId == 0))
                {
                    return;
                }
                // Otherwise, rebalance this node
                else
                {
                    Rebalance();
                }
            }
            // If the value to be deleted does not occur in a leaf,
            // we replace it with the largest value in its left subtree
            // and then proceed to delete that value from the node that
            // originally contained it
            else
            {
                // Grab the largest entry on the left subtree
                var             leftSubTree = nodeManager.Find(this.childrenIds[removeAt]);
                TreeNode <K, V> largestNode; int largestIndex;
                leftSubTree.FindLargest(out largestNode, out largestIndex);
                var replacementEntry = largestNode.GetEntry(largestIndex);

                // REplace it
                this.entries[removeAt] = replacementEntry;
                nodeManager.MarkAsChanged(this);

                // Remove it from the node we took it from
                largestNode.Remove(largestIndex);
            }
        }