articulated 1.3.0 → 1.3.2

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.
@@ -1,495 +1,348 @@
1
1
  "use strict";
2
- module.exports = createRBTree;
3
2
  // Modified from https://github.com/mikolalysenko/functional-red-black-tree/blob/master/rbtree.js
4
3
  // which is MIT Licensed, Copyright (c) 2013 Mikola Lysenko.
5
- var RED = 0;
6
- var BLACK = 1;
7
- function RBNode(color, key, value, left, right) {
8
- this._color = color;
9
- this.key = key;
10
- this.value = value;
11
- this.left = left;
12
- this.right = right;
4
+ //
5
+ // External types modified from
6
+ // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/functional-red-black-tree/functional-red-black-tree-tests.ts
7
+ // which is MIT Licensed.
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.RedBlackTreeIterator = exports.RedBlackTree = exports.RBNode = void 0;
10
+ const RED = 0;
11
+ const BLACK = 1;
12
+ /**
13
+ * @private Only exported for tests.
14
+ */
15
+ class RBNode {
16
+ constructor(color,
17
+ /** The key associated with the node. */
18
+ key,
19
+ /** The value associated with the node. */
20
+ value,
21
+ /** The left subtree of the node. */
22
+ left,
23
+ /** The right subtree of the node. */
24
+ right) {
25
+ this.color = color;
26
+ this.key = key;
27
+ this.value = value;
28
+ this.left = left;
29
+ this.right = right;
30
+ }
13
31
  }
32
+ exports.RBNode = RBNode;
14
33
  function cloneNode(node) {
15
- return new RBNode(node._color, node.key, node.value, node.left, node.right);
34
+ return new RBNode(node.color, node.key, node.value, node.left, node.right);
16
35
  }
17
36
  function repaint(color, node) {
18
37
  return new RBNode(color, node.key, node.value, node.left, node.right);
19
38
  }
20
- function RedBlackTree(compare, root) {
21
- this._compare = compare;
22
- this.root = root;
23
- }
24
- var proto = RedBlackTree.prototype;
25
- // Object.defineProperty(proto, "keys", {
26
- // get: function () {
27
- // var result = [];
28
- // this.forEach(function (k, v) {
29
- // result.push(k);
30
- // });
31
- // return result;
32
- // },
33
- // });
34
- // Object.defineProperty(proto, "values", {
35
- // get: function () {
36
- // var result = [];
37
- // this.forEach(function (k, v) {
38
- // result.push(v);
39
- // });
40
- // return result;
41
- // },
42
- // });
43
- //Set a key-value pair
44
- proto.set = function (key, value) {
45
- var cmp = this._compare;
46
- //Find point to insert/replace node
47
- var n = this.root;
48
- var n_stack = [];
49
- var d_stack = [];
50
- let d = 0;
51
- while (n) {
52
- d = cmp(key, n.key);
53
- n_stack.push(n);
54
- d_stack.push(d);
55
- // If the keys are equivalent, skip straight to the replace = true case.
56
- if (d === 0)
57
- break;
58
- else if (d < 0) {
59
- n = n.left;
60
- }
61
- else {
62
- n = n.right;
63
- }
39
+ /** Represents a functional red-black tree. */
40
+ class RedBlackTree {
41
+ constructor(compare, root) {
42
+ this.compare = compare;
43
+ this.root = root;
64
44
  }
65
- const replace = d === 0 && n_stack.length > 0;
66
- if (replace) {
67
- // The last node in the n_stack has key equivalent to `key`.
68
- // Replace its entry without changing the tree structure.
69
- const lastN = n_stack[n_stack.length - 1];
70
- if (lastN.key === key && lastN.value === value)
71
- return this;
72
- n_stack[n_stack.length - 1] = new RBNode(lastN._color, key, value, lastN.left, lastN.right);
45
+ /**
46
+ * Creates an empty red-black tree.
47
+ *
48
+ * @param compare Comparison function, same semantics as array.sort().
49
+ * @returns An empty tree ordered by `compare`.
50
+ */
51
+ static new(compare) {
52
+ return new RedBlackTree(compare, null);
73
53
  }
74
- else {
75
- n_stack.push(new RBNode(RED, key, value, null, null));
76
- }
77
- //Rebuild path to leaf node
78
- for (var s = n_stack.length - 2; s >= 0; --s) {
79
- var n = n_stack[s];
80
- if (d_stack[s] <= 0) {
81
- n_stack[s] = new RBNode(n._color, n.key, n.value, n_stack[s + 1], n.right);
54
+ /**
55
+ * Creates a new tree with `key` set to `value`, overwriting any
56
+ * existing value.
57
+ *
58
+ * @param key The key of the item to insert.
59
+ * @param value The value of the item to insert.
60
+ * @returns A new tree with `key` set to `value`.
61
+ */
62
+ set(key, value) {
63
+ const cmp = this.compare;
64
+ //Find point to insert/replace node
65
+ let n = this.root;
66
+ const n_stack = [];
67
+ const d_stack = [];
68
+ let d = 0;
69
+ while (n) {
70
+ d = cmp(key, n.key);
71
+ n_stack.push(n);
72
+ d_stack.push(d);
73
+ // If the keys are equivalent, skip straight to the replace = true case.
74
+ if (d === 0)
75
+ break;
76
+ else if (d < 0) {
77
+ n = n.left;
78
+ }
79
+ else {
80
+ n = n.right;
81
+ }
82
82
  }
83
- else {
84
- n_stack[s] = new RBNode(n._color, n.key, n.value, n.left, n_stack[s + 1]);
83
+ const replace = d === 0 && n_stack.length > 0;
84
+ if (replace) {
85
+ // The last node in the n_stack has key equivalent to `key`.
86
+ // Replace its entry without changing the tree structure.
87
+ const lastN = n_stack[n_stack.length - 1];
88
+ if (lastN.key === key && lastN.value === value)
89
+ return this;
90
+ n_stack[n_stack.length - 1] = new RBNode(lastN.color, key, value, lastN.left, lastN.right);
85
91
  }
86
- }
87
- if (replace)
88
- return new RedBlackTree(cmp, n_stack[0]);
89
- //Rebalance tree using rotations
90
- //console.log("start insert", key, d_stack)
91
- for (var s = n_stack.length - 1; s > 1; --s) {
92
- var p = n_stack[s - 1];
93
- var n = n_stack[s];
94
- if (p._color === BLACK || n._color === BLACK) {
95
- break;
92
+ else {
93
+ n_stack.push(new RBNode(RED, key, value, null, null));
96
94
  }
97
- var pp = n_stack[s - 2];
98
- if (pp.left === p) {
99
- if (p.left === n) {
100
- var y = pp.right;
101
- if (y && y._color === RED) {
102
- //console.log("LLr")
103
- p._color = BLACK;
104
- pp.right = repaint(BLACK, y);
105
- pp._color = RED;
106
- s -= 1;
107
- }
108
- else {
109
- //console.log("LLb")
110
- pp._color = RED;
111
- pp.left = p.right;
112
- p._color = BLACK;
113
- p.right = pp;
114
- n_stack[s - 2] = p;
115
- n_stack[s - 1] = n;
116
- if (s >= 3) {
117
- var ppp = n_stack[s - 3];
118
- if (ppp.left === pp) {
119
- ppp.left = p;
120
- }
121
- else {
122
- ppp.right = p;
123
- }
124
- }
125
- break;
126
- }
95
+ //Rebuild path to leaf node
96
+ let s;
97
+ for (s = n_stack.length - 2; s >= 0; --s) {
98
+ n = n_stack[s];
99
+ if (d_stack[s] <= 0) {
100
+ n_stack[s] = new RBNode(n.color, n.key, n.value, n_stack[s + 1], n.right);
127
101
  }
128
102
  else {
129
- var y = pp.right;
130
- if (y && y._color === RED) {
131
- //console.log("LRr")
132
- p._color = BLACK;
133
- pp.right = repaint(BLACK, y);
134
- pp._color = RED;
135
- s -= 1;
136
- }
137
- else {
138
- //console.log("LRb")
139
- p.right = n.left;
140
- pp._color = RED;
141
- pp.left = n.right;
142
- n._color = BLACK;
143
- n.left = p;
144
- n.right = pp;
145
- n_stack[s - 2] = n;
146
- n_stack[s - 1] = p;
147
- if (s >= 3) {
148
- var ppp = n_stack[s - 3];
149
- if (ppp.left === pp) {
150
- ppp.left = n;
151
- }
152
- else {
153
- ppp.right = n;
154
- }
155
- }
156
- break;
157
- }
103
+ n_stack[s] = new RBNode(n.color, n.key, n.value, n.left, n_stack[s + 1]);
158
104
  }
159
105
  }
160
- else {
161
- if (p.right === n) {
162
- var y = pp.left;
163
- if (y && y._color === RED) {
164
- //console.log("RRr", y.key)
165
- p._color = BLACK;
166
- pp.left = repaint(BLACK, y);
167
- pp._color = RED;
168
- s -= 1;
106
+ if (replace)
107
+ return new RedBlackTree(cmp, n_stack[0]);
108
+ //Rebalance tree using rotations
109
+ //console.log("start insert", key, d_stack)
110
+ for (s = n_stack.length - 1; s > 1; --s) {
111
+ const p = n_stack[s - 1];
112
+ n = n_stack[s];
113
+ if (p.color === BLACK || n.color === BLACK) {
114
+ break;
115
+ }
116
+ const pp = n_stack[s - 2];
117
+ if (pp.left === p) {
118
+ if (p.left === n) {
119
+ const y = pp.right;
120
+ if (y && y.color === RED) {
121
+ //console.log("LLr")
122
+ p.color = BLACK;
123
+ pp.right = repaint(BLACK, y);
124
+ pp.color = RED;
125
+ s -= 1;
126
+ }
127
+ else {
128
+ //console.log("LLb")
129
+ pp.color = RED;
130
+ pp.left = p.right;
131
+ p.color = BLACK;
132
+ p.right = pp;
133
+ n_stack[s - 2] = p;
134
+ n_stack[s - 1] = n;
135
+ if (s >= 3) {
136
+ const ppp = n_stack[s - 3];
137
+ if (ppp.left === pp) {
138
+ ppp.left = p;
139
+ }
140
+ else {
141
+ ppp.right = p;
142
+ }
143
+ }
144
+ break;
145
+ }
169
146
  }
170
147
  else {
171
- //console.log("RRb")
172
- pp._color = RED;
173
- pp.right = p.left;
174
- p._color = BLACK;
175
- p.left = pp;
176
- n_stack[s - 2] = p;
177
- n_stack[s - 1] = n;
178
- if (s >= 3) {
179
- var ppp = n_stack[s - 3];
180
- if (ppp.right === pp) {
181
- ppp.right = p;
182
- }
183
- else {
184
- ppp.left = p;
148
+ const y = pp.right;
149
+ if (y && y.color === RED) {
150
+ //console.log("LRr")
151
+ p.color = BLACK;
152
+ pp.right = repaint(BLACK, y);
153
+ pp.color = RED;
154
+ s -= 1;
155
+ }
156
+ else {
157
+ //console.log("LRb")
158
+ p.right = n.left;
159
+ pp.color = RED;
160
+ pp.left = n.right;
161
+ n.color = BLACK;
162
+ n.left = p;
163
+ n.right = pp;
164
+ n_stack[s - 2] = n;
165
+ n_stack[s - 1] = p;
166
+ if (s >= 3) {
167
+ const ppp = n_stack[s - 3];
168
+ if (ppp.left === pp) {
169
+ ppp.left = n;
170
+ }
171
+ else {
172
+ ppp.right = n;
173
+ }
185
174
  }
175
+ break;
186
176
  }
187
- break;
188
177
  }
189
178
  }
190
179
  else {
191
- var y = pp.left;
192
- if (y && y._color === RED) {
193
- //console.log("RLr")
194
- p._color = BLACK;
195
- pp.left = repaint(BLACK, y);
196
- pp._color = RED;
197
- s -= 1;
180
+ if (p.right === n) {
181
+ const y = pp.left;
182
+ if (y && y.color === RED) {
183
+ //console.log("RRr", y.key)
184
+ p.color = BLACK;
185
+ pp.left = repaint(BLACK, y);
186
+ pp.color = RED;
187
+ s -= 1;
188
+ }
189
+ else {
190
+ //console.log("RRb")
191
+ pp.color = RED;
192
+ pp.right = p.left;
193
+ p.color = BLACK;
194
+ p.left = pp;
195
+ n_stack[s - 2] = p;
196
+ n_stack[s - 1] = n;
197
+ if (s >= 3) {
198
+ const ppp = n_stack[s - 3];
199
+ if (ppp.right === pp) {
200
+ ppp.right = p;
201
+ }
202
+ else {
203
+ ppp.left = p;
204
+ }
205
+ }
206
+ break;
207
+ }
198
208
  }
199
209
  else {
200
- //console.log("RLb")
201
- p.left = n.right;
202
- pp._color = RED;
203
- pp.right = n.left;
204
- n._color = BLACK;
205
- n.right = p;
206
- n.left = pp;
207
- n_stack[s - 2] = n;
208
- n_stack[s - 1] = p;
209
- if (s >= 3) {
210
- var ppp = n_stack[s - 3];
211
- if (ppp.right === pp) {
212
- ppp.right = n;
213
- }
214
- else {
215
- ppp.left = n;
210
+ const y = pp.left;
211
+ if (y && y.color === RED) {
212
+ //console.log("RLr")
213
+ p.color = BLACK;
214
+ pp.left = repaint(BLACK, y);
215
+ pp.color = RED;
216
+ s -= 1;
217
+ }
218
+ else {
219
+ //console.log("RLb")
220
+ p.left = n.right;
221
+ pp.color = RED;
222
+ pp.right = n.left;
223
+ n.color = BLACK;
224
+ n.right = p;
225
+ n.left = pp;
226
+ n_stack[s - 2] = n;
227
+ n_stack[s - 1] = p;
228
+ if (s >= 3) {
229
+ const ppp = n_stack[s - 3];
230
+ if (ppp.right === pp) {
231
+ ppp.right = n;
232
+ }
233
+ else {
234
+ ppp.left = n;
235
+ }
216
236
  }
237
+ break;
217
238
  }
218
- break;
219
239
  }
220
240
  }
221
241
  }
242
+ //Return new tree
243
+ n_stack[0].color = BLACK;
244
+ return new RedBlackTree(cmp, n_stack[0]);
222
245
  }
223
- //Return new tree
224
- n_stack[0]._color = BLACK;
225
- return new RedBlackTree(cmp, n_stack[0]);
226
- };
227
- // //Visit all nodes inorder
228
- // function doVisitFull(visit, node) {
229
- // if (node.left) {
230
- // var v = doVisitFull(visit, node.left);
231
- // if (v) {
232
- // return v;
233
- // }
234
- // }
235
- // var v = visit(node.key, node.value);
236
- // if (v) {
237
- // return v;
238
- // }
239
- // if (node.right) {
240
- // return doVisitFull(visit, node.right);
241
- // }
242
- // }
243
- // //Visit half nodes in order
244
- // function doVisitHalf(lo, compare, visit, node) {
245
- // var l = compare(lo, node.key);
246
- // if (l <= 0) {
247
- // if (node.left) {
248
- // var v = doVisitHalf(lo, compare, visit, node.left);
249
- // if (v) {
250
- // return v;
251
- // }
252
- // }
253
- // var v = visit(node.key, node.value);
254
- // if (v) {
255
- // return v;
256
- // }
257
- // }
258
- // if (node.right) {
259
- // return doVisitHalf(lo, compare, visit, node.right);
260
- // }
261
- // }
262
- // //Visit all nodes within a range
263
- // function doVisit(lo, hi, compare, visit, node) {
264
- // var l = compare(lo, node.key);
265
- // var h = compare(hi, node.key);
266
- // var v;
267
- // if (l <= 0) {
268
- // if (node.left) {
269
- // v = doVisit(lo, hi, compare, visit, node.left);
270
- // if (v) {
271
- // return v;
272
- // }
273
- // }
274
- // if (h > 0) {
275
- // v = visit(node.key, node.value);
276
- // if (v) {
277
- // return v;
278
- // }
279
- // }
280
- // }
281
- // if (h > 0 && node.right) {
282
- // return doVisit(lo, hi, compare, visit, node.right);
283
- // }
284
- // }
285
- // proto.forEach = function rbTreeForEach(visit, lo, hi) {
286
- // if (!this.root) {
287
- // return;
288
- // }
289
- // switch (arguments.length) {
290
- // case 1:
291
- // return doVisitFull(visit, this.root);
292
- // break;
293
- // case 2:
294
- // return doVisitHalf(lo, this._compare, visit, this.root);
295
- // break;
296
- // case 3:
297
- // if (this._compare(lo, hi) >= 0) {
298
- // return;
299
- // }
300
- // return doVisit(lo, hi, this._compare, visit, this.root);
301
- // break;
302
- // }
303
- // };
304
- // //First item in list
305
- // Object.defineProperty(proto, "begin", {
306
- // get: function () {
307
- // var stack = [];
308
- // var n = this.root;
309
- // while (n) {
310
- // stack.push(n);
311
- // n = n.left;
312
- // }
313
- // return new RedBlackTreeIterator(this, stack);
314
- // },
315
- // });
316
- // //Last item in list
317
- // Object.defineProperty(proto, "end", {
318
- // get: function () {
319
- // var stack = [];
320
- // var n = this.root;
321
- // while (n) {
322
- // stack.push(n);
323
- // n = n.right;
324
- // }
325
- // return new RedBlackTreeIterator(this, stack);
326
- // },
327
- // });
328
- // proto.ge = function (key) {
329
- // var cmp = this._compare;
330
- // var n = this.root;
331
- // var stack = [];
332
- // var last_ptr = 0;
333
- // while (n) {
334
- // var d = cmp(key, n.key);
335
- // stack.push(n);
336
- // if (d <= 0) {
337
- // last_ptr = stack.length;
338
- // }
339
- // if (d <= 0) {
340
- // n = n.left;
341
- // } else {
342
- // n = n.right;
343
- // }
344
- // }
345
- // stack.length = last_ptr;
346
- // return new RedBlackTreeIterator(this, stack);
347
- // };
348
- // proto.gt = function (key) {
349
- // var cmp = this._compare;
350
- // var n = this.root;
351
- // var stack = [];
352
- // var last_ptr = 0;
353
- // while (n) {
354
- // var d = cmp(key, n.key);
355
- // stack.push(n);
356
- // if (d < 0) {
357
- // last_ptr = stack.length;
358
- // }
359
- // if (d < 0) {
360
- // n = n.left;
361
- // } else {
362
- // n = n.right;
363
- // }
364
- // }
365
- // stack.length = last_ptr;
366
- // return new RedBlackTreeIterator(this, stack);
367
- // };
368
- // proto.lt = function (key) {
369
- // var cmp = this._compare;
370
- // var n = this.root;
371
- // var stack = [];
372
- // var last_ptr = 0;
373
- // while (n) {
374
- // var d = cmp(key, n.key);
375
- // stack.push(n);
376
- // if (d > 0) {
377
- // last_ptr = stack.length;
378
- // }
379
- // if (d <= 0) {
380
- // n = n.left;
381
- // } else {
382
- // n = n.right;
383
- // }
384
- // }
385
- // stack.length = last_ptr;
386
- // return new RedBlackTreeIterator(this, stack);
387
- // };
388
- proto.le = function (key) {
389
- var cmp = this._compare;
390
- var n = this.root;
391
- var stack = [];
392
- var last_ptr = 0;
393
- while (n) {
394
- var d = cmp(key, n.key);
395
- stack.push(n);
396
- if (d >= 0) {
397
- last_ptr = stack.length;
398
- }
399
- if (d < 0) {
400
- n = n.left;
401
- }
402
- else {
403
- n = n.right;
246
+ /**
247
+ * Finds the last item in the tree whose key is <= `key`.
248
+ *
249
+ * @param key The key to search for.
250
+ * @returns An iterator at the given element.
251
+ */
252
+ le(key) {
253
+ const cmp = this.compare;
254
+ let n = this.root;
255
+ const stack = [];
256
+ let last_ptr = 0;
257
+ while (n) {
258
+ const d = cmp(key, n.key);
259
+ stack.push(n);
260
+ if (d >= 0) {
261
+ last_ptr = stack.length;
262
+ }
263
+ if (d < 0) {
264
+ n = n.left;
265
+ }
266
+ else {
267
+ n = n.right;
268
+ }
404
269
  }
270
+ stack.length = last_ptr;
271
+ return new RedBlackTreeIterator(this, stack);
405
272
  }
406
- stack.length = last_ptr;
407
- return new RedBlackTreeIterator(this, stack);
408
- };
409
- //Finds the item with key if it exists
410
- proto.find = function (key) {
411
- var cmp = this._compare;
412
- var n = this.root;
413
- var stack = [];
414
- while (n) {
415
- var d = cmp(key, n.key);
416
- stack.push(n);
417
- if (d === 0) {
418
- return new RedBlackTreeIterator(this, stack);
419
- }
420
- if (d <= 0) {
421
- n = n.left;
422
- }
423
- else {
424
- n = n.right;
273
+ /**
274
+ * @returns An iterator pointing to the first item in the tree with `key`, otherwise null.
275
+ */
276
+ find(key) {
277
+ const cmp = this.compare;
278
+ let n = this.root;
279
+ const stack = [];
280
+ while (n) {
281
+ const d = cmp(key, n.key);
282
+ stack.push(n);
283
+ if (d === 0) {
284
+ return new RedBlackTreeIterator(this, stack);
285
+ }
286
+ if (d <= 0) {
287
+ n = n.left;
288
+ }
289
+ else {
290
+ n = n.right;
291
+ }
425
292
  }
293
+ return new RedBlackTreeIterator(this, []);
426
294
  }
427
- return new RedBlackTreeIterator(this, []);
428
- };
429
- //Removes item with key from tree
430
- proto.remove = function (key) {
431
- var iter = this.find(key);
432
- return iter.remove();
433
- };
434
- //Returns the item at `key`
435
- proto.get = function (key) {
436
- var cmp = this._compare;
437
- var n = this.root;
438
- while (n) {
439
- var d = cmp(key, n.key);
440
- if (d === 0) {
441
- return n.value;
442
- }
443
- if (d <= 0) {
444
- n = n.left;
445
- }
446
- else {
447
- n = n.right;
295
+ /**
296
+ * Removes the first item with `key` in the tree.
297
+ *
298
+ * @param key The key of the item to remove.
299
+ * @returns A new tree with the given item removed, if it exists.
300
+ */
301
+ remove(key) {
302
+ const iter = this.find(key);
303
+ return iter.remove();
304
+ }
305
+ /**
306
+ * Retrieves the value associated with `key`.
307
+ *
308
+ * @param key The key of the item to look up.
309
+ * @returns The value of the first node associated with `key`.
310
+ */
311
+ // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
312
+ get(key) {
313
+ const cmp = this.compare;
314
+ let n = this.root;
315
+ while (n) {
316
+ const d = cmp(key, n.key);
317
+ if (d === 0) {
318
+ return n.value;
319
+ }
320
+ if (d <= 0) {
321
+ n = n.left;
322
+ }
323
+ else {
324
+ n = n.right;
325
+ }
448
326
  }
327
+ return;
449
328
  }
450
- return;
451
- };
452
- //Iterator for red black tree
453
- function RedBlackTreeIterator(tree, stack) {
454
- this.tree = tree;
455
- this._stack = stack;
456
329
  }
457
- var iproto = RedBlackTreeIterator.prototype;
458
- // //Test if iterator is valid
459
- // Object.defineProperty(iproto, "valid", {
460
- // get: function () {
461
- // return this._stack.length > 0;
462
- // },
463
- // });
464
- // //Node of the iterator
465
- // Object.defineProperty(iproto, "node", {
466
- // get: function () {
467
- // if (this._stack.length > 0) {
468
- // return this._stack[this._stack.length - 1];
469
- // }
470
- // return null;
471
- // },
472
- // enumerable: true,
473
- // });
474
- // //Makes a copy of an iterator
475
- // iproto.clone = function () {
476
- // return new RedBlackTreeIterator(this.tree, this._stack.slice());
477
- // };
330
+ exports.RedBlackTree = RedBlackTree;
478
331
  //Swaps two nodes
479
332
  function swapNode(n, v) {
480
333
  n.key = v.key;
481
334
  n.value = v.value;
482
335
  n.left = v.left;
483
336
  n.right = v.right;
484
- n._color = v._color;
337
+ n.color = v.color;
485
338
  }
486
339
  //Fix up a double black node in a tree
487
340
  function fixDoubleBlack(stack) {
488
- var n, p, s, z;
489
- for (var i = stack.length - 1; i >= 0; --i) {
341
+ let n, p, s, z;
342
+ for (let i = stack.length - 1; i >= 0; --i) {
490
343
  n = stack[i];
491
344
  if (i === 0) {
492
- n._color = BLACK;
345
+ n.color = BLACK;
493
346
  return;
494
347
  }
495
348
  //console.log("visit node:", n.key, i, stack[i].key, stack[i-1].key)
@@ -497,19 +350,19 @@ function fixDoubleBlack(stack) {
497
350
  if (p.left === n) {
498
351
  //console.log("left child")
499
352
  s = p.right;
500
- if (s.right && s.right._color === RED) {
353
+ if (s.right && s.right.color === RED) {
501
354
  //console.log("case 1: right sibling child red")
502
355
  s = p.right = cloneNode(s);
503
356
  z = s.right = cloneNode(s.right);
504
357
  p.right = s.left;
505
358
  s.left = p;
506
359
  s.right = z;
507
- s._color = p._color;
508
- n._color = BLACK;
509
- p._color = BLACK;
510
- z._color = BLACK;
360
+ s.color = p.color;
361
+ n.color = BLACK;
362
+ p.color = BLACK;
363
+ z.color = BLACK;
511
364
  if (i > 1) {
512
- var pp = stack[i - 2];
365
+ const pp = stack[i - 2];
513
366
  if (pp.left === p) {
514
367
  pp.left = s;
515
368
  }
@@ -520,7 +373,7 @@ function fixDoubleBlack(stack) {
520
373
  stack[i - 1] = s;
521
374
  return;
522
375
  }
523
- else if (s.left && s.left._color === RED) {
376
+ else if (s.left && s.left.color === RED) {
524
377
  //console.log("case 1: left sibling child red")
525
378
  s = p.right = cloneNode(s);
526
379
  z = s.left = cloneNode(s.left);
@@ -528,12 +381,12 @@ function fixDoubleBlack(stack) {
528
381
  s.left = z.right;
529
382
  z.left = p;
530
383
  z.right = s;
531
- z._color = p._color;
532
- p._color = BLACK;
533
- s._color = BLACK;
534
- n._color = BLACK;
384
+ z.color = p.color;
385
+ p.color = BLACK;
386
+ s.color = BLACK;
387
+ n.color = BLACK;
535
388
  if (i > 1) {
536
- var pp = stack[i - 2];
389
+ const pp = stack[i - 2];
537
390
  if (pp.left === p) {
538
391
  pp.left = z;
539
392
  }
@@ -544,10 +397,10 @@ function fixDoubleBlack(stack) {
544
397
  stack[i - 1] = z;
545
398
  return;
546
399
  }
547
- if (s._color === BLACK) {
548
- if (p._color === RED) {
400
+ if (s.color === BLACK) {
401
+ if (p.color === RED) {
549
402
  //console.log("case 2: black sibling, red parent", p.right.value)
550
- p._color = BLACK;
403
+ p.color = BLACK;
551
404
  p.right = repaint(RED, s);
552
405
  return;
553
406
  }
@@ -562,10 +415,10 @@ function fixDoubleBlack(stack) {
562
415
  s = cloneNode(s);
563
416
  p.right = s.left;
564
417
  s.left = p;
565
- s._color = p._color;
566
- p._color = RED;
418
+ s.color = p.color;
419
+ p.color = RED;
567
420
  if (i > 1) {
568
- var pp = stack[i - 2];
421
+ const pp = stack[i - 2];
569
422
  if (pp.left === p) {
570
423
  pp.left = s;
571
424
  }
@@ -587,19 +440,19 @@ function fixDoubleBlack(stack) {
587
440
  else {
588
441
  //console.log("right child")
589
442
  s = p.left;
590
- if (s.left && s.left._color === RED) {
591
- //console.log("case 1: left sibling child red", p.value, p._color)
443
+ if (s.left && s.left.color === RED) {
444
+ //console.log("case 1: left sibling child red", p.value, p.color)
592
445
  s = p.left = cloneNode(s);
593
446
  z = s.left = cloneNode(s.left);
594
447
  p.left = s.right;
595
448
  s.right = p;
596
449
  s.left = z;
597
- s._color = p._color;
598
- n._color = BLACK;
599
- p._color = BLACK;
600
- z._color = BLACK;
450
+ s.color = p.color;
451
+ n.color = BLACK;
452
+ p.color = BLACK;
453
+ z.color = BLACK;
601
454
  if (i > 1) {
602
- var pp = stack[i - 2];
455
+ const pp = stack[i - 2];
603
456
  if (pp.right === p) {
604
457
  pp.right = s;
605
458
  }
@@ -610,7 +463,7 @@ function fixDoubleBlack(stack) {
610
463
  stack[i - 1] = s;
611
464
  return;
612
465
  }
613
- else if (s.right && s.right._color === RED) {
466
+ else if (s.right && s.right.color === RED) {
614
467
  //console.log("case 1: right sibling child red")
615
468
  s = p.left = cloneNode(s);
616
469
  z = s.right = cloneNode(s.right);
@@ -618,12 +471,12 @@ function fixDoubleBlack(stack) {
618
471
  s.right = z.left;
619
472
  z.right = p;
620
473
  z.left = s;
621
- z._color = p._color;
622
- p._color = BLACK;
623
- s._color = BLACK;
624
- n._color = BLACK;
474
+ z.color = p.color;
475
+ p.color = BLACK;
476
+ s.color = BLACK;
477
+ n.color = BLACK;
625
478
  if (i > 1) {
626
- var pp = stack[i - 2];
479
+ const pp = stack[i - 2];
627
480
  if (pp.right === p) {
628
481
  pp.right = z;
629
482
  }
@@ -634,10 +487,10 @@ function fixDoubleBlack(stack) {
634
487
  stack[i - 1] = z;
635
488
  return;
636
489
  }
637
- if (s._color === BLACK) {
638
- if (p._color === RED) {
490
+ if (s.color === BLACK) {
491
+ if (p.color === RED) {
639
492
  //console.log("case 2: black sibling, red parent")
640
- p._color = BLACK;
493
+ p.color = BLACK;
641
494
  p.left = repaint(RED, s);
642
495
  return;
643
496
  }
@@ -652,10 +505,10 @@ function fixDoubleBlack(stack) {
652
505
  s = cloneNode(s);
653
506
  p.left = s.right;
654
507
  s.right = p;
655
- s._color = p._color;
656
- p._color = RED;
508
+ s.color = p.color;
509
+ p.color = RED;
657
510
  if (i > 1) {
658
- var pp = stack[i - 2];
511
+ const pp = stack[i - 2];
659
512
  if (pp.right === p) {
660
513
  pp.right = s;
661
514
  }
@@ -676,236 +529,128 @@ function fixDoubleBlack(stack) {
676
529
  }
677
530
  }
678
531
  }
679
- //Removes item at iterator from tree
680
- iproto.remove = function () {
681
- var stack = this._stack;
682
- if (stack.length === 0) {
683
- return this.tree;
684
- }
685
- //First copy path to node
686
- var cstack = new Array(stack.length);
687
- var n = stack[stack.length - 1];
688
- cstack[cstack.length - 1] = new RBNode(n._color, n.key, n.value, n.left, n.right);
689
- for (var i = stack.length - 2; i >= 0; --i) {
690
- var n = stack[i];
691
- if (n.left === stack[i + 1]) {
692
- cstack[i] = new RBNode(n._color, n.key, n.value, cstack[i + 1], n.right);
693
- }
694
- else {
695
- cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i + 1]);
696
- }
697
- }
698
- //Get node
699
- n = cstack[cstack.length - 1];
700
- //console.log("start remove: ", n.value)
701
- //If not leaf, then swap with previous node
702
- if (n.left && n.right) {
703
- //console.log("moving to leaf")
704
- //First walk to previous leaf
705
- var split = cstack.length;
706
- n = n.left;
707
- while (n.right) {
708
- cstack.push(n);
709
- n = n.right;
710
- }
711
- //Copy path to leaf
712
- var v = cstack[split - 1];
713
- cstack.push(new RBNode(n._color, v.key, v.value, n.left, n.right));
714
- cstack[split - 1].key = n.key;
715
- cstack[split - 1].value = n.value;
716
- //Fix up stack
717
- for (var i = cstack.length - 2; i >= split; --i) {
718
- n = cstack[i];
719
- cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i + 1]);
720
- }
721
- cstack[split - 1].left = cstack[split];
532
+ /** Iterates through the nodes in a red-black tree. */
533
+ class RedBlackTreeIterator {
534
+ constructor(
535
+ /** The tree associated with the iterator. */
536
+ tree, stack) {
537
+ this.tree = tree;
538
+ this.stack = stack;
722
539
  }
723
- //console.log("stack=", cstack.map(function(v) { return v.value }))
724
- //Remove leaf node
725
- n = cstack[cstack.length - 1];
726
- if (n._color === RED) {
727
- //Easy case: removing red leaf
728
- //console.log("RED leaf")
729
- var p = cstack[cstack.length - 2];
730
- if (p.left === n) {
731
- p.left = null;
540
+ /**
541
+ * Removes the iterator's current item form the tree.
542
+ *
543
+ * @returns A new binary search tree with the item removed.
544
+ */
545
+ remove() {
546
+ const stack = this.stack;
547
+ if (stack.length === 0) {
548
+ return this.tree;
732
549
  }
733
- else if (p.right === n) {
734
- p.right = null;
550
+ //First copy path to node
551
+ const cstack = new Array(stack.length);
552
+ let n = stack[stack.length - 1];
553
+ cstack[cstack.length - 1] = new RBNode(n.color, n.key, n.value, n.left, n.right);
554
+ let i;
555
+ for (i = stack.length - 2; i >= 0; --i) {
556
+ n = stack[i];
557
+ if (n.left === stack[i + 1]) {
558
+ cstack[i] = new RBNode(n.color, n.key, n.value, cstack[i + 1], n.right);
559
+ }
560
+ else {
561
+ cstack[i] = new RBNode(n.color, n.key, n.value, n.left, cstack[i + 1]);
562
+ }
735
563
  }
736
- cstack.pop();
737
- return new RedBlackTree(this.tree._compare, cstack[0]);
738
- }
739
- else {
740
- if (n.left || n.right) {
741
- //Second easy case: Single child black parent
742
- //console.log("BLACK single child")
743
- if (n.left) {
744
- swapNode(n, n.left);
745
- }
746
- else if (n.right) {
747
- swapNode(n, n.right);
748
- }
749
- //Child must be red, so repaint it black to balance color
750
- n._color = BLACK;
751
- return new RedBlackTree(this.tree._compare, cstack[0]);
564
+ //Get node
565
+ n = cstack[cstack.length - 1];
566
+ //console.log("start remove: ", n.value)
567
+ //If not leaf, then swap with previous node
568
+ if (n.left && n.right) {
569
+ //console.log("moving to leaf")
570
+ //First walk to previous leaf
571
+ const split = cstack.length;
572
+ n = n.left;
573
+ while (n.right) {
574
+ cstack.push(n);
575
+ n = n.right;
576
+ }
577
+ //Copy path to leaf
578
+ const v = cstack[split - 1];
579
+ cstack.push(new RBNode(n.color, v.key, v.value, n.left, n.right));
580
+ cstack[split - 1].key = n.key;
581
+ cstack[split - 1].value = n.value;
582
+ //Fix up stack
583
+ for (i = cstack.length - 2; i >= split; --i) {
584
+ n = cstack[i];
585
+ cstack[i] = new RBNode(n.color, n.key, n.value, n.left, cstack[i + 1]);
586
+ }
587
+ cstack[split - 1].left = cstack[split];
752
588
  }
753
- else if (cstack.length === 1) {
754
- //Third easy case: root
755
- //console.log("ROOT")
756
- return new RedBlackTree(this.tree._compare, null);
589
+ //console.log("stack=", cstack.map(function(v) { return v.value }))
590
+ //Remove leaf node
591
+ n = cstack[cstack.length - 1];
592
+ if (n.color === RED) {
593
+ //Easy case: removing red leaf
594
+ //console.log("RED leaf")
595
+ const p = cstack[cstack.length - 2];
596
+ if (p.left === n) {
597
+ p.left = null;
598
+ }
599
+ else if (p.right === n) {
600
+ p.right = null;
601
+ }
602
+ cstack.pop();
603
+ return new RedBlackTree(this.tree.compare, cstack[0]);
757
604
  }
758
605
  else {
759
- //Hard case: Repaint n, and then do some nasty stuff
760
- //console.log("BLACK leaf no children")
761
- var parent = cstack[cstack.length - 2];
762
- fixDoubleBlack(cstack);
763
- //Fix up links
764
- if (parent.left === n) {
765
- parent.left = null;
606
+ if (n.left || n.right) {
607
+ //Second easy case: Single child black parent
608
+ //console.log("BLACK single child")
609
+ if (n.left) {
610
+ swapNode(n, n.left);
611
+ }
612
+ else if (n.right) {
613
+ swapNode(n, n.right);
614
+ }
615
+ //Child must be red, so repaint it black to balance color
616
+ n.color = BLACK;
617
+ return new RedBlackTree(this.tree.compare, cstack[0]);
618
+ }
619
+ else if (cstack.length === 1) {
620
+ //Third easy case: root
621
+ //console.log("ROOT")
622
+ return new RedBlackTree(this.tree.compare, null);
766
623
  }
767
624
  else {
768
- parent.right = null;
625
+ //Hard case: Repaint n, and then do some nasty stuff
626
+ //console.log("BLACK leaf no children")
627
+ const parent = cstack[cstack.length - 2];
628
+ fixDoubleBlack(cstack);
629
+ //Fix up links
630
+ if (parent.left === n) {
631
+ parent.left = null;
632
+ }
633
+ else {
634
+ parent.right = null;
635
+ }
769
636
  }
770
637
  }
638
+ return new RedBlackTree(this.tree.compare, cstack[0]);
771
639
  }
772
- return new RedBlackTree(this.tree._compare, cstack[0]);
773
- };
774
- //Returns key
775
- Object.defineProperty(iproto, "key", {
776
- get: function () {
777
- if (this._stack.length > 0) {
778
- return this._stack[this._stack.length - 1].key;
640
+ /** The key of the iterator's current item. */
641
+ get key() {
642
+ if (this.stack.length > 0) {
643
+ return this.stack[this.stack.length - 1].key;
779
644
  }
780
645
  return;
781
- },
782
- enumerable: true,
783
- });
784
- //Returns value
785
- Object.defineProperty(iproto, "value", {
786
- get: function () {
787
- if (this._stack.length > 0) {
788
- return this._stack[this._stack.length - 1].value;
646
+ }
647
+ /** The value of the iterator's current item. */
648
+ get value() {
649
+ if (this.stack.length > 0) {
650
+ return this.stack[this.stack.length - 1].value;
789
651
  }
790
652
  return;
791
- },
792
- enumerable: true,
793
- });
794
- // //Advances iterator to next element in list
795
- // iproto.next = function () {
796
- // var stack = this._stack;
797
- // if (stack.length === 0) {
798
- // return;
799
- // }
800
- // var n = stack[stack.length - 1];
801
- // if (n.right) {
802
- // n = n.right;
803
- // while (n) {
804
- // stack.push(n);
805
- // n = n.left;
806
- // }
807
- // } else {
808
- // stack.pop();
809
- // while (stack.length > 0 && stack[stack.length - 1].right === n) {
810
- // n = stack[stack.length - 1];
811
- // stack.pop();
812
- // }
813
- // }
814
- // };
815
- // //Checks if iterator is at end of tree
816
- // Object.defineProperty(iproto, "hasNext", {
817
- // get: function () {
818
- // var stack = this._stack;
819
- // if (stack.length === 0) {
820
- // return false;
821
- // }
822
- // if (stack[stack.length - 1].right) {
823
- // return true;
824
- // }
825
- // for (var s = stack.length - 1; s > 0; --s) {
826
- // if (stack[s - 1].left === stack[s]) {
827
- // return true;
828
- // }
829
- // }
830
- // return false;
831
- // },
832
- // });
833
- // //Update value
834
- // iproto.update = function (value) {
835
- // var stack = this._stack;
836
- // if (stack.length === 0) {
837
- // throw new Error("Can't update empty node!");
838
- // }
839
- // var cstack = new Array(stack.length);
840
- // var n = stack[stack.length - 1];
841
- // cstack[cstack.length - 1] = new RBNode(
842
- // n._color,
843
- // n.key,
844
- // value,
845
- // n.left,
846
- // n.right
847
- // );
848
- // for (var i = stack.length - 2; i >= 0; --i) {
849
- // n = stack[i];
850
- // if (n.left === stack[i + 1]) {
851
- // cstack[i] = new RBNode(n._color, n.key, n.value, cstack[i + 1], n.right);
852
- // } else {
853
- // cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i + 1]);
854
- // }
855
- // }
856
- // return new RedBlackTree(this.tree._compare, cstack[0]);
857
- // };
858
- // //Moves iterator backward one element
859
- // iproto.prev = function () {
860
- // var stack = this._stack;
861
- // if (stack.length === 0) {
862
- // return;
863
- // }
864
- // var n = stack[stack.length - 1];
865
- // if (n.left) {
866
- // n = n.left;
867
- // while (n) {
868
- // stack.push(n);
869
- // n = n.right;
870
- // }
871
- // } else {
872
- // stack.pop();
873
- // while (stack.length > 0 && stack[stack.length - 1].left === n) {
874
- // n = stack[stack.length - 1];
875
- // stack.pop();
876
- // }
877
- // }
878
- // };
879
- // //Checks if iterator is at start of tree
880
- // Object.defineProperty(iproto, "hasPrev", {
881
- // get: function () {
882
- // var stack = this._stack;
883
- // if (stack.length === 0) {
884
- // return false;
885
- // }
886
- // if (stack[stack.length - 1].left) {
887
- // return true;
888
- // }
889
- // for (var s = stack.length - 1; s > 0; --s) {
890
- // if (stack[s - 1].right === stack[s]) {
891
- // return true;
892
- // }
893
- // }
894
- // return false;
895
- // },
896
- // });
897
- // //Default comparison function
898
- // function defaultCompare(a, b) {
899
- // if (a < b) {
900
- // return -1;
901
- // }
902
- // if (a > b) {
903
- // return 1;
904
- // }
905
- // return 0;
906
- // }
907
- //Build a tree
908
- function createRBTree(compare) {
909
- return new RedBlackTree(compare, null);
653
+ }
910
654
  }
655
+ exports.RedBlackTreeIterator = RedBlackTreeIterator;
911
656
  //# sourceMappingURL=functional-red-black-tree.js.map