-
Notifications
You must be signed in to change notification settings - Fork 109
/
MaxHeap.kt
117 lines (89 loc) · 2.84 KB
/
MaxHeap.kt
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
package structures
import java.lang.IllegalArgumentException
/**
*
* Max-heap is a binary tree in which each parent is greater than its children
*
*/
class MaxHeap(private val maxSize: Int) {
private val data = IntArray(maxSize + 1) { Int.MIN_VALUE }
private val root = 1
private var size = 0
val isEmpty: Boolean
get() = size == 0
private val Int.parent
get() = this / 2
private val Int.leftChild
get() = this * 2
private val Int.rightChild
get() = this * 2 + 1
init {
if (maxSize <= 0) throw IllegalArgumentException("The heap must have maxSize larger than zero")
data[0] = Int.MAX_VALUE
}
// Complexity: O(logn)
fun add(element: Int) {
if (size >= maxSize) throw IllegalStateException("The heap is full!")
data[++size] = Int.MIN_VALUE
set(size, element)
}
// Complexity: O(logn)
fun set(index: Int, newValue: Int) {
if (index < root || index > maxSize) throw IllegalArgumentException("The heap doesn't have the such index: $index!")
if (newValue < data[index]) throw IllegalArgumentException("The new value $newValue is less than the previous: ${data[index]}")
data[index] = newValue
var current = index
while (current > root && data[current.parent] < data[current]) {
swap(current, current.parent)
current = current.parent
}
}
// Complexity: O(1)
fun peekMax() = data[root]
// Complexity: O(logn)
fun popMax(): Int {
if (size < 1) throw IllegalStateException("The heap is empty!")
val max = data[root]
data[root] = data[size--]
heapify(root)
return max
}
private tailrec fun heapify(pos: Int) {
val leftChild = pos.leftChild
val rightChild = pos.rightChild
var largest = pos
if (leftChild <= size && data[leftChild] > data[largest]) {
largest = leftChild
}
if (rightChild <= size && data[rightChild] > data[largest]) {
largest = rightChild
}
if (largest != pos) {
swap(pos, largest)
heapify(largest)
}
}
private fun swap(index1: Int, index2: Int) {
val tmp = data[index1]
data[index1] = data[index2]
data[index2] = tmp
}
companion object {
fun create(intArray: IntArray): MaxHeap {
val arraySize = intArray.size
val heap = MaxHeap(arraySize)
heap.size = intArray.size
var index = 0
while (index < arraySize) {
heap.data[index + 1] = intArray[index]
index++
}
var pos = arraySize / 2
while (pos >= 0) {
heap.heapify(pos)
pos--
}
return heap
}
}
}