/// <summary>
        /// lets the value at arr[i] swim up so that themaxheap  obeys the max-heap property.
        /// </summary>
        /// <param name="i"></param>
        public void Swimup(int i)
        {
            while (i > 0 && arr[Parent(i)].CompareTo(arr[i]) < 0)
            {
                SortCommons <T> .Exchange(arr, i, Parent(i));

                i = Parent(i);
            }
        }
        /// <summary>
        /// return and remove the max one
        /// </summary>
        /// <returns></returns>
        public T Pop()
        {
            if (IsEmpty())
            {
                throw new Exception("heap is empty");
            }

            T tmp = arr[0];

            SortCommons <T> .Exchange(arr, 0, heapSize - 1);

            heapSize--;
            Sink(0);

            if (heapSize != 0 && arr.Length / heapSize > 2 && arr.Length / 2 >= 4)
            {
                Array.Resize(ref arr, arr.Length / 2);
            }

            return(tmp);
        }
        /// <summary>
        /// lets the value at arr[i] “float down” in the max-heap so that the subtree rooted at index i obeys the max-heap property.
        /// it runs at O(lgn)
        /// </summary>
        /// <param name="i"></param>
        public void Sink(int i)
        {
            int left  = Left(i);
            int right = Right(i);
            int max   = i;

            if (left < heapSize && arr[left].CompareTo(arr[max]) > 0)
            {
                max = left;
            }

            if (right < heapSize && arr[right].CompareTo(arr[max]) > 0)
            {
                max = right;
            }

            if (max != i)
            {
                SortCommons <T> .Exchange(arr, max, i);

                Sink(max);
            }
        }