Intuition The one core idea
A heap is just an ordinary array that we pretend is a triangular family tree, where every parent is bigger than its kids — so the biggest number always sits at the very front. Heap sort works by repeatedly grabbing that front champion, parking it at the back, and fixing the tree; do this n times and the array comes out sorted, without ever needing a second array.
Before you can read the parent note, you need to see the objects it talks about. This page builds every one of them from nothing. Take them in order — each rests on the one above it.
An array is a row of numbered boxes sitting next to each other in memory. Each box holds one value; each box has an index — its position number.
We write the array as A , and the value in box number i as A [ i ] .
Think of lockers in a hallway, numbered starting at 0 : locker 0 , locker 1 , locker 2 , … Because computers count from zero, the first box is index 0 , not 1 . That single convention decides every formula on this page, so lock it in now.
n = the length of the array = how many boxes there are.
The valid indices are therefore 0 , 1 , 2 , … , n − 1 . The last index is n − 1 , not n — box n does not exist. This off-by-one is the single most common bug source, so we name it now.
Common mistake The last box is
n − 1
If n = 5 , the boxes are A [ 0 ] , A [ 1 ] , A [ 2 ] , A [ 3 ] , A [ 4 ] . Asking for A [ 5 ] walks off the end. Whenever the parent note writes end = n-1, it means "point at the genuine last box."
A binary tree is a family diagram where one top node (the root ) can have up to two children, each child can have up to two children, and so on downward.
Picture a tournament bracket drawn upside-down: one champion slot at the top, splitting into two, then four, then eight. "Binary" just means at most two branches per node. The words we borrow from family trees:
root — the topmost node (has no parent).
parent — the node directly above another.
child — the node directly below (left child / right child).
leaf — a node with no children (bottom of a branch).
Why does the topic need a tree at all? Because a plain array has no notion of "bigger than my neighbours above." The tree gives us a direction — up — so we can talk about a single biggest value floating to the top.
Definition Complete binary tree
A complete binary tree is one where every level is completely full, except possibly the bottom level , which fills strictly left to right with no gaps.
Intuition Why "complete" matters
A tree normally needs pointers — little arrows in memory saying "my left child lives over there." Pointers cost extra memory. But if the tree has no gaps , we can just lay the nodes out row by row (level 0, then level 1, then level 2…) into the array boxes, and the position alone tells us who is whose child. No arrows needed.
Read the figure top-to-bottom, left-to-right, writing each node into the next array box. The tree and the array are now the same thing , viewed two ways. That equality is the whole reason heap sort is in-place (uses no extra array).
Now that the tree lives in the array, "go to my child" must become a calculation on the index number . For a node at index i (0-indexed, complete tree):
Two new symbols appear here — earn them before using them:
2 i + 1 and 2 i + 2 : plain multiplication and addition. Nothing hidden.
⌊ ⌋ — the floor brackets.
⌊ x ⌋
⌊ x ⌋ means "round down to the nearest whole number." ⌊ 2.9 ⌋ = 2 , ⌊ 3.0 ⌋ = 3 , ⌊ 0.5 ⌋ = 0 .
Intuition Why floor is needed here
When we divide ( i − 1 ) by 2 we sometimes get a fraction like 2.5 . But there is no "box number 2.5 ." Both children of one parent must point back to the same whole-number parent, so we throw away the fraction. That is exactly what flooring does — it answers the question "which single parent do I belong to?"
Worked example Check the formulas on a small tree
Take the root i = 0 :
left child = 2 ( 0 ) + 1 = 1 ✓
right child = 2 ( 0 ) + 2 = 2 ✓
Now take node i = 4 :
parent = ⌊( 4 − 1 ) /2 ⌋ = ⌊ 1.5 ⌋ = 1 .
Node i = 3 's parent = ⌊( 3 − 1 ) /2 ⌋ = ⌊ 1 ⌋ = 1 .
So boxes 3 and 4 are both children of box 1 — the floor made two different children agree on one parent. That is the design working.
≥
a ≥ b reads "==a is greater than or equal to b ==." So 5 ≥ 3 is true, and 4 ≥ 4 is also true. (The parent uses this to allow duplicate values as parent and child.)
Definition Max-heap property
A max-heap is a complete binary tree where every parent is ≥ both of its children. Nothing is said about left-vs-right order between siblings — only parent-beats-child.
Intuition What this guarantees, and what it does NOT
Since each parent outranks its kids, and those kids outrank their kids, the biggest value in the whole heap can only be at one place — the root, index 0 . That is the payoff: the champion is always instantly findable at A [ 0 ] .
But a heap is not a sorted array. Siblings can be in any order; a value two levels down might be larger than something on a different branch. A heap is "loosely sorted, tightly rooted."
swap( A [ i ] , A [ j ]) : exchange the contents of two boxes. Box i 's value goes to box j and vice-versa. This is how heap sort moves data without a second array.
sift-down (a.k.a. heapify ): if a node's value is too small for its position, keep swapping it downward with its larger child until it sits where the heap rule holds. The parent note's inner loop is this verb.
Intuition Picture of sift-down
A too-small value at the top is like a heavy diver: it sinks past lighter children level by level until it settles. Each sink is one comparison + one swap, and a complete tree is only about log 2 n levels tall — so it sinks at most log 2 n times.
log 2 n
log 2 n answers "==how many times can I halve n before reaching 1 ?==" Equivalently, "how many levels tall is a complete tree holding n nodes?" For n = 8 : halve to 4 , 2 , 1 — three halvings — so log 2 8 = 3 .
O ( ⋅ )
O ( f ( n )) is shorthand for "==the running time grows no faster than f ( n ) == as the array gets big." O ( n log n ) means: do roughly n things, each costing about log n steps.
Intuition Why these two show up together in heap sort
We crown a champion n times (that's the n ). Each crowning ends with one sift-down through a tree of height log 2 n (that's the log n ). Multiply: O ( n log n ) . Every symbol in the parent's headline is now something you can see , not just read.
Binary tree root parent child
Index formulas 2i+1 2i+2 floor
Log n height gives O n log n
Cover the right side and answer each aloud before opening the parent note.
In a 0-indexed array of length n , what is the last valid index? n − 1
What does "complete" buy us that lets a tree live in a flat array? No gaps, so position alone encodes parent/child — no pointers, no extra memory.
Left child of node i ? 2 i + 1
Right child of node i ? 2 i + 2
Parent of node i ? ⌊ ( i − 1 ) /2 ⌋
Why is there a floor in the parent formula? Division can give a fraction, but both children must map back to the one whole-numbered parent box, so we round down.
What is ⌊ 3.5 ⌋ ? 3
State the max-heap property in words. Every parent is greater than or equal to both of its children.
Where does the maximum value always sit in a max-heap? At the root, index 0 .
Is a heap the same as a sorted array? No — only parent-beats-child holds; siblings are unordered.
What does sift-down do? Sinks a too-small node downward by swapping with its larger child until the heap rule holds.
What does log 2 n count here? The number of levels (height) of a complete tree with n nodes.
Why is heap sort O ( n log n ) ? n crownings, each ending in a sift-down of cost log n .
Recall Quick self-quiz
For n = 16 , how tall is the heap (levels below root)? ::: log 2 16 = 4 .
Node 7 's parent? ::: ⌊ 6/2 ⌋ = 3 .