-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathheap.js
More file actions
119 lines (96 loc) · 2.27 KB
/
heap.js
File metadata and controls
119 lines (96 loc) · 2.27 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
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
goog.provide('soko.Heap');
goog.require('soko.HeapInterface');
goog.scope(function() {
/**
* @constructor
* @implements {soko.HeapInterface}
*/
soko.Heap = function() {
this.data_ = [];
this.map_ = {};
};
var Heap = soko.Heap;
Heap.prototype.size = function() {
return this.data_.length;
};
Heap.prototype.empty = function() {
return this.data_.length == 0;
};
Heap.prototype.push = function(value, score) {
var index = this.data_.length;
this.data_[index] = {score: score, value: value};
this.map_[value.id] = index;
this.siftUp_(index);
};
Heap.prototype.pop = function() {
this.swap_(0, this.data_.length - 1);
var v = this.data_[this.data_.length - 1];
this.data_.length--;
this.map_[v.value.id] = undefined;
this.siftDown_(0);
return v;
};
Heap.prototype.updateIfBetter = function(value, score) {
var index = this.map_[value.id];
if (score < this.data_[index].score) {
this.data_[index].score = score;
this.data_[index].value = value;
this.siftUp_(index);
}
};
Heap.prototype.exists = function(value) {
return this.map_[value.id] !== undefined;
};
/**
* Sifts the value at the index down.
* @param {number} index
* @private
*/
Heap.prototype.siftDown_ = function(index) {
var n = this.data_.length;
while (2 * index + 1 < n) {
var i1 = 2*index + 1;
var i2 = 2*index + 2;
var child = i2;
if (i2 >= this.data_.length ||
this.data_[i1].score < this.data_[i2].score) {
child = i1;
}
if (this.data_[child].score < this.data_[index].score) {
this.swap_(child, index);
index = child;
} else {
break;
}
}
};
/**
* Sifts the value at the index up.
* @param {number} index
* @private
*/
Heap.prototype.siftUp_ = function(index) {
while (index > 0) {
var parent = Math.floor((index - 1) / 2);
if (this.data_[parent].score > this.data_[index].score) {
this.swap_(parent, index);
index = parent;
} else {
break;
}
}
};
/**
* Swaps the values at the indices.
* @param {number} i1
* @param {number} i2
* @private
*/
Heap.prototype.swap_ = function(i1, i2) {
var v = this.data_[i1];
this.data_[i1] = this.data_[i2];
this.data_[i2] = v;
this.map_[this.data_[i1].value.id] = i1;
this.map_[this.data_[i2].value.id] = i2;
};
});