-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathHeap.scala
More file actions
71 lines (59 loc) · 2.46 KB
/
Heap.scala
File metadata and controls
71 lines (59 loc) · 2.46 KB
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
package dataStructures
import integerOperations.IntegerProperties._
import dataStructures.miscellaneous.DataStructureException
import dataStructures.miscellaneous.DataStructuresExceptionMessages.EmptyHeapException
case class HeapBranch(min: Int, left: Heap[Int], right: Heap[Int], size: Int, height: Int) extends Heap {
def isEmpty: Boolean = false
}
case object Leaf extends Heap {
def min: Nothing = throw new DataStructureException(EmptyHeapException)
def left: Heap[Nothing] = throw new DataStructureException(EmptyHeapException)
def right: Heap[Nothing] = throw new DataStructureException(EmptyHeapException)
def size: Int = 0
def height: Int = 0
def isEmpty: Boolean = true
}
abstract sealed class Heap[+Int] {
def min: Int
def left: Int
def right: Int
def size: Int
def height: Int
def isEmpty: Boolean
def insert(x: Int): Heap[Int] =
if (isEmpty) Heap.make(x)
else if (left.size < math.pow(2, left.height) - 1)
Heap.bubbleUp(min, left.insert(x), right)
else if (right.size < math.pow(2, right.height) - 1)
Heap.bubbleUp(min, left, right.insert(x))
else if (right.height < left.height)
Heap.bubbleUp(min, left, right.insert(x))
else Heap.bubbleUp(min, left.insert(x), right)
}
case object Leaf extends Heap[Nothing] {
def min: Nothing = throw new DataStructureException(EmptyHeapException)
def left: Heap[Nothing] = throw new DataStructureException(EmptyHeapException)
def right: Heap[Nothing] = throw new DataStructureException(EmptyHeapException)
def size: Int = 0
def height: Int = 0
def isEmpty: Boolean = true
}
object Heap {
def empty: Heap[Int] = Leaf
def make(x: Int, l: Heap[Int] = Leaf, r: Heap[Int] = Leaf): Heap[Int] =
HeapBranch(x, l, r, l.size + r.size + 1, math.max(l.height, r.height) + 1)
private[Heap] def bubbleUp(x: Int, l: Heap[Int], r: Heap[Int]): Heap[Int] = (l, r) match {
case (HeapBranch(y, lt, rt, _, _), _) if x > y =>
Heap.make(y, Heap.make(x, lt, rt), r)
case (_, HeapBranch(z, lt, rt, _, _)) if x > z =>
Heap.make(z, l, Heap.make(x, lt, rt))
case (_, _) => Heap.make(x, l, r)
}
private[Heap] def bubbleDown(x: Int, l: Heap[Int], r: Heap[Int]): Heap[Int] = (l, r) match {
case (HeapBranch(y, _, _, _, _), HeapBranch(z, lt, rt, _, _)) if z < y && x > z =>
Heap.make(z, l, Heap.bubbleDown(x, lt, rt))
case (HeapBranch(y, lt, rt, _, _), _) if x > y =>
Heap.make(y, Heap.bubbleDown(x, lt, rt), r)
case (_, _) => Heap.make(x, l, r)
}
}