Last active
June 29, 2020 00:03
-
-
Save simonbromberg/6167a20774b722860367566476a75fc0 to your computer and use it in GitHub Desktop.
Heap Swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct Heap<Element> { | |
var elements: [Element] | |
let priorityFunction: (Element, Element) -> Bool | |
init(elements: [Element] = [], priorityFunction: @escaping (Element, Element) -> Bool) { | |
self.priorityFunction = priorityFunction | |
self.elements = [] | |
for element in elements { | |
enqueue(element) | |
} | |
} | |
var isEmpty: Bool { | |
return elements.isEmpty | |
} | |
var count: Int { | |
return elements.count | |
} | |
func peek() -> Element? { | |
return elements.first | |
} | |
func isRoot(_ index: Int) -> Bool { | |
return index == 0 | |
} | |
func leftChildIndex(of index: Int) -> Int { | |
return 2 * index + 1 | |
} | |
func rightChildIndex(of index: Int) -> Int { | |
return leftChildIndex(of: index) + 1 | |
} | |
func parentIndex(of index: Int) -> Int { | |
return (index - 1) / 2 | |
} | |
func isHigherPriority(at firstIndex: Int, than secondIndex: Int) -> Bool { | |
return priorityFunction(elements[firstIndex], elements[secondIndex]) | |
} | |
func highestPriorityIndex(of parentIndex: Int, and childIndex: Int) -> Int { | |
guard childIndex < count && isHigherPriority(at: childIndex, than: parentIndex) else { return parentIndex } | |
return childIndex | |
} | |
func highestPriorityIndex(for parent: Int) -> Int { | |
return highestPriorityIndex(of: highestPriorityIndex(of: parent, and: leftChildIndex(of: parent)), and: rightChildIndex(of: parent)) | |
} | |
mutating func swapElement(at firstIndex: Int, with secondIndex: Int) { | |
guard firstIndex != secondIndex, 0..<count ~= firstIndex, 0..<count ~= secondIndex else { | |
return | |
} | |
elements.swapAt(firstIndex, secondIndex) | |
} | |
mutating func enqueue(_ element: Element) { | |
elements.append(element) | |
siftUp(elementAt: count - 1) | |
} | |
mutating func siftUp(elementAt index: Int) { | |
let parent = parentIndex(of: index) | |
guard !isRoot(index), isHigherPriority(at: index, than: parent) else { | |
return | |
} | |
swapElement(at: index, with: parent) | |
siftUp(elementAt: parent) | |
} | |
mutating func dequeue() -> Element? { | |
swapElement(at: 0, with: count - 1) | |
let element = elements.popLast() | |
siftDown(elementAt: 0) | |
return element | |
} | |
mutating func siftDown(elementAt index: Int) { | |
let child = highestPriorityIndex(for: index) | |
if index == child { | |
return | |
} | |
swapElement(at: index, with: child) | |
siftDown(elementAt: child) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment