Exemple #1
0
 // Grows child 'i' to make sure it's possible to remove an
 // item from it while keeping it at minItems, then calls remove to actually
 // remove it
 //
 // Most documentation says we have to do two sets of special casing:
 //    1) item is in this node
 //    2) item is in child
 // In both cases, we need to handle the two subcases:
 //    A) node has enough values that it can spare one
 //    B) node doesn't have enough values
 // For the latter, we have to check:
 //    a) left sibling has node to spare
 //    b) right sibling has node to spare
 //    c) we must merge
 // To simplify our code here, we handle cases #1 and #2 the same:
 // If a node doesn't have enough items, we make sure it does (using a,b,c).
 // We then simply redo our remove call, and the second time (regardless of
 // whether we're in case 1 or 2), we'll have enough items and can guarantee
 // that we hit case A.
 public T GrowChildAndRemove(int i, T item, int minItems, ToRemove typ)
 {
     if (i > 0 && Children[i - 1].Items.Length > minItems)
     {
         // Steal from left child
         Node <T> child      = MutableChild(i);
         Node <T> stealFrom  = MutableChild(i - 1);
         T        stolenItem = stealFrom.Items.Pop();
         child.Items.InsertAt(0, Items[i - 1]);
         Items[i - 1] = stolenItem;
         if (stealFrom.Children.Length > 0)
         {
             child.Children.InsertAt(0, stealFrom.Children.Pop());
         }
     }
     else if (i < Items.Length && Children[i + 1].Items.Length > minItems)
     {
         // steal from right child
         Node <T> child      = MutableChild(i);
         Node <T> stealFrom  = MutableChild(i + 1);
         T        stolenItem = stealFrom.Items.RemoveAt(0);
         child.Items.Append(Items[i]);
         Items[i] = stolenItem;
         if (stealFrom.Children.Length > 0)
         {
             child.Children.Append(stealFrom.Children.RemoveAt(0));
         }
     }
     else
     {
         if (i >= Items.Length)
         {
             i--;
         }
         Node <T> child = MutableChild(i);
         // merge with right child
         T        mergeItem  = Items.RemoveAt(i);
         Node <T> mergeChild = Children.RemoveAt(i + 1);
         child.Items.Append(mergeItem);
         child.Items.Append(mergeChild.Items);
         child.Children.Append(mergeChild.Children);
         _ = Cow.FreeNode(mergeChild);
     }
     return(Remove(item, minItems, typ));
 }