articulated 1.3.1 → 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,343 @@
1
- "use strict";
2
- module.exports = createRBTree;
3
1
  // Modified from https://github.com/mikolalysenko/functional-red-black-tree/blob/master/rbtree.js
4
2
  // 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;
3
+ //
4
+ // External types modified from
5
+ // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/functional-red-black-tree/functional-red-black-tree-tests.ts
6
+ // which is MIT Licensed.
7
+ const RED = 0;
8
+ const BLACK = 1;
9
+ /**
10
+ * @private Only exported for tests.
11
+ */
12
+ export class RBNode {
13
+ constructor(color,
14
+ /** The key associated with the node. */
15
+ key,
16
+ /** The value associated with the node. */
17
+ value,
18
+ /** The left subtree of the node. */
19
+ left,
20
+ /** The right subtree of the node. */
21
+ right) {
22
+ this.color = color;
23
+ this.key = key;
24
+ this.value = value;
25
+ this.left = left;
26
+ this.right = right;
27
+ }
13
28
  }
14
29
  function cloneNode(node) {
15
- return new RBNode(node._color, node.key, node.value, node.left, node.right);
30
+ return new RBNode(node.color, node.key, node.value, node.left, node.right);
16
31
  }
17
32
  function repaint(color, node) {
18
33
  return new RBNode(color, node.key, node.value, node.left, node.right);
19
34
  }
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
- }
35
+ /** Represents a functional red-black tree. */
36
+ export class RedBlackTree {
37
+ constructor(compare, root) {
38
+ this.compare = compare;
39
+ this.root = root;
64
40
  }
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);
41
+ /**
42
+ * Creates an empty red-black tree.
43
+ *
44
+ * @param compare Comparison function, same semantics as array.sort().
45
+ * @returns An empty tree ordered by `compare`.
46
+ */
47
+ static new(compare) {
48
+ return new RedBlackTree(compare, null);
73
49
  }
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);
50
+ /**
51
+ * Creates a new tree with `key` set to `value`, overwriting any
52
+ * existing value.
53
+ *
54
+ * @param key The key of the item to insert.
55
+ * @param value The value of the item to insert.
56
+ * @returns A new tree with `key` set to `value`.
57
+ */
58
+ set(key, value) {
59
+ const cmp = this.compare;
60
+ //Find point to insert/replace node
61
+ let n = this.root;
62
+ const n_stack = [];
63
+ const d_stack = [];
64
+ let d = 0;
65
+ while (n) {
66
+ d = cmp(key, n.key);
67
+ n_stack.push(n);
68
+ d_stack.push(d);
69
+ // If the keys are equivalent, skip straight to the replace = true case.
70
+ if (d === 0)
71
+ break;
72
+ else if (d < 0) {
73
+ n = n.left;
74
+ }
75
+ else {
76
+ n = n.right;
77
+ }
82
78
  }
83
- else {
84
- n_stack[s] = new RBNode(n._color, n.key, n.value, n.left, n_stack[s + 1]);
79
+ const replace = d === 0 && n_stack.length > 0;
80
+ if (replace) {
81
+ // The last node in the n_stack has key equivalent to `key`.
82
+ // Replace its entry without changing the tree structure.
83
+ const lastN = n_stack[n_stack.length - 1];
84
+ if (lastN.key === key && lastN.value === value)
85
+ return this;
86
+ n_stack[n_stack.length - 1] = new RBNode(lastN.color, key, value, lastN.left, lastN.right);
85
87
  }
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;
88
+ else {
89
+ n_stack.push(new RBNode(RED, key, value, null, null));
96
90
  }
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
- }
91
+ //Rebuild path to leaf node
92
+ let s;
93
+ for (s = n_stack.length - 2; s >= 0; --s) {
94
+ n = n_stack[s];
95
+ if (d_stack[s] <= 0) {
96
+ n_stack[s] = new RBNode(n.color, n.key, n.value, n_stack[s + 1], n.right);
127
97
  }
128
98
  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
- }
99
+ n_stack[s] = new RBNode(n.color, n.key, n.value, n.left, n_stack[s + 1]);
158
100
  }
