It can be performed in place with constant auxiliary storage; the "fixheap" routine given below is recursive, but it's tail-recursive, and therefore can be straightforwardly converted to be iterative. No other O(N lg N) sort can be performed with constant auxiliary storage.
Here's a Python implementation:
def reverserange(n): list = range(n) list.reverse() return list def fixheap(array, heaplen, index, greaterthan): lc = 2 * index + 1 # left child rc = lc + 1 # right child # if the left child is inside the heap and the max of the 3, move it up: if (lc < heaplen and greaterthan(array[lc], array[index]) and (rc >= heaplen or (rc < heaplen and not greaterthan(array[rc], array[lc])))): (array[index], array[lc]) = (array[lc], array[index]) fixheap(array, heaplen, lc, greaterthan) # else if the right child is, move it up: elif (rc < heaplen and greaterthan(array[rc], array[index]) and greaterthan(array[rc], array[lc])): (array[index], array[rc]) = (array[rc], array[index]) fixheap(array, heaplen, rc, greaterthan) def makeheap(array, greaterthan): for i in reverserange(len(array)/2): fixheap(array, len(array), i, greaterthan) def heapsort(array, cmp=lambda x, y: x > y): makeheap(array, cmp) for i in reverserange(len(array)): (array[i], array[0]) = (array[0], array[i]) fixheap(array, i, 0, cmp)