Heapsort works as follows. A heap is constructed by calling the Build-Heap function.
The smallest value is extracted repeatedly until the heap is empty. The values having
been extracted are placed in sorted order. After each extraction, the heap property is
preserved at a cost of O(log n) by calling the heapify function. Thus, heapsort runs in
O(n log n) time because it creates a heap in O(n) time and then extracts n elements,
spending for each one O(log n) time concluding to O(n log n) + O(n) = O(n log n)
running time. During extraction, the only space required is that for storing the heap.
In order to achieve constant space overhead, the heap is stored in the part of the input
array that has not been sorted yet