/// <summary>
 /// Return a new dict with the root key-value pair removed
 /// </summary>
 AvlNode <T> RemoveRoot()
 {
     if (IsEmpty)
     {
         return(this);
     }
     if (_left.IsEmpty)
     {
         return(_right);
     }
     if (_right.IsEmpty)
     {
         return(_left);
     }
     //Neither are empty:
     if (_left._count < _right._count)
     {
         //LTDict has fewer, so promote from GTDict to minimize depth
         AvlNode <T> min;
         var         newGt   = _right.RemoveMin(out min);
         var         newRoot = NewOrMutate(min.Value, _left, newGt);
         return(newRoot.FixRootBalance());
     }
     else
     {
         AvlNode <T> max;
         var         newLt   = _left.RemoveMax(out max);
         var         newRoot = NewOrMutate(max.Value, newLt, _right);
         return(newRoot.FixRootBalance());
     }
 }
 AvlNode <T> RemoveMax(out AvlNode <T> max)
 {
     if (IsEmpty)
     {
         max = Empty;
         return(Empty);
     }
     if (_right.IsEmpty)
     {
         //We are the max:
         max = this;
         return(_left);
     }
     else
     {
         //Go down:
         var newGt   = _right.RemoveMax(out max);
         var newRoot = NewOrMutate(Value, _left, newGt);
         return(newRoot.FixRootBalance());
     }
 }