159
101
  }
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;
102
+ if (replace)
103
+ return new RedBlackTree(cmp, n_stack[0]);
104
+ //Rebalance tree using rotations
105
+ //console.log("start insert", key, d_stack)
106
+ for (s = n_stack.length - 1; s > 1; --s) {
107
+ const p = n_stack[s - 1];
108
+ n = n_stack[s];
109
+ if (p.color === BLACK || n.color === BLACK) {
110
+ break;
111
+ }
112
+ const pp = n_stack[s - 2];
113
+ if (pp.left === p) {
114
+ if (p.left === n) {
115
+ const y = pp.right;
116
+ if (y && y.color === RED) {
117
+ //console.log("LLr")
118
+ p.color = BLACK;
119
+ pp.right = repaint(BLACK, y);
120
+ pp.color = RED;
121
+ s -= 1;
122
+ }
123
+ else {
124
+ //console.log("LLb")
125
+ pp.color = RED;
126
+ pp.left = p.right;
127
+ p.color = BLACK;
128
+ p.right = pp;
129
+ n_stack[s - 2] = p;
130
+ n_stack[s - 1] = n;
131
+ if (s >= 3) {
132
+ const ppp = n_stack[s - 3];
133
+ if (ppp.left === pp) {
134
+ ppp.left = p;
135
+ }
136
+ else {
137
+ ppp.right = p;
138
+ }
139
+ }
140
+ break;
141
+ }
169
142
  }
170
143
  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;
144
+ const y = pp.right;
145
+ if (y && y.color === RED) {
146
+ //console.log("LRr")
147
+ p.color = BLACK;
148
+ pp.right = repaint(BLACK, y);
149
+ pp.color = RED;
150
+ s -= 1;
151
+ }
152
+ else {
153
+ //console.log("LRb")
154
+ p.right = n.left;
155
+ pp.color = RED;
156
+ pp.left = n.right;
157
+ n.color = BLACK;
158
+ n.left = p;
159
+ n.right = pp;
160
+ n_stack[s - 2] = n;
161
+ n_stack[s - 1] = p;
162
+ if (s >= 3) {
163
+ const ppp = n_stack[s - 3];
164
+ if (ppp.left === pp) {
165
+ ppp.left = n;
166
+ }
167
+ else {
168
+ ppp.right = n;
169
+ }
185
170
  }
171
+ break;
186
172
  }
187
- break;
188
173
  }
189
174
  }
190
175
  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;
176
+ if (p.right === n) {
177
+ const y = pp.left;
178
+ if (y && y.color === RED) {
179
+ //console.log("RRr", y.key)
180
+ p.color = BLACK;
181
+ pp.left = repaint(BLACK, y);
182
+ pp.color = RED;
183
+ s -= 1;
184
+ }
185
+ else {
186
+ //console.log("RRb")
187
+ pp.color = RED;
188
+ pp.right = p.left;
189
+ p.color = BLACK;
190
+ p.left = pp;
191
+ n_stack[s - 2] = p;
192
+ n_stack[s - 1] = n;
193
+ if (s >= 3) {
194
+ const ppp = n_stack[s - 3];
195
+ if (ppp.right === pp) {
196
+ ppp.right = p;
197
+ }
198
+ else {
199
+ ppp.left = p;
200
+ }
201
+ }
202
+ break;
203
+ }
198
204
  }
199
205
  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;
