Heaps are a type of data structure, defined as an array of elements such that it functions according to a heap shape property, such that the heap is an almost complete binary tree (where the last row isn’t full), and the heap order property, which is a specific criterion the heap may fulfil to be valid.

Two common types of heaps are min-heaps and max-heaps, which have the property and , respectively.

For a max heap, the maximum element is at the root.

The heap shape property allows us to index:

The height of a node in a heap is the number of edges on the longest simple downwards path from the node to a leaf. The height of the heap is the height of its root. Because we talk about a binary heap, its height is .

Operations

There are a few operations we want to implement for a max heap:

  • Inserting a new element.
  • Getting the maximum element.
  • Maintaining the max heap property (which runs in ).

The heapify function enforces the heap order property if it’s violated, with runtime . The max heapify function effectively pushes down smaller nodes.

def max_heapify(A, i): # assume i do boundary checking
	l = left(i)
	r = right(i)
	if (A[l] > A[i]):
		largest = l
	else: largest = i
 
	if (A[r] > A[largest]):
		largest = r
	if (largest != i)
		swap(A[i], A[largest]) # max(A[2i], A[2i + 1])
		max_heapify(A, largest)
		# recurse downwards
		# until property is not violated or we've hit a leaf node

The build-max-heap function constructs a max heap. It starts at the halfway point in the array because all elements to the right of floor(n / 2) are leaf nodes. Then, we work our way up the heap.

function Build-Max-Heap(A, n):
	for each i = floor(n / 2) -> 1 do
		Max-Heapify(A, i)

Its time complexity is naively , which is a correct upper bound, but not asymptotically tight. However, we can construct a tighter bound:

  • At height , there are at most nodes. Since we work our way up, the number of nodes at each level decreases exponentially (half the nodes of the previous iteration’s level).
    • This means the number of nodes that require a heapify decreases as we move up the tree. i.e., at the bottom, we do calls to max-heapify, then , then .
    • Basically, the premise that max-heapify requires is incorrect. It will never swap all the way down to the leaves (at each subtree, it only requires at most one swap).
  • The height of the heap is .
  • Then the runtime is the following. The sum converges absolutely.

Heapsort also relies on heap properties.

See also

  • Heap memory, a different construct in programming languages for dynamically allocated, often garbage collected memory
  • Priority queue, an abstract data type typically implemented with a heap