Building a heap from an array of input elements can be done by starting with an empty heap, then successively inserting each element. This approach, called Williams' method after the inventor of binary heaps, is easily seen to run in time: it performs insertions at cost each. However, Williams' method is suboptimal. A faster method (due to
Floyd) starts by arbitrarily putting the elements on a binary tree, respecting the shape property (the tree could be represented by an array, see below). Then starting from the lowest level and moving upwards, sift the root of each subtree downward as in the deletion algorithm until the heap property is restored. More specifically if all the subtrees starting at some height h have already been "heapified" (the bottommost level corresponding to h=0), the trees at height h+1 can be heapified by sending their root down along the path of maximum valued children when building a max-heap, or minimum valued children when building a min-heap. This process takes O(h) operations (swaps) per node. In this method most of the heapification takes place in the lower levels. Since the height of the heap is \lfloor \log n \rfloor, the number of nodes at height h is \le \frac{2^{\lfloor \log n \rfloor}}{2^h} \le \frac{n}{2^h}. Therefore, the cost of heapifying all subtrees is: : \begin{align} \sum_{h=0}^{\lfloor \log n \rfloor} \frac{n}{2^h} O(h) & = O\left(n\sum_{h=0}^{\lfloor \log n \rfloor} \frac{h}{2^h}\right) \\ & = O\left(n\sum_{h=0}^{\infty} \frac{h}{2^h}\right) \\ & = O(n) \end{align} This uses the fact that the given infinite
series \sum_{i=0}^\infty i/2^i
converges. The exact value of the above (the worst-case number of comparisons during the heap construction) is known to be equal to: : 2 n - 2 s_2 (n) - e_2 (n) , where is the
sum of all digits of the binary representation of and is the exponent of in the prime factorization of . The average case is more complex to analyze, but it can be shown to asymptotically approach comparisons. The
Build-Max-Heap function that follows, converts an array
A which stores a complete binary tree with
n nodes to a max-heap by repeatedly using
Max-Heapify (down-heapify for a max-heap) in a bottom-up manner. The array elements indexed by , , ...,
n are all leaves for the tree (assuming that indices start at 1)—thus each is a one-element heap, and does not need to be down-heapified.
Build-Max-Heap runs
Max-Heapify on each of the remaining tree nodes.
Build-Max-Heap (
A):
for each index
i from floor(
length(
A)/2)
downto 1
do: Max-Heapify(
A,
i) == Heap implementation == Heaps are commonly implemented with an
array. Any binary tree can be stored in an array, but because a binary heap is always a complete binary tree, it can be stored compactly. No space is required for
pointers; instead, the parent and children of each node can be found by arithmetic on array indices. These properties make this heap implementation a simple example of an
implicit data structure or
Ahnentafel list. Details depend on the root position, which in turn may depend on constraints of a
programming language used for implementation, or programmer preference. Specifically, sometimes the root is placed at index 1, in order to simplify arithmetic. Let
n be the number of elements in the heap and
i be an arbitrary valid index of the array storing the heap. If the tree root is at index 0, with valid indices 0 through
n − 1, then each element
a at index
i has • children at indices 2
i + 1 and 2
i + 2 • its parent at index
floor((
i − 1) / 2). Alternatively, if the tree root is at index 1, with valid indices 1 through
n, then each element
a at index
i has • children at indices 2
i and 2
i +1 • its parent at index
floor(
i / 2). This implementation is used in the
heapsort algorithm which reuses the space allocated to the input array to store the heap (i.e. the algorithm is done
in-place). This implementation is also useful as a
Priority queue. When a
dynamic array is used, insertion of an unbounded number of items is possible. The upheap or downheap operations can then be stated in terms of an array as follows: suppose that the heap property holds for the indices
b,
b+1, ...,
e. The sift-down function extends the heap property to
b−1,
b,
b+1, ...,
e. Only index
i =
b−1 can violate the heap property. Let
j be the index of the largest child of
a[
i] (for a max-heap, or the smallest child for a min-heap) within the range
b, ...,
e. (If no such index exists because then the heap property holds for the newly extended range and nothing needs to be done.) By swapping the values
a[
i] and
a[
j] the heap property for position
i is established. At this point, the only problem is that the heap property might not hold for index
j. The sift-down function is applied
tail-recursively to index
j until the heap property is established for all elements. The sift-down function is fast. In each step it only needs two comparisons and one swap. The index value where it is working doubles in each iteration, so that at most log2
e steps are required. For big heaps and using
virtual memory, storing elements in an array according to the above scheme is inefficient: (almost) every level is in a different
page.
B-heaps are binary heaps that keep subtrees in a single page, reducing the number of pages accessed by up to a factor of ten. The operation of merging two binary heaps takes Θ(
n) for equal-sized heaps. The best you can do is (in case of array implementation) simply concatenating the two heap arrays and build a heap of the result. A heap on
n elements can be merged with a heap on
k elements using O(log
n log
k) key comparisons, or, in case of a pointer-based implementation, in O(log
n log
k) time. An algorithm for splitting a heap on
n elements into two heaps on
k and
n-k elements, respectively, based on a new view of heaps as an ordered collections of subheaps was presented in. The algorithm requires O(log
n * log
n) comparisons. The view also presents a new and conceptually simple algorithm for merging heaps. When merging is a common task, a different heap implementation is recommended, such as
binomial heaps, which can be merged in O(log
n). Additionally, a binary heap can be implemented with a traditional binary tree data structure, but there is an issue with finding the adjacent element on the last level on the binary heap when adding an element. This element can be determined algorithmically or by adding extra data to the nodes, called "threading" the tree—instead of merely storing references to the children, we store the
inorder successor of the node as well. It is possible to modify the heap structure to make the extraction of both the smallest and largest element possible in
O(\log n) time. To do this, the rows alternate between min heap and max-heap. The algorithms are roughly the same, but, in each step, one must consider the alternating rows with alternating comparisons. The performance is roughly the same as a normal single direction heap. This idea can be generalized to a min-max-median heap. == Derivation of index equations ==