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); }
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)); }