Beispiel #1
0
        private List <Node234> Split(Node234 node)
        {
            Debug.Assert(node.GetDegree() == 4 || node.GetDegree() == 0); // Node should have either 4 or 0 children(leaf)

            var newChildren = new List <Node234>();

            Node234 leftSubTree = new Node234(node.Values[0]);

            newChildren.Add(leftSubTree);

            Node234 rightSubTree = new Node234(node.Values[2]);

            newChildren.Add(rightSubTree);

            if (node.GetDegree() != 0)   // must be 4-node
            {
                leftSubTree.AddChild(node.Children[0]);
                leftSubTree.AddChild(node.Children[1]);
                rightSubTree.AddChild(node.Children[2]);
                rightSubTree.AddChild(node.Children[3]);
            }

            ////Debug.WriteLine(string.Format("Split newChildren: {0} & {1}", newChildren[0], newChildren[1]));

            return(newChildren);
        }
Beispiel #2
0
        private void DeleteInternal(int target, Node234 node)
        {
            //Debug.WriteLine(string.Format("DeleteInternal {0}, {1}", target, node));

            if (node.Values.Contains(target))
            {
                //Debug.WriteLine(string.Format("Target {0} is in node {1}", target, node));
                if (node.IsLeaf())
                {
                    Debug.Assert(node.Values.Count != 1);
                    node.Values.Remove(target);
                    //Debug.WriteLine(string.Format("Deleted at leaf {0}, {1} ", target, node));
                    return;
                }
                else
                {
                    int     predecessorIndex = node.GetChildPredecessorIndex(target);
                    Node234 predecessorNode  = node.Children[predecessorIndex];
                    int     predecessorValue = predecessorNode.Values[predecessorNode.Values.Count - 1]; // ??????

                    int     successorIndex = node.GetChildSuccessorIndex(target);
                    Node234 successorNode  = node.Children[successorIndex];
                    int     successorValue = successorNode.Values[0]; //TODOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOo



                    if (predecessorNode.Values.Count > 1)   // can steal from predecessor?
                    //Debug.WriteLine(string.Format("stealing from predecessor: {0}", predecessorNode));
                    {
                        node.Values[node.Values.IndexOf(target)] = predecessorValue;
                        DeleteInternal(predecessorValue, predecessorNode);
                    }
                    else if (successorNode.Values.Count > 1)     // steal from successor?
                    //Debug.WriteLine(string.Format("stealing from successor: {0}", successorNode));
                    {
                        node.Values[node.Values.IndexOf(target)] = successorValue;
                        DeleteInternal(successorValue, successorNode);
                    }
                    else     // cannot steal, demote/merge                  // TODO MAY BE WRONG, SEE DIGIPEN CASE 2.3
                    //Debug.WriteLine(string.Format("cannot steal, demote/merge {0} ", node));

                    // Build mergedNode, add values
                    {
                        Node234 mergedNode = new Node234(target);
                        mergedNode.AddValue(predecessorValue);
                        mergedNode.AddValue(successorValue);

                        // wire children
                        mergedNode.AddChildren(predecessorNode.Children);
                        mergedNode.AddChildren(successorNode.Children);

                        // clean up
                        node.Values.Remove(target);
                        node.Children.Remove(predecessorNode);
                        node.Children.Remove(successorNode);

                        node.AddChild(mergedNode);

                        DeleteInternal(target, mergedNode); // Recurse to delete target
                    }
                }
            }
            else     // still looking for node with value
            //Debug.WriteLine(string.Format("Node does not contain value"));

            {
                int     childIndexToFollow = node.GetChildIndexToFollow(target);
                Node234 childToFollow      = node.Children[childIndexToFollow];

                Node234 sibling;
                int     siblingValueIndex;

                if (childToFollow.Values.Count == 1)
                {
                    if (childIndexToFollow > 0 && node.Children[childIndexToFollow - 1].Values.Count >= 2)   // Left immediate sibling exists and has at least 2 keys
                    // Clockwise rotation
                    //Debug.WriteLine("Clockwise rotation");

                    {
                        int pivotValueIndex = childIndexToFollow - 1;
                        childToFollow.AddValue(node.Values[pivotValueIndex]); // Rot value to child

                        sibling           = node.Children[childIndexToFollow - 1];
                        siblingValueIndex = sibling.Values.Count - 1;                     // Index of left sibling's rightmost value

                        node.Values[pivotValueIndex] = sibling.Values[siblingValueIndex]; // Rot sibling value to node
                        sibling.Values.RemoveAt(siblingValueIndex);                       //
                        if (sibling.GetDegree() != 0)
                        {
                            childToFollow.AddChild(sibling.Children[siblingValueIndex + 1]);    // Adopt child
                            sibling.Children.RemoveAt(siblingValueIndex + 1);                   //
                        }
                    }
                    else if (childIndexToFollow < node.GetDegree() - 1 && node.Children[childIndexToFollow + 1].Values.Count >= 2)     // Right immediate sibling exists and has at least 2 keys
                    // Counter-clockwise rotation
                    //Debug.WriteLine("Counter-clockwise rotation");

                    {
                        int pivotValueIndex = childIndexToFollow;
                        childToFollow.AddValue(node.Values[pivotValueIndex]); // Rot value to child

                        sibling           = node.Children[childIndexToFollow + 1];
                        siblingValueIndex = 0;                                            // Index of right sibling's leftmost value

                        node.Values[pivotValueIndex] = sibling.Values[siblingValueIndex]; // Rot sibling value to node
                        sibling.Values.RemoveAt(siblingValueIndex);                       //
                        if (sibling.GetDegree() != 0)
                        {
                            childToFollow.AddChild(sibling.Children[siblingValueIndex]);    // Adopt child
                            sibling.Children.RemoveAt(siblingValueIndex);                   //
                        }
                    }
                    else     // merge case
                    //Debug.WriteLine("Merge case");

                    {
                        if (node == Root && node.GetDegree() == 2)
                        {
                            PromoteChildren(node);
                            //Debug.WriteLine("     promote children");
                        }
                        else
                        {
                            if (childIndexToFollow > 0 && node.Children[childIndexToFollow - 1].Values.Count == 1)
                            {
                                //Debug.WriteLine("     demote value and merge with left sibling");
                                DemoteValue(node, childIndexToFollow - 1, childIndexToFollow, childIndexToFollow - 1);  // demote value and merge with left sibling
                            }
                            else if (childIndexToFollow < node.Children.Count - 1 && node.Children[childIndexToFollow + 1].Values.Count == 1)
                            {
                                //Debug.WriteLine("     demote value and merge with right sibling");
                                DemoteValue(node, childIndexToFollow, childIndexToFollow, childIndexToFollow + 1);  // demote value and merge with right sibling
                            }
                            else
                            {
                                throw new Exception("Oh shit");
                            }
                        }
                    }
                }

                childIndexToFollow = node.GetChildIndexToFollow(target);
                DeleteInternal(target, node.Children[childIndexToFollow]);
            }
            //Debug.WriteLine(String.Format("Deleted {0}. => {1}", target, this));
        }