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