private static AvlNode <T> RemoveLeftmostChild(ref AvlNode <T> node)
        {
            if (node.Left == null)
            {
                var toReturn = node;
                node = node.Right;
                return(toReturn);
            }

            var child  = node.Left;
            var result = RemoveLeftmostChild(ref child);

            node.Left = child;
            BalanceIfRightIsHeavy(ref node);
            return(result);
        }
        public static bool Contains(AvlNode <T> node, T value)
        {
            if (node == null)
            {
                return(false);
            }

            var cmp = value.CompareTo(node.Value);

            if (cmp < 0)
            {
                return(Contains(node.Left, value));
            }
            if (cmp > 0)
            {
                return(Contains(node.Right, value));
            }
            return(true);
        }
        public static T AtIndex(AvlNode <T> node, int index)
        {
            if (node == null)
            {
                throw new IndexOutOfRangeException("Noooo");
            }

            var rootIndex = GetSize(node.Left);

            if (index < rootIndex)
            {
                return(AtIndex(node.Left, index));
            }
            if (index > rootIndex)
            {
                return(AtIndex(node.Right, index - rootIndex - 1));
            }
            return(node.Value);
        }
        public static int IndexOf(AvlNode <T> node, T value)
        {
            if (node == null)
            {
                return(-1);
            }

            var cmp = value.CompareTo(node.Value);

            if (cmp < 0)
            {
                return(IndexOf(node.Left, value));
            }
            if (cmp > 0)
            {
                return(IndexOf(node.Right, value) + GetSize(node.Left) + 1);
            }
            return(GetSize(node.Left));
        }
 public static void RotateLeft(ref AvlNode <T> node)
 {
     Rotate(ref node, 1, 0);
 }
 public static void RotateRight(ref AvlNode <T> node)
 {
     Rotate(ref node, 0, 1);
 }
 public static int GetHeight(AvlNode <T> node)
 {
     return(node == null ? 0 : node.height);
 }
 public static int GetSize(AvlNode <T> node)
 {
     return(node == null ? 0 : node.size);
 }
 public bool Remove(T value)
 {
     return(AvlNode <T> .Remove(ref this.root, value));
 }
 public bool Add(T value)
 {
     return(AvlNode <T> .Add(ref this.root, value));
 }
 public T AtIndex(int index)
 {
     return(AvlNode <T> .AtIndex(this.root, index));
 }
 public int IndexOf(T value)
 {
     return(AvlNode <T> .IndexOf(this.root, value));
 }
 public bool Contains(T value)
 {
     return(AvlNode <T> .Contains(this.root, value));
 }
 public AvlTree()
 {
     root = null;
 }