AvlNode <T> RemoveMin(out AvlNode <T> min)
        {
            if (IsEmpty)
            {
                min = Empty;
                return(Empty);
            }
            if (_left.IsEmpty)
            {
                //We are the minimum:
                min = this;
                return(_right);
            }
            //Go down:
            var newLt   = _left.RemoveMin(out min);
            var newRoot = NewOrMutate(Value, newLt, _right);

            return(newRoot.FixRootBalance());
        }
        public AvlNode <T> SetItem(int index, T val)
        {
            AvlNode <T> newLt = _left;
            AvlNode <T> newGt = _right;

            if (index < _left._count)
            {
                newLt = _left.SetItem(index, val);
            }
            else if (index > _left._count)
            {
                newGt = _right.SetItem(index - _left._count - 1, val);
            }
            else
            {
                return(NewOrMutate(val, newLt, newGt));
            }
            return(NewOrMutate(Value, newLt, newGt));
        }
 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());
     }
 }
        /// <summary>
        /// Return a new tree with the key-value pair inserted
        /// If the key is already present, it replaces the value
        /// This operation is O(Log N) where N is the number of keys
        /// </summary>
        public AvlNode <T> InsertIntoNew(int index, T val)
        {
            if (IsEmpty)
            {
                return(new AvlNode <T>(val));
            }

            AvlNode <T> newLt = _left;
            AvlNode <T> newGt = _right;

            if (index <= _left._count)
            {
                newLt = _left.InsertIntoNew(index, val);
            }
            else
            {
                newGt = _right.InsertIntoNew(index - _left._count - 1, val);
            }

            var newRoot = NewOrMutate(Value, newLt, newGt);

            return(newRoot.FixRootBalance());
        }
 public virtual AvlNode <T> NewOrMutate(T newValue, AvlNode <T> newLeft, AvlNode <T> newRight)
 {
     return(new AvlNode <T>(newValue, newLeft, newRight));
 }
 public AvlNode()
 {
     _right = Empty;
     _left  = Empty;
 }