In [1]:
import numpy as np
from IPython.display import clear_output
from pjdiagram import *
from ipywidgets import *
from heapsort import heap_sort_example, build_heap_example
from heap import percolate_down
| Performance | Complexity |
|---|---|
| Worst-case | $O(n\log{n})$ |
| Best-case | $O(n\log{n})$ |
| Average | $O(n\log{n})$ |
| Worst-case space | $O(1)$ |
The time complexity for heap sort in all cases make it a good choice when there need to be guarantees for runtime. Additionally, heap sort requires a constant amount of memory, as it can sort in-place.
It is possible implement heap sort by using heap_insert and heap_pop (see notes on heaps). However, both of these operations require the allocation of additional space. Instead, we can perform the same operations in place.
The function build_heap applies the function percoluate_down on each non-leaf node in the tree starting at the bottom.
In [2]:
def build_heap(lst):
# last non-leaf node
nonleaf_nodes = len(lst)/2
# start at bottom work up for each node
for i in range(nonleaf_nodes-1, -1, -1):
percolate_down(lst, i, len(lst))
a visualize demonstration of what build_heap is doing:
In [3]:
build_heap_example()
which allows us to define:
In [4]:
def heap_sort(lst):
build_heap(lst)
# build up list starting from largset at back to smallest up front
for i in range(len(lst)-1, 0, -1):
# move largest value to the back
lst[0], lst[i] = lst[i], lst[0]
# re-heapify tree
percolate_down(lst, 0, i)
return lst
and we can see the sort in action:
In [5]:
heap_sort_example()