-
Notifications
You must be signed in to change notification settings - Fork 0
/
Heap.swift
131 lines (114 loc) · 2.93 KB
/
Heap.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//
// Heap.swift
// Algorithms_Swift
//
// Created by Sicc on 23/09/2019.
// Copyright © 2019 chang sic jung. All rights reserved.
//
import Foundation
struct Heap<Element: Equatable> {
var elements: [Element] = []
let sort: (Element, Element) -> Bool
init(sort: @escaping (Element, Element) -> Bool, elements: [Element] = []) {
self.sort = sort
self.elements = elements
if !elements.isEmpty {
for i in stride(from: elements.count / 2 - 1, through: 0, by: -1) {
siftDown(from: i)
}
}
}
var isEmpty: Bool {
return elements.isEmpty
}
var count: Int {
return elements.count
}
func peek() -> Element? {
return elements.first
}
func leftChildIndex(ofParentAt index: Int) -> Int {
return (2 * index) + 1
}
func rightChildIndex(ofParentAt index: Int) -> Int {
return (2 * index) + 2
}
func parentIndex(ofChildAt index: Int) -> Int {
return (index - 1) / 2
}
mutating func remove() -> Element? {
guard !isEmpty else {
return nil
}
elements.swapAt(0, count - 1)
defer {
siftDown(from: 0)
}
return elements.removeLast()
}
mutating func siftDown(from index: Int) {
var parent = index
while true {
let left = leftChildIndex(ofParentAt: parent)
let right = rightChildIndex(ofParentAt: parent)
var candidate = parent
if left < count && sort(elements[left], elements[candidate]) {
candidate = left
}
if right < count && sort(elements[right], elements[candidate]) {
candidate = right
}
if candidate == parent {
return
}
elements.swapAt(parent, candidate)
parent = candidate
}
}
mutating func insert(_ element: Element) {
elements.append(element)
siftUp(from: elements.count - 1)
}
mutating func siftUp(from index: Int) {
var child = index
var parent = parentIndex(ofChildAt: child)
while child > 0 && sort(elements[child], elements[parent]) {
elements.swapAt(child, parent)
child = parent
parent = parentIndex(ofChildAt: child)
}
}
mutating func remove(at index: Int) -> Element? {
guard index < elements.count else {
return nil // 1
}
if index == elements.count - 1 {
return elements.removeLast() // 2
} else {
elements.swapAt(index, elements.count - 1) // 3
defer {
siftDown(from: index) // 5
siftUp(from: index)
}
return elements.removeLast() // 4
}
}
func index(of element: Element, startingAt i: Int) -> Int? {
if i >= count {
return nil
}
if sort(element, elements[i]) {
return nil
}
if element == elements[i] {
return i
}
if let j = index(of: element, startingAt: leftChildIndex(ofParentAt: i)) {
return j
}
if let j = index(of: element, startingAt: rightChildIndex(ofParentAt: i)) {
return j
}
return nil
}
}