206
+ const y = pp.left;
207
+ if (y && y.color === RED) {
208
+ //console.log("RLr")
209
+ p.color = BLACK;
210
+ pp.left = repaint(BLACK, y);
211
+ pp.color = RED;
212
+ s -= 1;
213
+ }
214
+ else {
215
+ //console.log("RLb")
216
+ p.left = n.right;
217
+ pp.color = RED;
218
+ pp.right = n.left;
219
+ n.color = BLACK;
220
+ n.right = p;
221
+ n.left = pp;
222
+ n_stack[s - 2] = n;
223
+ n_stack[s - 1] = p;
224
+ if (s >= 3) {
225
+ const ppp = n_stack[s - 3];
226
+ if (ppp.right === pp) {
227
+ ppp.right = n;
228
+ }
229
+ else {
230
+ ppp.left = n;
231
+ }
216
232
  }
233
+ break;
217
234
  }
218
- break;
219
235
  }
220
236
  }
221
237
  }
238
+ //Return new tree
239
+ n_stack[0].color = BLACK;
240
+ return new RedBlackTree(cmp, n_stack[0]);
222
241
  }
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;
242
+ /**
243
+ * Finds the last item in the tree whose key is <= `key`.
244
+ *
245
+ * @param key The key to search for.
246
+ * @returns An iterator at the given element.
247
+ */
248
+ le(key) {
249
+ const cmp = this.compare;
250
+ let n = this.root;
251
+ const stack = [];
252
+ let last_ptr = 0;
253
+ while (n) {
254
+ const d = cmp(key, n.key);
255
+ stack.push(n);
256
+ if (d >= 0) {
257
+ last_ptr = stack.length;
258
+ }
259
+ if (d < 0) {
260
+ n = n.left;
261
+ }
262
+ else {
263
+ n = n.right;
264
+ }
404
265
  }
266
+ stack.length = last_ptr;
267
+ return new RedBlackTreeIterator(this, stack);
405
268
  }
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;
269
+ /**
270
+ * @returns An iterator pointing to the first item in the tree with `key`, otherwise null.
271
+ */
272
+ find(key) {
273
+ const cmp = this.compare;
274
+ let n = this.root;
275
+ const stack = [];
276
+ while (n) {
277
+ const d = cmp(key, n.key);
278
+ stack.push(n);
279
+ if (d === 0) {
280
+ return new RedBlackTreeIterator(this, stack);
281
+ }
282
+ if (d <= 0) {
283
+ n = n.left;
284
+ }
285
+ else {
286
+ n = n.right;
287
+ }
425
288
  }
289
+ return new RedBlackTreeIterator(this, []);
426
290
  }
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;
291
+ /**
292
+ * Removes the first item with `key` in the tree.
293
+ *
294
+ * @param key The key of the item to remove.
295
+ * @returns A new tree with the given item removed, if it exists.
296
+ */
297
+ remove(key) {
298
+ const iter = this.find(key);
299
+ return iter.remove();
300
+ }
301
+ /**
302
+ * Retrieves the value associated with `key`.
303
+ *
304
+ * @param key The key of the item to look up.
305
+ * @returns The value of the first node associated with `key`.
306
+ */
307
+ // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
308
+ get(key) {
309
+ const cmp = this.compare;
310
+ let n = this.root;
311
+ while (n) {
312
+ const d = cmp(key, n.key);
313
+ if (d === 0) {
314
+ return n.value;
315
+ }
316
+ if (d <= 0) {
317
+ n = n.left;
318
+ }
319
+ else {
320
+ n = n.right;
321
+ }
448
322
  }
323
+ return;
449
324
  }
450
- return;
451
- };
452
- //Iterator for red black tree
453
- function RedBlackTreeIterator(tree, stack) {
454
- this.tree = tree;
455
- this._stack = stack;
456
325
  }
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
- // };
478
326
  //Swaps two nodes
479
327
  function swapNode(n, v) {
480
328
  n.key = v.key;
481
329
  n.value = v.value;
482
330
  n.left = v.left;
483
331
  n.right = v.right;
484
- n._color = v._color;
332
+ n.color = v.color;
485
333
  }
486
334
  //Fix up a double black node in a tree
