Introduction
A binary heap is a complete binary tree, stored in an array, in which every parent is at least as large as its children (a max-heap) or at most as large (a min-heap). It answers one question fast: "which element has the highest priority?" The answer sits at the root, and the structure can be repaired in time after an insertion or a removal.
That makes the heap the standard implementation of a priority queue, used in heapsort, in Dijkstra's shortest-path algorithm and Prim's minimum spanning tree algorithm, in Huffman coding, and in priority scheduling of processes.
A heap is not a search structure: it does not keep keys sorted and cannot find an arbitrary key quickly. It keeps only enough order to expose the maximum (or minimum).
Prerequisites
- Trees and Binary Trees: complete binary trees, height convention (edges), array representation.
- Arrays: index arithmetic.
- Logarithms and geometric sums; the sum is derived below.
Core concepts
Shape property and heap property
A binary heap must satisfy two conditions.
- Shape property. The tree is a complete binary tree: all levels are full except possibly the last, which is filled from the left.
- Heap property. For a max-heap, for every node other than the root. For a min-heap, the inequality is reversed.
The heap property is local (parent versus child), but by transitivity it implies that every node is at least as large as everything in its subtree. Hence the maximum of a max-heap is at the root. Nothing is said about the order between siblings or between different subtrees.
Min versus max. Every statement in this note has a mirror image: swap "max" with "min", "largest" with "smallest" and with . The examples use max-heaps.
Array layout (1-indexed)
Store the nodes level by level in . Then, for :
where a child index larger than means the child does not exist. With 0-based arrays the formulas are , and . These notes use 1-based indexing for heaps; check the convention in every question.
Useful consequences for a heap of elements:
- Height for (empty height ); (edge convention).
- Leaves are exactly , so there are leaves; internal nodes are .
- In a max-heap the minimum is one of the leaves; finding it still takes time.
- The second largest element is at index 2 or 3. More generally, the -th largest element is at depth at most . For , over all inputs the 2nd largest appears only at indices 2 and 3, and the 3rd largest anywhere in indices 2 to 7, never at the root. This bounds the search region for the largest elements.

The core operations
Pseudocode uses 1-based arrays, <- for assignment and A.size for the number of elements currently in the heap.
MAX-HEAPIFY (sift down)
Precondition: the subtrees rooted at and are max-heaps, but may be smaller than a child. MAX-HEAPIFY moves down until the subtree rooted at is a max-heap.
MAX-HEAPIFY(A, i) // iterative; O(1) auxiliary space
while i <= A.size
l <- 2i
r <- 2i + 1
largest <- i
if l <= A.size and A[l] > A[largest] then largest <- l
if r <= A.size and A[r] > A[largest] then largest <- r
if largest = i then return
exchange A[i] with A[largest]
i <- largestEach level costs at most two comparisons and one exchange, so the time is , where is the height of node ; from the root that is .
BUILD-MAX-HEAP (bottom-up)
BUILD-MAX-HEAP(A, n)
A.size <- n
for i <- floor(n/2) downto 1
MAX-HEAPIFY(A, i)Leaves are already one-element heaps, so the loop starts at the last internal node . Going downwards in index guarantees that when node is processed, both of its subtrees are already heaps, which is the precondition of MAX-HEAPIFY.
Worked example: building a heap
Input , , so the loop runs .
| Step | Node (value) | What happens | Array after the step | Exchanges |
|---|---|---|---|---|
| 25 | Children 8 and 4 are smaller; no change | 5 13 2 25 7 17 20 8 4 | 0 | |
| 2 | Larger child is 20 (index 7); exchange | 5 13 20 25 7 17 2 8 4 | 1 | |
| 13 | Larger child is 25 (index 4); exchange; at index 4, 13 beats 8 and 4 | 5 25 20 13 7 17 2 8 4 | 1 | |
| 5 | Exchange with 25 (index 2), then with 13 (index 4), then with 8 (index 8) | 25 13 20 8 7 17 2 5 4 | 3 |
Result: the max-heap after 5 exchanges.

Why BUILD-MAX-HEAP is , not
The easy bound multiplies about calls by per call and gets . That bound is correct but loose, because most nodes are near the bottom and sift down only a short distance.
A node of height costs . In an -element heap there are at most nodes of height , and for this is at most (because whenever ). So the total work is at most
using at . The loop also touches nodes, so the time is as well. Hence BUILD-MAX-HEAP runs in .
An exact count makes this concrete. Each exchange moves a key down one level, so the number of exchanges is at most the sum of the heights of all nodes. For a perfect tree of height (so ) that sum is : 4 for , 11 for , 57 for . Over all inputs, the maximum number of exchanges for is exactly 4 (reached, for example, by the increasing input 1 2 3 4 5 6 7).

Top-down construction is different. Building a heap by successive INSERT calls costs in the worst case (for example, keys arriving in increasing order into a max-heap, where each new key rises to the root). Only the bottom-up method is .
INSERT and INCREASE-KEY (sift up)
MAX-HEAP-INSERT(A, key)
A.size <- A.size + 1
A[A.size] <- key
i <- A.size
while i > 1 and A[floor(i/2)] < A[i]
exchange A[i] with A[floor(i/2)]
i <- floor(i/2)INCREASE-KEY at index sets the larger value and runs the same while loop from . DECREASE-KEY in a max-heap runs MAX-HEAPIFY from instead. Each is .
EXTRACT-MAX
HEAP-EXTRACT-MAX(A)
if A.size < 1 then error "heap underflow"
max <- A[1]
A[1] <- A[A.size]
A.size <- A.size - 1
MAX-HEAPIFY(A, 1)
return maxWorked example: insert and extract
Start from the heap .
- Insert 30. Place it at index 10. Its parent (index 5) holds 7: exchange. Parent (index 2) holds 13: exchange. Parent (index 1) holds 25: exchange. Result , after 3 exchanges.
- Extract-max (from the original 9-element heap). Return 25; move the last element 4 to the root; sift down: exchange with 20 (index 3), then with 17 (index 6). Result , after 2 exchanges.
- Increase-key (from the original heap): change from 4 to 22. It rises past 8 (index 4) and 13 (index 2) and stops below 25. Result .
Both panels of Figure 4 start from the same original heap : the extract-max panel does not contain the inserted 30, so it returns 25, not 30.

