-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
126 lines (102 loc) · 3.08 KB
/
index.js
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
const DEFAULT_COMPARE = (a, b) => {
return a > b ? a : b;
};
const DEFAULT_ID_KEY = 'id';
/*
* A minimal implmentation of a priority q inspired by js-priority-queue by Adam Hooper.
*/
class DiQueue {
constructor(data, compareFn, identityKey) {
this.data = data || [];
this.length = this.data.length;
this.compareFn = compareFn || DEFAULT_COMPARE;
this.identityKey = identityKey || DEFAULT_ID_KEY;
if (this.length > 0) {
for (var i = (this.length >> 1) - 1; i >= 0; i--) {
this._down(i);
}
}
}
_down(index) {
var halfLength = this.length >> 1;
var item = this.data[index];
var right, left, best;
while (index < halfLength) {
left = (index << 1) + 1;
right = left + 1;
best = this.data[left];
if (right < this.length && this.compareFn(this.data[right], best) === best) {
left = right;
best = this.data[right];
}
if (this.compareFn(best, item) === best) break;
this.data[index] = best;
index = left;
}
this.data[index] = item;
}
_findElementIndex(value) {
var l = this.data.length;
for (var i = 0; i < l; i++) {
if (this.data[i][this.identityKey] === value) {
return i;
}
}
return -1;
}
_up(index) {
var item = this.data[index];
var parent, current;
while (index > 0) {
parent = (index - 1) >> 1;
current = this.data[parent];
if (this.compareFn(item, current) === item) break;
this.data[index] = current;
index = parent;
}
this.data[index] = item;
}
peekPop() { return this.data[0]; }
peekShift() { return this.data.reduce(this.compareFn); }
pop() {
if (!this.length) return null;
var first = this.data[0];
this.length--;
if (this.length > 0) {
this.data[0] = this.data[this.length];
this._down(0);
}
this.data.pop();
return first;
}
push(data) {
this.data.push(data);
this._up(this.length);
this.length++;
}
remove(idValue) {
var index = this._findElementIndex(idValue);
if (index === -1) return;
this.data.splice(index, 1);
this.length--;
}
shift() {
if (!this.length) return null;
var last = this.data.reduce(this.compareFn);
this.length--;
if (this.length > 0) this.data.splice(this.data.indexOf(last), 1);
return last;
}
update(idValue, updatedItem) {
var index = this._findElementIndex(idValue);
if (index === -1) { this.push(updatedItem); return; }
var prevItem = this.data[index];
this.data[index] = updatedItem;
if (this.compareFn(prevItem, updatedItem) === updatedItem) {
this._up(index);
} else {
this._down(index);
}
}
}
module.exports = DiQueue;