Skip to content

Ternary Heapsort

Heapsort variant that uses a ternary heap with three children per node.

Ternary heapsort replaces the binary heap with a ternary heap, where each node has up to three children instead of two. This reduces the height of the heap, which can reduce the number of levels traversed during heap operations.

The tradeoff is that each step may require more comparisons to select the largest child.

Problem

Given an array AA of length nn, reorder it such that:

A[0]A[1]A[n1] A[0] \le A[1] \le \dots \le A[n-1]

Idea

In a ternary heap, the children of node ii are:

3i+1,3i+2,3i+3 3i + 1,\quad 3i + 2,\quad 3i + 3

This reduces the height of the heap to:

O(log3n) O(\log_3 n)

which is smaller than the binary heap height:

O(log2n) O(\log_2 n)

Algorithm

ternary_heapsort(A):
    build_ternary_heap(A)

    for i from n - 1 down to 1:
        swap A[0] and A[i]
        heapify(A, 0, i)

Heap construction:

build_ternary_heap(A):
    for i from floor((n - 2) / 3) down to 0:
        heapify(A, i, n)

Heapify:

heapify(A, i, size):
    largest = i

    c1 = 3*i + 1
    c2 = 3*i + 2
    c3 = 3*i + 3

    if c1 < size and A[c1] > A[largest]:
        largest = c1
    if c2 < size and A[c2] > A[largest]:
        largest = c2
    if c3 < size and A[c3] > A[largest]:
        largest = c3

    if largest != i:
        swap A[i] and A[largest]
        heapify(A, largest, size)

Example

Let:

A=[4,9,7,1,3,6,2] A = [4, 9, 7, 1, 3, 6, 2]

Construct a ternary heap:

[9,4,7,1,3,6,2] [9, 4, 7, 1, 3, 6, 2]

Then repeatedly extract the maximum and restore the heap until sorted.

Correctness

The heap property ensures that every parent node is greater than or equal to its children. The root is therefore the maximum element. Swapping it with the last element places it in its correct position. Repeating this process produces a sorted array.

Complexity

metricvalue
build heapO(n)O(n)
extractionO(nlogn)O(n \log n)

Height:

O(log3n) O(\log_3 n)

Each heapify step examines up to three children, so comparisons per level increase slightly.

Total complexity remains:

O(nlogn) O(n \log n)

Properties

propertyvalue
stableno
in-placeyes
branching factor3
heightlower than binary heap
comparisons per levelhigher

Notes

Ternary heapsort trades fewer levels for more comparisons at each level. In practice, performance depends on hardware and data patterns. Binary heaps are more common, but higher arity heaps can perform better in some environments.

This idea generalizes to dd-ary heaps, where each node has dd children.

Implementation

def ternary_heapsort(a):
    n = len(a)

    def heapify(i, size):
        largest = i
        c1 = 3 * i + 1
        c2 = 3 * i + 2
        c3 = 3 * i + 3

        if c1 < size and a[c1] > a[largest]:
            largest = c1
        if c2 < size and a[c2] > a[largest]:
            largest = c2
        if c3 < size and a[c3] > a[largest]:
            largest = c3

        if largest != i:
            a[i], a[largest] = a[largest], a[i]
            heapify(largest, size)

    for i in range((n - 2) // 3, -1, -1):
        heapify(i, n)

    for i in range(n - 1, 0, -1):
        a[0], a[i] = a[i], a[0]
        heapify(0, i)

    return a
func TernaryHeapSort(a []int) {
	n := len(a)

	var heapify func(int, int)
	heapify = func(i, size int) {
		largest := i

		c1 := 3*i + 1
		c2 := 3*i + 2
		c3 := 3*i + 3

		if c1 < size && a[c1] > a[largest] {
			largest = c1
		}
		if c2 < size && a[c2] > a[largest] {
			largest = c2
		}
		if c3 < size && a[c3] > a[largest] {
			largest = c3
		}

		if largest != i {
			a[i], a[largest] = a[largest], a[i]
			heapify(largest, size)
		}
	}

	for i := (n - 2) / 3; i >= 0; i-- {
		heapify(i, n)
	}

	for i := n - 1; i > 0; i-- {
		a[0], a[i] = a[i], a[0]
		heapify(0, i)
	}
}