Cost of operations
Under unit-cost key comparisons/array accesses, bounds below are worst-case unless marked otherwise. Best cases for insert, extract-max, known-index key update/delete and arbitrary-key search are constant (e.g. no sift needed, delete the last element, or find the root). Find-max is always constant; bottom-up build is linear; min-scan is linear; concatenate-and-build merge is linear for every input. Average-case bounds require a distribution and are deferred. For a binary max-heap with elements:
| Operation | Time | Note |
|---|---|---|
| Find maximum | ||
| Insert | Sift up; if the new key is small | |
| Extract-max | Sift down from the root | |
| Increase-key or decrease-key at a known index | Sift up or down | |
| Delete at a known index | Replace by the last element, then sift up or down | |
| Build from keys (bottom-up) | Analysis above | |
| Search for an arbitrary key | No ordering to exploit | |
| Find minimum in a max-heap | Scan the leaves | |
| Merge two heaps of sizes and | Concatenate arrays and build |
Space is for the array. BUILD-MAX-HEAP, HEAP-EXTRACT-MAX and HEAPSORT all call the displayed iterative MAX-HEAPIFY, so those implementations use auxiliary workspace. A recursive heapify would instead need worst-case call-stack space.
Heapsort in brief
Heapsort builds a max-heap, then repeatedly exchanges the root with the last element of the heap, shrinks the heap by one, and sifts the new root down.
HEAPSORT(A, n)
BUILD-MAX-HEAP(A, n)
for i <- n downto 2
exchange A[1] with A[i]
A.size <- A.size - 1
MAX-HEAPIFY(A, 1)- Time in the worst case: to build plus sift-downs of each. Distinct keys have worst-case ; with all equal keys, sift-downs terminate immediately and total time is . Average-input analysis is deferred rather than assumed. It is not adaptive: sorted input does not make it faster in general.
- In place: extra space, using the iterative MAX-HEAPIFY displayed here.
- Not stable. Sorting the records (compared on the number only) produces : the two equal keys swap their original order.
- Full treatment: Heapsort.
Finding the $k$-th smallest element
- With a min-heap of all elements: build in , then extract-min times: . For the example keys , the third extraction returns 5, the 3rd smallest.
- Without destroying the heap: keep a second, small min-heap of "candidates", starting with the root. Each time the smallest candidate is removed, add its two children from the big heap. After removals the -th one removed is the answer, in time, because the candidate heap never holds more than items.
d-ary heaps
For integer , a -ary heap lets each node have up to children, still complete and still stored level by level. With 1-based indexing, the children of node are at indices
For these reduce to and . Example for : the children of node 2 are at 5, 6 and 7, and the parent of node 10 is node 3.
The height is ; for it is 4 when and 6 when . Insert and increase-key cost (fewer levels to climb), while extract-max costs because each level compares up to children. A larger therefore helps algorithms with many key increases and few extractions.
Important properties and observations
- A sorted array (descending for a max-heap) is always a valid heap; a heap is usually not sorted.
- Every subtree of a heap is a heap. Every path from the root to a leaf is sorted (non-increasing in a max-heap).
- The number of distinct max-heaps that can be formed from distinct keys has and, for , satisfies , where is the size of the left subtree forced by the complete shape. Values: .
- Bottom-up build is ; insertions are . These are different algorithms and can give different final arrays from the same input: for input 1, 2, 3, bottom-up gives 3 2 1 and three insertions give 3 1 2.
- A heap gives access only to one end. For both the minimum and the maximum, use two heaps or a different structure.
GATE examination perspective
- Array traces. Questions give an array and ask for the result of build-heap, an insertion or a deletion. Work level by level, and record the array after each operation. Check the heap property at the end.
- "Is this array a heap?" Check for every ; the shape is automatic for an array without gaps.
- Counting comparisons or exchanges. State what is counted. MAX-HEAPIFY as written above makes up to two key comparisons per level (left child with the current node, then right child with the larger of the two).
- Complexity traps. Build-heap is , not . Searching a heap is . Finding the minimum of a max-heap is .
- Indexing traps. 0-based and 1-based formulas differ, so an off-by-one index is a likely error.
- Position of the -th largest. Depth at most (see "Array layout"); the smallest is a leaf.
Summary
Sources
- T. H. Cormen, C. E. Leiserson, R. L. Rivest, C. Stein, Introduction to Algorithms, 3rd ed., MIT Press, 2009: Chapter 6 (heaps, MAX-HEAPIFY, BUILD-MAX-HEAP and its linear-time analysis, heapsort, priority queues, and Problem 6-2 on d-ary heaps), Sections 6.1 to 6.5.
- P. Morin, Open Data Structures (Python edition), Section 10.1 "BinaryHeap: An Implicit Binary Tree", (consulted 2026-11-09; uses 0-based indexing and a min-heap).