08-heaps
Min-Heap Pop (Sift Down)
Remove the minimum value, move the last item to the root, and sift downward.
Algorithm
Steps
- Store the heap in an array.
- Compare parent and child indexes instead of building explicit tree nodes.
- Swap only when the heap order is violated.
- Print the deterministic final heap state for replay comparison.
Complexity
- Time: O(log n)
- Space: O(1) extra
sift down
After removing the root, the last value moves to the root and swaps with the smaller child until order is restored.
Visual walkthrough
Kotlin DSA Implementation
basic.kt
fun listString(values: List<Int>) = values.joinToString(", ", "[", "]")
fun heapInsert(heap: MutableList<Int>, value: Int) {
heap.add(value)
var child = heap.lastIndex
while (child > 0) {
val parent = (child - 1) / 2
if (heap[parent] <= heap[child]) break
val tmp = heap[parent]; heap[parent] = heap[child]; heap[child] = tmp
child = parent
}
}
fun heapPop(heap: MutableList<Int>): Int {
val smallest = heap[0]
heap[0] = heap.removeAt(heap.lastIndex)
var parent = 0
while (true) {
val left = parent * 2 + 1
val right = left + 1
if (left >= heap.size) break
var child = left
if (right < heap.size && heap[right] < heap[left]) child = right
if (heap[parent] <= heap[child]) break
val tmp = heap[parent]; heap[parent] = heap[child]; heap[child] = tmp
parent = child
}
return smallest
}
fun main() { val heap = mutableListOf(1, 4, 2, 9, 6, 7); val popped = heapPop(heap); println("$popped -> ${listString(heap)}") }
Output
1 -> [2, 4, 7, 9, 6]
Implementation notes
- Kotlin stores the heap in
val heap = mutableListOf(1, 4, 2, 9, 6, 7), aMutableList<Int>whose binding is stable while its elements are mutated in place. heapPop(heap: MutableList<Int>): Intcopiesval smallest = heap[0]and returns that removed minimum after the sift-down.- Root replacement uses
heap[0] = heap.removeAt(heap.lastIndex):removeAtremoves and returns the last element, then that value is written into index0. The checked call uses a six-element heap; this compact helper does not handle an empty or singleton heap separately. - Sift-down starts with mutable
var parent = 0; child indexes areleft = parent * 2 + 1andright = left + 1. if (left >= heap.size) breakstops at a leaf.var child = leftis replaced byrightonly whenright < heap.size && heap[right] < heap[left].- This is a min-heap:
if (heap[parent] <= heap[child]) breakstops when the parent is already no larger than the smaller child. - Swaps use an explicit temporary variable:
val tmp = heap[parent]; heap[parent] = heap[child]; heap[child] = tmp, thenparent = childcontinues downward. - The trace shows
[1, 4, 2, 9, 6, 7], removes1and moves7to the root as[7, 4, 2, 9, 6], then swaps with smaller child2to[2, 4, 7, 9, 6]. println("$popped -> ${listString(heap)}")prints1 -> [2, 4, 7, 9, 6].