list-toolkit 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/cjs/heap/min-heap.js +21 -51
- package/cjs/meta-utils.js +1 -1
- package/cjs/tree/splay-tree.js +362 -0
- package/package.json +5 -5
- package/src/heap/min-heap.js +21 -52
- package/src/meta-utils.js +1 -1
- package/src/tree/splay-tree.js +378 -0
package/README.md
CHANGED
|
@@ -102,7 +102,7 @@ const john = new Person('John'),
|
|
|
102
102
|
const people = List.from([john, jane, jim, jill]);
|
|
103
103
|
|
|
104
104
|
// iterator over the list manually:
|
|
105
|
-
for (let node = people.front; node !== people; node = node[
|
|
105
|
+
for (let node = people.front; node !== people; node = node[people.nextName]) {
|
|
106
106
|
console.log(node.name); // John, Jane, Jim, Jill
|
|
107
107
|
}
|
|
108
108
|
// yes, the link names are customizable, can be strings or symbols, for example:
|
|
@@ -146,6 +146,7 @@ BSD 3-Clause "New" or "Revised" License. See the LICENSE file for details.
|
|
|
146
146
|
|
|
147
147
|
## Release History
|
|
148
148
|
|
|
149
|
+
* 2.1.0 *Added splay tree. Updated deps.*
|
|
149
150
|
* 2.0.0 *New major release.*
|
|
150
151
|
* 1.0.1 *Fixed exports. Added more methods to `MinHeap`.*
|
|
151
152
|
* 1.0.1 *Initial release.*
|
package/cjs/heap/min-heap.js
CHANGED
|
@@ -27,17 +27,10 @@ const down = (array, i, less = defaultLess, n = array.length) => {
|
|
|
27
27
|
for (;;) {
|
|
28
28
|
const l = (i << 1) + 1;
|
|
29
29
|
if (l >= n) break;
|
|
30
|
-
|
|
30
|
+
const r = l + 1,
|
|
31
|
+
c = r < n && less(array[r], array[l]) ? r : l,
|
|
32
|
+
iValue = array[i],
|
|
31
33
|
cValue = array[c];
|
|
32
|
-
const r = c + 1;
|
|
33
|
-
if (r < n) {
|
|
34
|
-
const rValue = array[r];
|
|
35
|
-
if (less(rValue, cValue)) {
|
|
36
|
-
c = r;
|
|
37
|
-
cValue = rValue;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
const iValue = array[i];
|
|
41
34
|
if (!less(cValue, iValue)) break;
|
|
42
35
|
array[i] = cValue;
|
|
43
36
|
array[c] = iValue;
|
|
@@ -48,6 +41,10 @@ const down = (array, i, less = defaultLess, n = array.length) => {
|
|
|
48
41
|
class MinHeap {
|
|
49
42
|
constructor(options, ...args) {
|
|
50
43
|
(0, _metaUtils.copyOptions)(this, MinHeap.defaults, options);
|
|
44
|
+
if (typeof this.compare == 'function') {
|
|
45
|
+
this.less = (a, b) => this.compare(a, b) < 0;
|
|
46
|
+
this.equal = (a, b) => !this.compare(a, b);
|
|
47
|
+
}
|
|
51
48
|
this.array = [];
|
|
52
49
|
this.merge(...args);
|
|
53
50
|
}
|
|
@@ -78,17 +75,10 @@ class MinHeap {
|
|
|
78
75
|
for (let i = 0;;) {
|
|
79
76
|
const l = (i << 1) + 1;
|
|
80
77
|
if (l >= n) break;
|
|
81
|
-
|
|
78
|
+
const r = l + 1,
|
|
79
|
+
c = r < n && this.less(this.array[r], this.array[l]) ? r : l,
|
|
80
|
+
iValue = this.array[i],
|
|
82
81
|
cValue = this.array[c];
|
|
83
|
-
const r = c + 1;
|
|
84
|
-
if (r < n) {
|
|
85
|
-
const rValue = this.array[r];
|
|
86
|
-
if (this.less(rValue, cValue)) {
|
|
87
|
-
c = r;
|
|
88
|
-
cValue = rValue;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
const iValue = this.array[i];
|
|
92
82
|
if (!this.less(cValue, iValue)) break;
|
|
93
83
|
this.array[i] = cValue;
|
|
94
84
|
this.array[c] = iValue;
|
|
@@ -120,17 +110,10 @@ class MinHeap {
|
|
|
120
110
|
for (let i = 0;;) {
|
|
121
111
|
const l = (i << 1) + 1;
|
|
122
112
|
if (l >= n) break;
|
|
123
|
-
|
|
113
|
+
const r = l + 1,
|
|
114
|
+
c = r < n && this.less(this.array[r], this.array[l]) ? r : l,
|
|
115
|
+
iValue = this.array[i],
|
|
124
116
|
cValue = this.array[c];
|
|
125
|
-
const r = c + 1;
|
|
126
|
-
if (r < n) {
|
|
127
|
-
const rValue = this.array[r];
|
|
128
|
-
if (this.less(rValue, cValue)) {
|
|
129
|
-
c = r;
|
|
130
|
-
cValue = rValue;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
const iValue = this.array[i];
|
|
134
117
|
if (!this.less(cValue, iValue)) break;
|
|
135
118
|
this.array[i] = cValue;
|
|
136
119
|
this.array[c] = iValue;
|
|
@@ -147,17 +130,10 @@ class MinHeap {
|
|
|
147
130
|
for (let i = 0;;) {
|
|
148
131
|
const l = (i << 1) + 1;
|
|
149
132
|
if (l >= n) break;
|
|
150
|
-
|
|
133
|
+
const r = l + 1,
|
|
134
|
+
c = r < n && this.less(this.array[r], this.array[l]) ? r : l,
|
|
135
|
+
iValue = this.array[i],
|
|
151
136
|
cValue = this.array[c];
|
|
152
|
-
const r = c + 1;
|
|
153
|
-
if (r < n) {
|
|
154
|
-
const rValue = this.array[r];
|
|
155
|
-
if (this.less(rValue, cValue)) {
|
|
156
|
-
c = r;
|
|
157
|
-
cValue = rValue;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
const iValue = this.array[i];
|
|
161
137
|
if (!this.less(cValue, iValue)) break;
|
|
162
138
|
this.array[i] = cValue;
|
|
163
139
|
this.array[c] = iValue;
|
|
@@ -230,17 +206,10 @@ class MinHeap {
|
|
|
230
206
|
for (let i = j;;) {
|
|
231
207
|
const l = (i << 1) + 1;
|
|
232
208
|
if (l >= n) break;
|
|
233
|
-
|
|
209
|
+
const r = l + 1,
|
|
210
|
+
c = r < n && less(array[r], array[l]) ? r : l,
|
|
211
|
+
iValue = array[i],
|
|
234
212
|
cValue = array[c];
|
|
235
|
-
const r = c + 1;
|
|
236
|
-
if (r < n) {
|
|
237
|
-
const rValue = array[r];
|
|
238
|
-
if (less(rValue, cValue)) {
|
|
239
|
-
c = r;
|
|
240
|
-
cValue = rValue;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
const iValue = array[i];
|
|
244
213
|
if (!less(cValue, iValue)) break;
|
|
245
214
|
array[i] = cValue;
|
|
246
215
|
array[c] = iValue;
|
|
@@ -323,6 +292,7 @@ class MinHeap {
|
|
|
323
292
|
exports.MinHeap = MinHeap;
|
|
324
293
|
MinHeap.defaults = {
|
|
325
294
|
less: defaultLess,
|
|
326
|
-
equal: defaultEqual
|
|
295
|
+
equal: defaultEqual,
|
|
296
|
+
compare: null
|
|
327
297
|
};
|
|
328
298
|
var _default = exports.default = MinHeap;
|
package/cjs/meta-utils.js
CHANGED
|
@@ -119,7 +119,7 @@ exports.addAlias = addAlias;
|
|
|
119
119
|
const addAliases = (object, dict, force) => copyDescriptors(object, object, dict, force);
|
|
120
120
|
exports.addAliases = addAliases;
|
|
121
121
|
const augmentIterator = iterator => {
|
|
122
|
-
if (!
|
|
122
|
+
if (!iterator.hasOwnProperty(Symbol.iterator)) {
|
|
123
123
|
iterator[Symbol.iterator] = function () {
|
|
124
124
|
return this;
|
|
125
125
|
};
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.SplayTreeNode = exports.SplayTree = void 0;
|
|
7
|
+
var _metaUtils = require("../meta-utils.js");
|
|
8
|
+
const defaultLess = (a, b) => a < b;
|
|
9
|
+
const zig = tree => {
|
|
10
|
+
const newTree = tree.left,
|
|
11
|
+
parent = newTree.parent = tree.parent;
|
|
12
|
+
if (parent) {
|
|
13
|
+
if (parent.left === tree) parent.left = newTree;else parent.right = newTree;
|
|
14
|
+
}
|
|
15
|
+
tree.parent = newTree;
|
|
16
|
+
const child = tree.left = newTree.right;
|
|
17
|
+
if (child) child.parent = tree;
|
|
18
|
+
newTree.right = tree;
|
|
19
|
+
return newTree;
|
|
20
|
+
};
|
|
21
|
+
const zag = tree => {
|
|
22
|
+
const newTree = tree.right,
|
|
23
|
+
parent = newTree.parent = tree.parent;
|
|
24
|
+
if (parent) {
|
|
25
|
+
if (parent.left === tree) parent.left = newTree;else parent.right = newTree;
|
|
26
|
+
}
|
|
27
|
+
tree.parent = newTree;
|
|
28
|
+
const child = tree.right = newTree.left;
|
|
29
|
+
if (child) child.parent = tree;
|
|
30
|
+
newTree.left = tree;
|
|
31
|
+
return newTree;
|
|
32
|
+
};
|
|
33
|
+
const splay = node => {
|
|
34
|
+
while (node.parent) {
|
|
35
|
+
if (!node.parent.parent) {
|
|
36
|
+
node.parent.left === node ? zig(node.parent) : zag(node.parent);
|
|
37
|
+
} else if (node.parent.left === node && node.parent.parent.left === node.parent) {
|
|
38
|
+
zig(node.parent.parent);
|
|
39
|
+
zig(node.parent);
|
|
40
|
+
} else if (node.parent.right === node && node.parent.parent.right === node.parent) {
|
|
41
|
+
zag(node.parent.parent);
|
|
42
|
+
zag(node.parent);
|
|
43
|
+
} else if (node.parent.left === node && node.parent.parent.right === node.parent) {
|
|
44
|
+
zig(node.parent);
|
|
45
|
+
zag(node.parent);
|
|
46
|
+
} else {
|
|
47
|
+
zag(node.parent);
|
|
48
|
+
zig(node.parent);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return node;
|
|
52
|
+
};
|
|
53
|
+
const count = tree => tree ? count(tree.left) + count(tree.right) + 1 : 0;
|
|
54
|
+
class SplayTreeNode {
|
|
55
|
+
constructor(value) {
|
|
56
|
+
this.left = this.right = this.parent = null;
|
|
57
|
+
this.value = value;
|
|
58
|
+
}
|
|
59
|
+
getMin() {
|
|
60
|
+
let z = this;
|
|
61
|
+
while (z.left) z = z.left;
|
|
62
|
+
return z;
|
|
63
|
+
}
|
|
64
|
+
getMax() {
|
|
65
|
+
let z = this;
|
|
66
|
+
while (z.right) z = z.right;
|
|
67
|
+
return z;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.SplayTreeNode = SplayTreeNode;
|
|
71
|
+
class SplayTree {
|
|
72
|
+
constructor(options) {
|
|
73
|
+
(0, _metaUtils.copyOptions)(this, SplayTree.defaults, options);
|
|
74
|
+
if (typeof this.compare == 'function') {
|
|
75
|
+
this.less = (a, b) => this.compare(a, b) < 0;
|
|
76
|
+
this.find = this.findWithCompare;
|
|
77
|
+
this.insert = this.insertWithCompare;
|
|
78
|
+
this.splitMaxTree = this.splitMaxTreeWithCompare;
|
|
79
|
+
}
|
|
80
|
+
this.root = null;
|
|
81
|
+
this.size = 0;
|
|
82
|
+
}
|
|
83
|
+
get isEmpty() {
|
|
84
|
+
return !this.root;
|
|
85
|
+
}
|
|
86
|
+
get length() {
|
|
87
|
+
return this.size;
|
|
88
|
+
}
|
|
89
|
+
getMin() {
|
|
90
|
+
return this.root.getMin();
|
|
91
|
+
}
|
|
92
|
+
getMax() {
|
|
93
|
+
return this.root.getMax();
|
|
94
|
+
}
|
|
95
|
+
find(value) {
|
|
96
|
+
for (let z = this.root; z;) {
|
|
97
|
+
if (this.less(z.value, value)) z = z.right;else if (this.less(value, z.value)) z = z.left;else return z;
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
findWithCompare(value) {
|
|
102
|
+
for (let z = this.root; z;) {
|
|
103
|
+
const cmp = this.compare(value, z.value);
|
|
104
|
+
if (cmp < 0) z = z.left;else if (cmp > 0) z = z.right;else return z;
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
promote(value) {
|
|
109
|
+
const z = this.find(value);
|
|
110
|
+
if (z) {
|
|
111
|
+
this.root = splay(z);
|
|
112
|
+
}
|
|
113
|
+
return z;
|
|
114
|
+
}
|
|
115
|
+
splay(node) {
|
|
116
|
+
this.root = splay(node);
|
|
117
|
+
return this;
|
|
118
|
+
}
|
|
119
|
+
insert(value) {
|
|
120
|
+
let z = this.root,
|
|
121
|
+
parent = null;
|
|
122
|
+
while (z) {
|
|
123
|
+
parent = z;
|
|
124
|
+
if (this.less(z.value, value)) z = z.right;else if (this.less(value, z.value)) z = z.left;else break;
|
|
125
|
+
}
|
|
126
|
+
if (!z) {
|
|
127
|
+
z = new SplayTreeNode(value);
|
|
128
|
+
z.parent = parent;
|
|
129
|
+
if (parent) {
|
|
130
|
+
if (this.less(parent.value, value)) parent.right = z;else parent.left = z;
|
|
131
|
+
}
|
|
132
|
+
++this.size;
|
|
133
|
+
}
|
|
134
|
+
this.root = splay(z);
|
|
135
|
+
return this;
|
|
136
|
+
}
|
|
137
|
+
insertWithCompare(value) {
|
|
138
|
+
let z = this.root,
|
|
139
|
+
parent = null;
|
|
140
|
+
while (z) {
|
|
141
|
+
parent = z;
|
|
142
|
+
const cmp = this.compare(value, z.value);
|
|
143
|
+
if (cmp < 0) z = z.left;else if (cmp > 0) z = z.right;else break;
|
|
144
|
+
}
|
|
145
|
+
if (!z) {
|
|
146
|
+
z = new SplayTreeNode(value);
|
|
147
|
+
z.parent = parent;
|
|
148
|
+
if (parent) {
|
|
149
|
+
if (this.compare(parent.value, value) < 0) parent.right = z;else parent.left = z;
|
|
150
|
+
}
|
|
151
|
+
++this.size;
|
|
152
|
+
}
|
|
153
|
+
this.root = splay(z);
|
|
154
|
+
return this;
|
|
155
|
+
}
|
|
156
|
+
remove(value) {
|
|
157
|
+
const z = this.find(value);
|
|
158
|
+
if (!z) return this;
|
|
159
|
+
splay(z);
|
|
160
|
+
this.root = null;
|
|
161
|
+
let maxNode = null;
|
|
162
|
+
if (z.left) {
|
|
163
|
+
z.left.parent = null;
|
|
164
|
+
maxNode = z.left.getMax();
|
|
165
|
+
this.root = splay(maxNode);
|
|
166
|
+
}
|
|
167
|
+
if (z.right) {
|
|
168
|
+
if (maxNode) maxNode.right = z.right;else this.root = z.right;
|
|
169
|
+
z.right.parent = maxNode;
|
|
170
|
+
}
|
|
171
|
+
--this.size;
|
|
172
|
+
return this;
|
|
173
|
+
}
|
|
174
|
+
clear() {
|
|
175
|
+
this.root = null;
|
|
176
|
+
this.size = 0;
|
|
177
|
+
return this;
|
|
178
|
+
}
|
|
179
|
+
splitMaxTree(value) {
|
|
180
|
+
if (!this.root) return new SplayTree(this);
|
|
181
|
+
let z = this.root,
|
|
182
|
+
parent = null,
|
|
183
|
+
right;
|
|
184
|
+
while (z) {
|
|
185
|
+
parent = z;
|
|
186
|
+
if (this.less(z.value, value)) {
|
|
187
|
+
z = z.right;
|
|
188
|
+
right = true;
|
|
189
|
+
} else if (this.less(value, z.value)) {
|
|
190
|
+
z = z.left;
|
|
191
|
+
right = false;
|
|
192
|
+
} else break;
|
|
193
|
+
}
|
|
194
|
+
this.root = splay(z || parent);
|
|
195
|
+
const newTree = new SplayTree(this);
|
|
196
|
+
if (z || right) {
|
|
197
|
+
newTree.root = this.root.right;
|
|
198
|
+
if (newTree.root) {
|
|
199
|
+
newTree.root.parent = null;
|
|
200
|
+
newTree.size = count(newTree.root);
|
|
201
|
+
this.root.right = null;
|
|
202
|
+
this.size -= newTree.size;
|
|
203
|
+
}
|
|
204
|
+
} else {
|
|
205
|
+
newTree.root = this.root;
|
|
206
|
+
newTree.size = this.size;
|
|
207
|
+
this.root = this.root.left;
|
|
208
|
+
if (this.root) {
|
|
209
|
+
this.root.parent = null;
|
|
210
|
+
this.size = count(this.root);
|
|
211
|
+
newTree.root.left = null;
|
|
212
|
+
newTree.size -= this.size;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return newTree;
|
|
216
|
+
}
|
|
217
|
+
splitMaxTreeWithCompare(value) {
|
|
218
|
+
if (!this.root) return new SplayTree(this);
|
|
219
|
+
let z = this.root,
|
|
220
|
+
parent = null,
|
|
221
|
+
right;
|
|
222
|
+
while (z) {
|
|
223
|
+
parent = z;
|
|
224
|
+
const cmp = this.compare(value, z.value);
|
|
225
|
+
if (cmp < 0) {
|
|
226
|
+
z = z.left;
|
|
227
|
+
right = false;
|
|
228
|
+
} else if (cmp > 0) {
|
|
229
|
+
z = z.right;
|
|
230
|
+
right = true;
|
|
231
|
+
} else break;
|
|
232
|
+
}
|
|
233
|
+
this.root = splay(z || parent);
|
|
234
|
+
const newTree = new SplayTree(this);
|
|
235
|
+
if (z || right) {
|
|
236
|
+
newTree.root = this.root.right;
|
|
237
|
+
if (newTree.root) {
|
|
238
|
+
newTree.root.parent = null;
|
|
239
|
+
newTree.size = count(newTree.root);
|
|
240
|
+
this.root.right = null;
|
|
241
|
+
this.size -= newTree.size;
|
|
242
|
+
}
|
|
243
|
+
} else {
|
|
244
|
+
newTree.root = this.root;
|
|
245
|
+
newTree.size = this.size;
|
|
246
|
+
this.root = this.root.left;
|
|
247
|
+
if (this.root) {
|
|
248
|
+
this.root.parent = null;
|
|
249
|
+
this.size = count(this.root);
|
|
250
|
+
newTree.root.left = null;
|
|
251
|
+
newTree.size -= this.size;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return newTree;
|
|
255
|
+
}
|
|
256
|
+
joinMaxTreeUnsafe(tree) {
|
|
257
|
+
if (this.root.right) {
|
|
258
|
+
this.splay(this.getMax());
|
|
259
|
+
}
|
|
260
|
+
this.root.right = tree.root;
|
|
261
|
+
tree.root.parent = this.root;
|
|
262
|
+
this.size += tree.size;
|
|
263
|
+
tree.clear();
|
|
264
|
+
return this;
|
|
265
|
+
}
|
|
266
|
+
join(tree) {
|
|
267
|
+
if (!tree.root) return this;
|
|
268
|
+
if (!this.root) {
|
|
269
|
+
this.root = tree.root;
|
|
270
|
+
this.size = tree.size;
|
|
271
|
+
tree.clear();
|
|
272
|
+
return this;
|
|
273
|
+
}
|
|
274
|
+
const leftMax = this.getMax(),
|
|
275
|
+
rightMin = tree.getMin();
|
|
276
|
+
if (this.less(leftMax.value, rightMin.value)) {
|
|
277
|
+
return this.splay(leftMax).joinMaxTreeUnsafe(tree);
|
|
278
|
+
}
|
|
279
|
+
for (const value of tree) {
|
|
280
|
+
this.insert(value);
|
|
281
|
+
}
|
|
282
|
+
tree.clear();
|
|
283
|
+
return this;
|
|
284
|
+
}
|
|
285
|
+
[Symbol.iterator]() {
|
|
286
|
+
let current = this.root ? this.root.getMin() : null;
|
|
287
|
+
return {
|
|
288
|
+
next: () => {
|
|
289
|
+
if (!current) return {
|
|
290
|
+
done: true
|
|
291
|
+
};
|
|
292
|
+
const last = current;
|
|
293
|
+
if (current.right) {
|
|
294
|
+
current = current.right.getMin();
|
|
295
|
+
} else {
|
|
296
|
+
for (;;) {
|
|
297
|
+
const parent = current.parent;
|
|
298
|
+
if (!parent) {
|
|
299
|
+
current = null;
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
if (parent.left === current) {
|
|
303
|
+
current = parent;
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
current = parent;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return {
|
|
310
|
+
value: last.value
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
getReverseIterator() {
|
|
316
|
+
return {
|
|
317
|
+
[Symbol.iterator]: () => {
|
|
318
|
+
let current = this.root ? this.root.getMax() : null;
|
|
319
|
+
return {
|
|
320
|
+
next: () => {
|
|
321
|
+
if (!current) return {
|
|
322
|
+
done: true
|
|
323
|
+
};
|
|
324
|
+
const last = current;
|
|
325
|
+
if (current.left) {
|
|
326
|
+
current = current.left.getMax();
|
|
327
|
+
} else {
|
|
328
|
+
for (;;) {
|
|
329
|
+
const parent = current.parent;
|
|
330
|
+
if (!parent) {
|
|
331
|
+
current = null;
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
if (parent.right === current) {
|
|
335
|
+
current = parent;
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
current = parent;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return {
|
|
342
|
+
value: last.value
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
static from(values, options) {
|
|
350
|
+
const tree = new SplayTree(options);
|
|
351
|
+
for (const value of values) {
|
|
352
|
+
tree.insert(value);
|
|
353
|
+
}
|
|
354
|
+
return tree;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
exports.SplayTree = SplayTree;
|
|
358
|
+
SplayTree.defaults = {
|
|
359
|
+
less: defaultLess,
|
|
360
|
+
compare: null
|
|
361
|
+
};
|
|
362
|
+
var _default = exports.default = SplayTree;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "list-toolkit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "List-based data structures to organize your objects.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
},
|
|
34
34
|
"homepage": "https://github.com/uhop/list-toolkit#readme",
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@babel/cli": "^7.24.
|
|
37
|
-
"@babel/core": "^7.
|
|
38
|
-
"@babel/preset-env": "^7.
|
|
39
|
-
"tape-six": "^0.9.
|
|
36
|
+
"@babel/cli": "^7.24.8",
|
|
37
|
+
"@babel/core": "^7.25.2",
|
|
38
|
+
"@babel/preset-env": "^7.25.4",
|
|
39
|
+
"tape-six": "^0.9.6"
|
|
40
40
|
},
|
|
41
41
|
"files": [
|
|
42
42
|
"/src",
|
package/src/heap/min-heap.js
CHANGED
|
@@ -26,17 +26,10 @@ const down = (array, i, less = defaultLess, n = array.length) => {
|
|
|
26
26
|
for (;;) {
|
|
27
27
|
const l = (i << 1) + 1;
|
|
28
28
|
if (l >= n) break;
|
|
29
|
-
|
|
29
|
+
const r = l + 1,
|
|
30
|
+
c = r < n && less(array[r], array[l]) ? r : l,
|
|
31
|
+
iValue = array[i],
|
|
30
32
|
cValue = array[c];
|
|
31
|
-
const r = c + 1;
|
|
32
|
-
if (r < n) {
|
|
33
|
-
const rValue = array[r];
|
|
34
|
-
if (less(rValue, cValue)) {
|
|
35
|
-
c = r;
|
|
36
|
-
cValue = rValue;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
const iValue = array[i];
|
|
40
33
|
if (!less(cValue, iValue)) break;
|
|
41
34
|
array[i] = cValue;
|
|
42
35
|
array[c] = iValue;
|
|
@@ -48,6 +41,10 @@ const down = (array, i, less = defaultLess, n = array.length) => {
|
|
|
48
41
|
export class MinHeap {
|
|
49
42
|
constructor(options, ...args) {
|
|
50
43
|
copyOptions(this, MinHeap.defaults, options);
|
|
44
|
+
if (typeof this.compare == 'function') {
|
|
45
|
+
this.less = (a, b) => this.compare(a, b) < 0;
|
|
46
|
+
this.equal = (a, b) => !this.compare(a, b);
|
|
47
|
+
}
|
|
51
48
|
this.array = [];
|
|
52
49
|
this.merge(...args);
|
|
53
50
|
}
|
|
@@ -83,17 +80,10 @@ export class MinHeap {
|
|
|
83
80
|
for (let i = 0; ; ) {
|
|
84
81
|
const l = (i << 1) + 1;
|
|
85
82
|
if (l >= n) break;
|
|
86
|
-
|
|
83
|
+
const r = l + 1,
|
|
84
|
+
c = r < n && this.less(this.array[r], this.array[l]) ? r : l,
|
|
85
|
+
iValue = this.array[i],
|
|
87
86
|
cValue = this.array[c];
|
|
88
|
-
const r = c + 1;
|
|
89
|
-
if (r < n) {
|
|
90
|
-
const rValue = this.array[r];
|
|
91
|
-
if (this.less(rValue, cValue)) {
|
|
92
|
-
c = r;
|
|
93
|
-
cValue = rValue;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
const iValue = this.array[i];
|
|
97
87
|
if (!this.less(cValue, iValue)) break;
|
|
98
88
|
this.array[i] = cValue;
|
|
99
89
|
this.array[c] = iValue;
|
|
@@ -127,17 +117,10 @@ export class MinHeap {
|
|
|
127
117
|
for (let i = 0; ; ) {
|
|
128
118
|
const l = (i << 1) + 1;
|
|
129
119
|
if (l >= n) break;
|
|
130
|
-
|
|
120
|
+
const r = l + 1,
|
|
121
|
+
c = r < n && this.less(this.array[r], this.array[l]) ? r : l,
|
|
122
|
+
iValue = this.array[i],
|
|
131
123
|
cValue = this.array[c];
|
|
132
|
-
const r = c + 1;
|
|
133
|
-
if (r < n) {
|
|
134
|
-
const rValue = this.array[r];
|
|
135
|
-
if (this.less(rValue, cValue)) {
|
|
136
|
-
c = r;
|
|
137
|
-
cValue = rValue;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
const iValue = this.array[i];
|
|
141
124
|
if (!this.less(cValue, iValue)) break;
|
|
142
125
|
this.array[i] = cValue;
|
|
143
126
|
this.array[c] = iValue;
|
|
@@ -155,17 +138,10 @@ export class MinHeap {
|
|
|
155
138
|
for (let i = 0; ; ) {
|
|
156
139
|
const l = (i << 1) + 1;
|
|
157
140
|
if (l >= n) break;
|
|
158
|
-
|
|
141
|
+
const r = l + 1,
|
|
142
|
+
c = r < n && this.less(this.array[r], this.array[l]) ? r : l,
|
|
143
|
+
iValue = this.array[i],
|
|
159
144
|
cValue = this.array[c];
|
|
160
|
-
const r = c + 1;
|
|
161
|
-
if (r < n) {
|
|
162
|
-
const rValue = this.array[r];
|
|
163
|
-
if (this.less(rValue, cValue)) {
|
|
164
|
-
c = r;
|
|
165
|
-
cValue = rValue;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
const iValue = this.array[i];
|
|
169
145
|
if (!this.less(cValue, iValue)) break;
|
|
170
146
|
this.array[i] = cValue;
|
|
171
147
|
this.array[c] = iValue;
|
|
@@ -257,17 +233,10 @@ export class MinHeap {
|
|
|
257
233
|
for (let i = j; ; ) {
|
|
258
234
|
const l = (i << 1) + 1;
|
|
259
235
|
if (l >= n) break;
|
|
260
|
-
|
|
236
|
+
const r = l + 1,
|
|
237
|
+
c = r < n && less(array[r], array[l]) ? r : l,
|
|
238
|
+
iValue = array[i],
|
|
261
239
|
cValue = array[c];
|
|
262
|
-
const r = c + 1;
|
|
263
|
-
if (r < n) {
|
|
264
|
-
const rValue = array[r];
|
|
265
|
-
if (less(rValue, cValue)) {
|
|
266
|
-
c = r;
|
|
267
|
-
cValue = rValue;
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
const iValue = array[i];
|
|
271
240
|
if (!less(cValue, iValue)) break;
|
|
272
241
|
array[i] = cValue;
|
|
273
242
|
array[c] = iValue;
|
|
@@ -321,7 +290,7 @@ export class MinHeap {
|
|
|
321
290
|
const last = heapArray.length - 1;
|
|
322
291
|
if (index !== last) {
|
|
323
292
|
const item = heapArray[index],
|
|
324
|
-
newItem = heapArray[index] = heapArray.pop();
|
|
293
|
+
newItem = (heapArray[index] = heapArray.pop());
|
|
325
294
|
return MinHeap.updateByIndex(heapArray, index, less(newItem, item), less);
|
|
326
295
|
}
|
|
327
296
|
heapArray.pop();
|
|
@@ -360,6 +329,6 @@ export class MinHeap {
|
|
|
360
329
|
}
|
|
361
330
|
}
|
|
362
331
|
|
|
363
|
-
MinHeap.defaults = {less: defaultLess, equal: defaultEqual};
|
|
332
|
+
MinHeap.defaults = {less: defaultLess, equal: defaultEqual, compare: null};
|
|
364
333
|
|
|
365
334
|
export default MinHeap;
|
package/src/meta-utils.js
CHANGED
|
@@ -100,7 +100,7 @@ export const addAlias = (object, name, aliases, force) => addDescriptor(object,
|
|
|
100
100
|
export const addAliases = (object, dict, force) => copyDescriptors(object, object, dict, force);
|
|
101
101
|
|
|
102
102
|
export const augmentIterator = iterator => {
|
|
103
|
-
if (!
|
|
103
|
+
if (!iterator.hasOwnProperty(Symbol.iterator)) {
|
|
104
104
|
iterator[Symbol.iterator] = function () {
|
|
105
105
|
return this;
|
|
106
106
|
};
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import {copyOptions} from '../meta-utils.js';
|
|
4
|
+
|
|
5
|
+
const defaultLess = (a, b) => a < b;
|
|
6
|
+
|
|
7
|
+
const zig = tree => {
|
|
8
|
+
const newTree = tree.left,
|
|
9
|
+
parent = (newTree.parent = tree.parent);
|
|
10
|
+
if (parent) {
|
|
11
|
+
if (parent.left === tree) parent.left = newTree;
|
|
12
|
+
else parent.right = newTree;
|
|
13
|
+
}
|
|
14
|
+
tree.parent = newTree;
|
|
15
|
+
const child = (tree.left = newTree.right);
|
|
16
|
+
if (child) child.parent = tree;
|
|
17
|
+
newTree.right = tree;
|
|
18
|
+
return newTree;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const zag = tree => {
|
|
22
|
+
const newTree = tree.right,
|
|
23
|
+
parent = (newTree.parent = tree.parent);
|
|
24
|
+
if (parent) {
|
|
25
|
+
if (parent.left === tree) parent.left = newTree;
|
|
26
|
+
else parent.right = newTree;
|
|
27
|
+
}
|
|
28
|
+
tree.parent = newTree;
|
|
29
|
+
const child = (tree.right = newTree.left);
|
|
30
|
+
if (child) child.parent = tree;
|
|
31
|
+
newTree.left = tree;
|
|
32
|
+
return newTree;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const splay = node => {
|
|
36
|
+
while (node.parent) {
|
|
37
|
+
if (!node.parent.parent) {
|
|
38
|
+
node.parent.left === node ? zig(node.parent) : zag(node.parent);
|
|
39
|
+
} else if (node.parent.left === node && node.parent.parent.left === node.parent) {
|
|
40
|
+
zig(node.parent.parent);
|
|
41
|
+
zig(node.parent);
|
|
42
|
+
} else if (node.parent.right === node && node.parent.parent.right === node.parent) {
|
|
43
|
+
zag(node.parent.parent);
|
|
44
|
+
zag(node.parent);
|
|
45
|
+
} else if (node.parent.left === node && node.parent.parent.right === node.parent) {
|
|
46
|
+
zig(node.parent);
|
|
47
|
+
zag(node.parent);
|
|
48
|
+
} else {
|
|
49
|
+
zag(node.parent);
|
|
50
|
+
zig(node.parent);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return node;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const count = tree => (tree ? count(tree.left) + count(tree.right) + 1 : 0);
|
|
57
|
+
|
|
58
|
+
export class SplayTreeNode {
|
|
59
|
+
constructor(value) {
|
|
60
|
+
this.left = this.right = this.parent = null;
|
|
61
|
+
this.value = value;
|
|
62
|
+
}
|
|
63
|
+
getMin() {
|
|
64
|
+
let z = this;
|
|
65
|
+
while (z.left) z = z.left;
|
|
66
|
+
return z;
|
|
67
|
+
}
|
|
68
|
+
getMax() {
|
|
69
|
+
let z = this;
|
|
70
|
+
while (z.right) z = z.right;
|
|
71
|
+
return z;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export class SplayTree {
|
|
76
|
+
constructor(options) {
|
|
77
|
+
copyOptions(this, SplayTree.defaults, options);
|
|
78
|
+
if (typeof this.compare == 'function') {
|
|
79
|
+
this.less = (a, b) => this.compare(a, b) < 0;
|
|
80
|
+
this.find = this.findWithCompare;
|
|
81
|
+
this.insert = this.insertWithCompare;
|
|
82
|
+
this.splitMaxTree = this.splitMaxTreeWithCompare;
|
|
83
|
+
}
|
|
84
|
+
this.root = null;
|
|
85
|
+
this.size = 0;
|
|
86
|
+
}
|
|
87
|
+
get isEmpty() {
|
|
88
|
+
return !this.root;
|
|
89
|
+
}
|
|
90
|
+
get length() {
|
|
91
|
+
return this.size;
|
|
92
|
+
}
|
|
93
|
+
getMin() {
|
|
94
|
+
return this.root.getMin();
|
|
95
|
+
}
|
|
96
|
+
getMax() {
|
|
97
|
+
return this.root.getMax();
|
|
98
|
+
}
|
|
99
|
+
find(value) {
|
|
100
|
+
for (let z = this.root; z; ) {
|
|
101
|
+
if (this.less(z.value, value)) z = z.right;
|
|
102
|
+
else if (this.less(value, z.value)) z = z.left;
|
|
103
|
+
else return z;
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
findWithCompare(value) {
|
|
108
|
+
for (let z = this.root; z; ) {
|
|
109
|
+
const cmp = this.compare(value, z.value);
|
|
110
|
+
if (cmp < 0) z = z.left;
|
|
111
|
+
else if (cmp > 0) z = z.right;
|
|
112
|
+
else return z;
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
promote(value) {
|
|
117
|
+
const z = this.find(value);
|
|
118
|
+
if (z) {
|
|
119
|
+
this.root = splay(z);
|
|
120
|
+
}
|
|
121
|
+
return z;
|
|
122
|
+
}
|
|
123
|
+
splay(node) {
|
|
124
|
+
this.root = splay(node);
|
|
125
|
+
return this;
|
|
126
|
+
}
|
|
127
|
+
insert(value) {
|
|
128
|
+
let z = this.root,
|
|
129
|
+
parent = null;
|
|
130
|
+
while (z) {
|
|
131
|
+
parent = z;
|
|
132
|
+
if (this.less(z.value, value)) z = z.right;
|
|
133
|
+
else if (this.less(value, z.value)) z = z.left;
|
|
134
|
+
else break;
|
|
135
|
+
}
|
|
136
|
+
if (!z) {
|
|
137
|
+
z = new SplayTreeNode(value);
|
|
138
|
+
z.parent = parent;
|
|
139
|
+
if (parent) {
|
|
140
|
+
if (this.less(parent.value, value)) parent.right = z;
|
|
141
|
+
else parent.left = z;
|
|
142
|
+
}
|
|
143
|
+
++this.size;
|
|
144
|
+
}
|
|
145
|
+
this.root = splay(z);
|
|
146
|
+
return this;
|
|
147
|
+
}
|
|
148
|
+
insertWithCompare(value) {
|
|
149
|
+
let z = this.root,
|
|
150
|
+
parent = null;
|
|
151
|
+
while (z) {
|
|
152
|
+
parent = z;
|
|
153
|
+
const cmp = this.compare(value, z.value);
|
|
154
|
+
if (cmp < 0) z = z.left;
|
|
155
|
+
else if (cmp > 0) z = z.right;
|
|
156
|
+
else break;
|
|
157
|
+
}
|
|
158
|
+
if (!z) {
|
|
159
|
+
z = new SplayTreeNode(value);
|
|
160
|
+
z.parent = parent;
|
|
161
|
+
if (parent) {
|
|
162
|
+
if (this.compare(parent.value, value) < 0) parent.right = z;
|
|
163
|
+
else parent.left = z;
|
|
164
|
+
}
|
|
165
|
+
++this.size;
|
|
166
|
+
}
|
|
167
|
+
this.root = splay(z);
|
|
168
|
+
return this;
|
|
169
|
+
}
|
|
170
|
+
remove(value) {
|
|
171
|
+
const z = this.find(value);
|
|
172
|
+
if (!z) return this;
|
|
173
|
+
|
|
174
|
+
splay(z);
|
|
175
|
+
this.root = null;
|
|
176
|
+
|
|
177
|
+
let maxNode = null;
|
|
178
|
+
if (z.left) {
|
|
179
|
+
z.left.parent = null;
|
|
180
|
+
maxNode = z.left.getMax();
|
|
181
|
+
this.root = splay(maxNode);
|
|
182
|
+
}
|
|
183
|
+
if (z.right) {
|
|
184
|
+
if (maxNode) maxNode.right = z.right;
|
|
185
|
+
else this.root = z.right;
|
|
186
|
+
z.right.parent = maxNode;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
--this.size;
|
|
190
|
+
|
|
191
|
+
return this;
|
|
192
|
+
}
|
|
193
|
+
clear() {
|
|
194
|
+
this.root = null;
|
|
195
|
+
this.size = 0;
|
|
196
|
+
return this;
|
|
197
|
+
}
|
|
198
|
+
splitMaxTree(value) {
|
|
199
|
+
if (!this.root) return new SplayTree(this);
|
|
200
|
+
let z = this.root,
|
|
201
|
+
parent = null,
|
|
202
|
+
right;
|
|
203
|
+
while (z) {
|
|
204
|
+
parent = z;
|
|
205
|
+
if (this.less(z.value, value)) {
|
|
206
|
+
z = z.right;
|
|
207
|
+
right = true;
|
|
208
|
+
} else if (this.less(value, z.value)) {
|
|
209
|
+
z = z.left;
|
|
210
|
+
right = false;
|
|
211
|
+
} else break;
|
|
212
|
+
}
|
|
213
|
+
this.root = splay(z || parent);
|
|
214
|
+
|
|
215
|
+
const newTree = new SplayTree(this);
|
|
216
|
+
if (z || right) {
|
|
217
|
+
newTree.root = this.root.right;
|
|
218
|
+
if (newTree.root) {
|
|
219
|
+
newTree.root.parent = null;
|
|
220
|
+
newTree.size = count(newTree.root);
|
|
221
|
+
this.root.right = null;
|
|
222
|
+
this.size -= newTree.size;
|
|
223
|
+
}
|
|
224
|
+
} else {
|
|
225
|
+
newTree.root = this.root;
|
|
226
|
+
newTree.size = this.size;
|
|
227
|
+
this.root = this.root.left;
|
|
228
|
+
if (this.root) {
|
|
229
|
+
this.root.parent = null;
|
|
230
|
+
this.size = count(this.root);
|
|
231
|
+
newTree.root.left = null;
|
|
232
|
+
newTree.size -= this.size;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return newTree;
|
|
236
|
+
}
|
|
237
|
+
splitMaxTreeWithCompare(value) {
|
|
238
|
+
if (!this.root) return new SplayTree(this);
|
|
239
|
+
let z = this.root,
|
|
240
|
+
parent = null,
|
|
241
|
+
right;
|
|
242
|
+
while (z) {
|
|
243
|
+
parent = z;
|
|
244
|
+
const cmp = this.compare(value, z.value);
|
|
245
|
+
if (cmp < 0) {
|
|
246
|
+
z = z.left;
|
|
247
|
+
right = false;
|
|
248
|
+
} else if (cmp > 0) {
|
|
249
|
+
z = z.right;
|
|
250
|
+
right = true;
|
|
251
|
+
} else break;
|
|
252
|
+
}
|
|
253
|
+
this.root = splay(z || parent);
|
|
254
|
+
|
|
255
|
+
const newTree = new SplayTree(this);
|
|
256
|
+
if (z || right) {
|
|
257
|
+
newTree.root = this.root.right;
|
|
258
|
+
if (newTree.root) {
|
|
259
|
+
newTree.root.parent = null;
|
|
260
|
+
newTree.size = count(newTree.root);
|
|
261
|
+
this.root.right = null;
|
|
262
|
+
this.size -= newTree.size;
|
|
263
|
+
}
|
|
264
|
+
} else {
|
|
265
|
+
newTree.root = this.root;
|
|
266
|
+
newTree.size = this.size;
|
|
267
|
+
this.root = this.root.left;
|
|
268
|
+
if (this.root) {
|
|
269
|
+
this.root.parent = null;
|
|
270
|
+
this.size = count(this.root);
|
|
271
|
+
newTree.root.left = null;
|
|
272
|
+
newTree.size -= this.size;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return newTree;
|
|
276
|
+
}
|
|
277
|
+
joinMaxTreeUnsafe(tree) {
|
|
278
|
+
if (this.root.right) {
|
|
279
|
+
this.splay(this.getMax());
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
this.root.right = tree.root;
|
|
283
|
+
tree.root.parent = this.root;
|
|
284
|
+
this.size += tree.size;
|
|
285
|
+
|
|
286
|
+
tree.clear();
|
|
287
|
+
|
|
288
|
+
return this;
|
|
289
|
+
}
|
|
290
|
+
join(tree) {
|
|
291
|
+
if (!tree.root) return this;
|
|
292
|
+
if (!this.root) {
|
|
293
|
+
this.root = tree.root;
|
|
294
|
+
this.size = tree.size;
|
|
295
|
+
tree.clear();
|
|
296
|
+
return this;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const leftMax = this.getMax(), rightMin = tree.getMin();
|
|
300
|
+
if (this.less(leftMax.value, rightMin.value)) {
|
|
301
|
+
return this.splay(leftMax).joinMaxTreeUnsafe(tree);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
for (const value of tree) {
|
|
305
|
+
this.insert(value);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
tree.clear();
|
|
309
|
+
return this;
|
|
310
|
+
}
|
|
311
|
+
[Symbol.iterator]() {
|
|
312
|
+
let current = this.root ? this.root.getMin() : null;
|
|
313
|
+
return {
|
|
314
|
+
next: () => {
|
|
315
|
+
if (!current) return {done: true};
|
|
316
|
+
const last = current;
|
|
317
|
+
if (current.right) {
|
|
318
|
+
current = current.right.getMin();
|
|
319
|
+
} else {
|
|
320
|
+
for (;;) {
|
|
321
|
+
const parent = current.parent;
|
|
322
|
+
if (!parent) {
|
|
323
|
+
current = null;
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
if (parent.left === current) {
|
|
327
|
+
current = parent;
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
current = parent;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return {value: last.value};
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
getReverseIterator() {
|
|
338
|
+
return {
|
|
339
|
+
[Symbol.iterator]: () => {
|
|
340
|
+
let current = this.root ? this.root.getMax() : null;
|
|
341
|
+
return {
|
|
342
|
+
next: () => {
|
|
343
|
+
if (!current) return {done: true};
|
|
344
|
+
const last = current;
|
|
345
|
+
if (current.left) {
|
|
346
|
+
current = current.left.getMax();
|
|
347
|
+
} else {
|
|
348
|
+
for (;;) {
|
|
349
|
+
const parent = current.parent;
|
|
350
|
+
if (!parent) {
|
|
351
|
+
current = null;
|
|
352
|
+
break;
|
|
353
|
+
}
|
|
354
|
+
if (parent.right === current) {
|
|
355
|
+
current = parent;
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
current = parent;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return {value: last.value};
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
static from(values, options) {
|
|
368
|
+
const tree = new SplayTree(options);
|
|
369
|
+
for (const value of values) {
|
|
370
|
+
tree.insert(value);
|
|
371
|
+
}
|
|
372
|
+
return tree;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
SplayTree.defaults = {less: defaultLess, compare: null};
|
|
377
|
+
|
|
378
|
+
export default SplayTree;
|