Overview
A d-ary heap is a generalization of the binary heap where each node has up to d children. Like a binary heap, it stores elements in a compact array and maintains the heap property (min-heap or max-heap). Increasing d makes the heap shallower (fewer levels) but increases the fan-out comparisons during downward adjustments. This trade-off can improve throughput for workloads with many decrease-key operations or when cache behavior benefits from fewer pointer-chasing levels.
Compared with Binary Heap, a d-ary heap offers:
-
Shorter height:
⌈log_d n⌉levels instead of⌈log_2 n⌉. -
More work per level: selecting the best among up to
dchildren during sift-down.
Structure Definition
-
Storage: array
A[0..n-1](0-indexed). -
Arity: integer
d ≥ 2. -
Indexing formulas (0-indexed):
PARENT(i) = (i - 1) / d // integer division
CHILD(i, k) = d * i + k // for k in {1..d}
FIRST_CHILD = d * i + 1
LAST_CHILD = min(d * i + d, n - 1)- Heap property (min-heap): For all valid children
cofi,A[i] ≤ A[c]. (Flip comparisons for max-heap.)
Core Operations
Assume a min-heap and a key comparable with <.
Sift-up (decrease-key / insert bubble)
function SIFT_UP(A, i, d):
while i > 0:
p = PARENT(i)
if A[i] < A[p]:
swap(A[i], A[p])
i = p
else:
breakSift-down (extract-min / delete bubble)
function SIFT_DOWN(A, i, n, d):
while true:
left = FIRST_CHILD(i)
if left >= n: break // i is a leaf
// find index m of minimum among children i's [left .. LAST_CHILD(i)]
m = left
last = min(left + d - 1, n - 1)
for c from left to last:
if A[c] < A[m]: m = c
if A[m] < A[i]:
swap(A[i], A[m])
i = m
else:
breakInsert (push)
function INSERT(A, x, d):
A.append(x)
SIFT_UP(A, n-1, d)Find-min and Extract-min (pop)
function MIN(A): return A[0]
function EXTRACT_MIN(A, d):
n = length(A)
minval = A[0]
A[0] = A[n-1]
remove last element
SIFT_DOWN(A, 0, n-1, d)
return minvalDecrease-key
function DECREASE_KEY(A, i, new_key, d):
A[i] = new_key
SIFT_UP(A, i, d)Build-heap (Floyd’s method, generalized)
function BUILD_HEAP(A, d):
n = length(A)
for i from (n-1)/d downto 0:
SIFT_DOWN(A, i, n, d)Example (Stepwise)
Start with d = 3 (ternary heap) and array A = [2, 5, 9, 7, 6, 12] (already a min-heap).
Insert 4:
-
Append →
A = [2, 5, 9, 7, 6, 12, 4], indexi=6. -
SIFT_UP:
PARENT(6) = 2(value9). Swap4and9→A = [2, 5, 4, 7, 6, 12, 9]. -
New
i=2, parentPARENT(2)=0(value2). Stop (4 ≥ 2). Heap property restored.
Extract-min:
-
Save
2, move last element9to root →[9, 5, 4, 7, 6, 12]. -
SIFT_DOWN at
i=0: children indices1..3→ values5, 4, 7; pick smallest4(index 2). Swap →[4, 5, 9, 7, 6, 12]. -
New
i=2: children6..8(none). Stop. Result is a valid min-heap.
Complexity and Performance
Let n be the number of elements.
-
Height:
h = ⌈log_d n⌉. -
Insert / Decrease-key (sift-up):
O(log_d n)comparisons and swaps. -
Extract-min (sift-down):
O(d · log_d n)comparisons in the worst case (up todchild comparisons per level). -
Build-heap:
O(n)time (same asymptotic as binary heaps; the linear-time proof generalizes for constantd). -
Space:
O(n)contiguous array.
Comparison with binary heap (d=2):
-
Larger
d→ fewer levels → fewer parent hops, but more child comparisons per sift-down. -
For workloads dominated by decrease-key (sift-up), higher
dcan be beneficial; for workloads dominated by extract-min, too largedmay hurt due to thedfactor.
Tip
In graph algorithms like Dijkstra’s (with
Vextractions and up toEdecrease-keys), a rough rule is to pickd ≈ max(2, ⌈E / V⌉)to balance many decrease-keys against fewer but heavier extract-mins.
Implementation Details or Trade-offs
-
Choosing
d:-
d = 2(binary) is a strong default. -
d = 4or8can reduce height and improve instruction/cache behavior on modern CPUs. -
Extremely large
dincreases comparison cost and may degrade performance.
-
-
Branching cost: Use unrolled min-child selection for small, fixed
d(e.g.,d ∈ {3,4,8}), or a small loop for generald. -
Stability & duplicates: Heaps are not stable; equal keys may reorder.
-
Decrease-key indexing: If keys live in external records, store handles/indices in the heap to avoid moving large payloads.
-
Cache friendliness: The contiguous array and shallower height often improve locality relative to pointer-based trees.
Practical Use Cases
-
Priority queues in large-fan-out search and scheduling.
-
Shortest paths (Dijkstra’s) where many decrease-keys occur per extract-min.
-
Event simulation with high insertion rates and moderate extract rate.
Limitations / Pitfalls
Warning
Index math bugs: Mind
0-indexing. Children ared*i+1 .. min(d*i+d, n-1). Off-by-one errors at the tail are common.
Warning
Oversized
d: Very largedcan slow down extract-min due todcomparisons per level; pickdbased on workload, not just height.
Warning
d = 1is invalid: The heap wouldn’t progress; required ≥ 2.
Summary
A d-ary heap keeps the compact array layout of heaps while letting you tune arity to the workload. Raising d shrinks height and speeds operations like decrease-key, at the cost of more comparisons during sift-down. With careful choice of d, d-ary heaps can outperform binary heaps in priority-queue heavy algorithms.