In Swift, implementing a generic heap can provide flexibility and reusability for storing any comparable elements. Below is a simple implementation of a min-heap which maintains the smallest element at the top.
class Heap {
private var elements: [T] = []
func insert(_ value: T) {
elements.append(value)
siftUp(from: elements.count - 1)
}
func remove() -> T? {
guard !elements.isEmpty else { return nil }
if elements.count == 1 { return elements.removeLast() }
let minValue = elements[0]
elements[0] = elements.removeLast()
siftDown(from: 0)
return minValue
}
var peek: T? {
return elements.first
}
private func siftUp(from index: Int) {
var childIndex = index
let child = elements[childIndex]
var parentIndex = (childIndex - 1) / 2
while childIndex > 0 && child < elements[parentIndex] {
elements[childIndex] = elements[parentIndex]
childIndex = parentIndex
parentIndex = (childIndex - 1) / 2
}
elements[childIndex] = child
}
private func siftDown(from index: Int) {
var parentIndex = index
let length = elements.count
while true {
let leftChildIndex = 2 * parentIndex + 1
let rightChildIndex = 2 * parentIndex + 2
var firstIndex = parentIndex
if leftChildIndex < length && elements[leftChildIndex] < elements[firstIndex] {
firstIndex = leftChildIndex
}
if rightChildIndex < length && elements[rightChildIndex] < elements[firstIndex] {
firstIndex = rightChildIndex
}
if firstIndex == parentIndex { return }
elements.swapAt(parentIndex, firstIndex)
parentIndex = firstIndex
}
}
}
How do I avoid rehashing overhead with std::set in multithreaded code?
How do I find elements with custom comparators with std::set for embedded targets?
How do I erase elements while iterating with std::set for embedded targets?
How do I provide stable iteration order with std::unordered_map for large datasets?
How do I reserve capacity ahead of time with std::unordered_map for large datasets?
How do I erase elements while iterating with std::unordered_map in multithreaded code?
How do I provide stable iteration order with std::map for embedded targets?
How do I provide stable iteration order with std::map in multithreaded code?
How do I avoid rehashing overhead with std::map in performance-sensitive code?
How do I merge two containers efficiently with std::map for embedded targets?