487
335
  function fixDoubleBlack(stack) {
488
- var n, p, s, z;
489
- for (var i = stack.length - 1; i >= 0; --i) {
336
+ let n, p, s, z;
337
+ for (let i = stack.length - 1; i >= 0; --i) {
490
338
  n = stack[i];
491
339
  if (i === 0) {
492
- n._color = BLACK;
340
+ n.color = BLACK;
493
341
  return;
494
342
  }
495
343
  //console.log("visit node:", n.key, i, stack[i].key, stack[i-1].key)
@@ -497,19 +345,19 @@ function fixDoubleBlack(stack) {
497
345
  if (p.left === n) {
498
346
  //console.log("left child")
499
347
  s = p.right;
500
- if (s.right && s.right._color === RED) {
348
+ if (s.right && s.right.color === RED) {
501
349
  //console.log("case 1: right sibling child red")
502
350
  s = p.right = cloneNode(s);
503
351
  z = s.right = cloneNode(s.right);
504
352
  p.right = s.left;
505
353
  s.left = p;
506
354
  s.right = z;
507
- s._color = p._color;
508
- n._color = BLACK;
509
- p._color = BLACK;
510
- z._color = BLACK;
355
+ s.color = p.color;
356
+ n.color = BLACK;
357
+ p.color = BLACK;
358
+ z.color = BLACK;
511
359
  if (i > 1) {
512
- var pp = stack[i - 2];
360
+ const pp = stack[i - 2];
513
361
  if (pp.left === p) {
514
362
  pp.left = s;
515
363
  }
@@ -520,7 +368,7 @@ function fixDoubleBlack(stack) {
520
368
  stack[i - 1] = s;
521
369
  return;
522
370
  }
523
- else if (s.left && s.left._color === RED) {
371
+ else if (s.left && s.left.color === RED) {
524
372
  //console.log("case 1: left sibling child red")
525
373
  s = p.right = cloneNode(s);
526
374
  z = s.left = cloneNode(s.left);
@@ -528,12 +376,12 @@ function fixDoubleBlack(stack) {
528
376
  s.left = z.right;
529
377
  z.left = p;
530
378
  z.right = s;
531
- z._color = p._color;
532
- p._color = BLACK;
533
- s._color = BLACK;
534
- n._color = BLACK;
379
+ z.color = p.color;
380
+ p.color = BLACK;
381
+ s.color = BLACK;
382
+ n.color = BLACK;
535
383
  if (i > 1) {
536
- var pp = stack[i - 2];
384
+ const pp = stack[i - 2];
537
385
  if (pp.left === p) {
538
386
  pp.left = z;
539
387
  }
@@ -544,10 +392,10 @@ function fixDoubleBlack(stack) {
544
392
  stack[i - 1] = z;
545
393
  return;
546
394
  }
547
- if (s._color === BLACK) {
548
- if (p._color === RED) {
395
+ if (s.color === BLACK) {
396
+ if (p.color === RED) {
549
397
  //console.log("case 2: black sibling, red parent", p.right.value)
550
- p._color = BLACK;
398
+ p.color = BLACK;
551
399
  p.right = repaint(RED, s);
552
400
  return;
553
401
  }
@@ -562,10 +410,10 @@ function fixDoubleBlack(stack) {
562
410
  s = cloneNode(s);
563
411
  p.right = s.left;
564
412
  s.left = p;
565
- s._color = p._color;
566
- p._color = RED;
413
+ s.color = p.color;
414
+ p.color = RED;
567
415
  if (i > 1) {
568
- var pp = stack[i - 2];
416
+ const pp = stack[i - 2];
569
417
  if (pp.left === p) {
570
418
  pp.left = s;
571
419
  }
@@ -587,19 +435,19 @@ function fixDoubleBlack(stack) {
587
435
  else {
588
436
  //console.log("right child")
589
437
  s = p.left;
590
- if (s.left && s.left._color === RED) {
591
- //console.log("case 1: left sibling child red", p.value, p._color)
438
+ if (s.left && s.left.color === RED) {
439
+ //console.log("case 1: left sibling child red", p.value, p.color)
592
440
  s = p.left = cloneNode(s);
593
441
  z = s.left = cloneNode(s.left);
594
442
  p.left = s.right;
595
443
  s.right = p;
596
444
  s.left = z;
597
- s._color = p._color;
598
- n._color = BLACK;
599
- p._color = BLACK;
600
- z._color = BLACK;
445
+ s.color = p.color;
446
+ n.color = BLACK;
447
+ p.color = BLACK;
448
+ z.color = BLACK;
601
449
  if (i > 1) {
602
- var pp = stack[i - 2];
450
+ const pp = stack[i - 2];
603
451
  if (pp.right === p) {
604
452
  pp.right = s;
605
453
  }
@@ -610,7 +458,7 @@ function fixDoubleBlack(stack) {
610
458
  stack[i - 1] = s;
611
459
  return;
612
460
  }
613
- else if (s.right && s.right._color === RED) {
461
+ else if (s.right && s.right.color === RED) {
614
462
  //console.log("case 1: right sibling child red")
615
463
  s = p.left = cloneNode(s);
616
464
  z = s.right = cloneNode(s.right);
@@ -618,12 +466,12 @@ function fixDoubleBlack(stack) {
618
466
  s.right = z.left;
619
467
  z.right = p;
620
468
  z.left = s;
621
- z._color = p._color;
622
- p._color = BLACK;
623
- s._color = BLACK;
624
- n._color = BLACK;
469
+ z.color = p.color;
470
+ p.color = BLACK;
471
+ s.color = BLACK;
472
+ n.color = BLACK;
625
473
  if (i > 1) {
626
- var pp = stack[i - 2];
474
+ const pp = stack[i - 2];
627
475
  if (pp.right === p) {
628
476
  pp.right = z;
629
477
  }
@@ -634,10 +482,10 @@ function fixDoubleBlack(stack) {
634
482
  stack[i - 1] = z;
635
483
  return;
636
484
  }
637
- if (s._color === BLACK) {
638
- if (p._color === RED) {
485
+ if (s.color === BLACK) {
486
+ if (p.color === RED) {
639
487
  //console.log("case 2: black sibling, red parent")
640
- p._color = BLACK;
488
+ p.color = BLACK;
641
489
  p.left = repaint(RED, s);
642
490
  return;
643
491
  }
@@ -652,10 +500,10 @@ function fixDoubleBlack(stack) {
652
500
  s = cloneNode(s);
653
501
  p.left = s.right;
654
502
  s.right = p;
655
- s._color = p._color;
656
- p._color = RED;
503
+ s.color = p.color;
504
+ p.color = RED;
657
505
  if (i > 1) {
658
- var pp = stack[i - 2];
506
+ const pp = stack[i - 2];
659
507
  if (pp.right === p) {
660
508
  pp.right = s;
661
509
  }
@@ -676,236 +524,127 @@ function fixDoubleBlack(stack) {
676
524
  }
677
525
  }
678
526
  }
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];
527
+ /** Iterates through the nodes in a red-black tree. */
528
+ export class RedBlackTreeIterator {
529
+ constructor(
530
+ /** The tree associated with the iterator. */
531
+ tree, stack) {
532
+ this.tree = tree;
533
+ this.stack = stack;
722
534
  }
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;
535
+ /**
536
+ * Removes the iterator's current item form the tree.
537
+ *
538
+ * @returns A new binary search tree with the item removed.
539
+ */
540
+ remove() {
541
+ const stack = this.stack;
542
+ if (stack.length === 0) {
543
+ return this.tree;
732
544
  }
733
- else if (p.right === n) {
734
- p.right = null;
545
+ //First copy path to node
546
+ const cstack = new Array(stack.length);
547
+ let n = stack[stack.length - 1];
548
+ cstack[cstack.length - 1] = new RBNode(n.color, n.key, n.value, n.left, n.right);
549
+ let i;
550
+ for (i = stack.length - 2; i >= 0; --i) {
551
+ n = stack[i];
552
+ if (n.left === stack[i + 1]) {
553
+ cstack[i] = new RBNode(n.color, n.key, n.value, cstack[i + 1], n.right);
554
+ }
555
+ else {
556
+ cstack[i] = new RBNode(n.color, n.key, n.value, n.left, cstack[i + 1]);
557
+ }
735
558
  }
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]);
559
+ //Get node
560
+ n = cstack[cstack.length - 1];
561
+ //console.log("start remove: ", n.value)
562
+ //If not leaf, then swap with previous node
563
+ if (n.left && n.right) {
564
+ //console.log("moving to leaf")
565
+ //First walk to previous leaf
566
+ const split = cstack.length;
567
+ n = n.left;
568
+ while (n.right) {
569
+ cstack.push(n);
570
+ n = n.right;
571
+ }
572
+ //Copy path to leaf
573
+ const v = cstack[split - 1];
574
+ cstack.push(new RBNode(n.color, v.key, v.value, n.left, n.right));
575
+ cstack[split - 1].key = n.key;
576
+ cstack[split - 1].value = n.value;
577
+ //Fix up stack
578
+ for (i = cstack.length - 2; i >= split; --i) {
579
+ n = cstack[i];
580
+ cstack[i] = new RBNode(n.color, n.key, n.value, n.left, cstack[i + 1]);
581
+ }
582
+ cstack[split - 1].left = cstack[split];
752
583
  }
753
- else if (cstack.length === 1) {
754
- //Third easy case: root
755
- //console.log("ROOT")
756
- return new RedBlackTree(this.tree._compare, null);
584
+ //console.log("stack=", cstack.map(function(v) { return v.value }))
585
+ //Remove leaf node
586
+ n = cstack[cstack.length - 1];
587
+ if (n.color === RED) {
588
+ //Easy case: removing red leaf
589
+ //console.log("RED leaf")
590
+ const p = cstack[cstack.length - 2];
591
+ if (p.left === n) {
592
+ p.left = null;
593
+ }
594
+ else if (p.right === n) {
595
+ p.right = null;
596
+ }
597
+ cstack.pop();
598
+ return new RedBlackTree(this.tree.compare, cstack[0]);
757
599
  }
758
600
  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;
601
+ if (n.left || n.right) {
602
+ //Second easy case: Single child black parent
603
+ //console.log("BLACK single child")
604
+ if (n.left) {
605
+ swapNode(n, n.left);
606
+ }
607
+ else if (n.right) {
608
+ swapNode(n, n.right);
609
+ }
610
+ //Child must be red, so repaint it black to balance color
611
+ n.color = BLACK;
612
+ return new RedBlackTree(this.tree.compare, cstack[0]);
613
+ }
614
+ else if (cstack.length === 1) {
615
+ //Third easy case: root
616
+ //console.log("ROOT")
617
+ return new RedBlackTree(this.tree.compare, null);
766
618
  }
767
619
  else {
768
- parent.right = null;
620
+ //Hard case: Repaint n, and then do some nasty stuff
621
+ //console.log("BLACK leaf no children")
622
+ const parent = cstack[cstack.length - 2];
623
+ fixDoubleBlack(cstack);
624
+ //Fix up links
625
+ if (parent.left === n) {
626
+ parent.left = null;
627
+ }
628
+ else {
629
+ parent.right = null;
630
+ }
769
631
  }
770
632
  }
633
+ return new RedBlackTree(this.tree.compare, cstack[0]);
771
634
  }
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;
635
+ /** The key of the iterator's current item. */
636
+ get key() {
637
+ if (this.stack.length > 0) {
638
+ return this.stack[this.stack.length - 1].key;
779
639
  }
780
640
  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;
641
+ }
642
+ /** The value of the iterator's current item. */
643
+ get value() {
644
+ if (this.stack.length > 0) {
645
+ return this.stack[this.stack.length - 1].value;
789
646
  }
790
647
  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);
648
+ }
910
649
  }
911
650
  //# sourceMappingURL=functional-red-black-tree.js.map