articulated 0.3.0 → 0.4.1

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.
@@ -0,0 +1,911 @@
1
+ "use strict";
2
+ module.exports = createRBTree;
3
+ // Modified from https://github.com/mikolalysenko/functional-red-black-tree/blob/master/rbtree.js
4
+ // 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;
13
+ }
14
+ function cloneNode(node) {
15
+ return new RBNode(node._color, node.key, node.value, node.left, node.right);
16
+ }
17
+ function repaint(color, node) {
18
+ return new RBNode(color, node.key, node.value, node.left, node.right);
19
+ }
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
+ }
64
+ }
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);
73
+ }
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);
82
+ }
83
+ else {
84
+ n_stack[s] = new RBNode(n._color, n.key, n.value, n.left, n_stack[s + 1]);
85
+ }
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;
96
+ }
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
+ }
127
+ }
128
+ 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
+ }
158
+ }
159
+ }
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;
169
+ }
170
+ 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;
185
+ }
186
+ }
187
+ break;
188
+ }
189
+ }
190
+ 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;
198
+ }
199
+ 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;
216
+ }
217
+ }
218
+ break;
219
+ }
220
+ }
221
+ }
222
+ }
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;
404
+ }
405
+ }
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;
425
+ }
426
+ }
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;
448
+ }
449
+ }
450
+ return;
451
+ };
452
+ //Iterator for red black tree
453
+ function RedBlackTreeIterator(tree, stack) {
454
+ this.tree = tree;
455
+ this._stack = stack;
456
+ }
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
+ //Swaps two nodes
479
+ function swapNode(n, v) {
480
+ n.key = v.key;
481
+ n.value = v.value;
482
+ n.left = v.left;
483
+ n.right = v.right;
484
+ n._color = v._color;
485
+ }
486
+ //Fix up a double black node in a tree
487
+ function fixDoubleBlack(stack) {
488
+ var n, p, s, z;
489
+ for (var i = stack.length - 1; i >= 0; --i) {
490
+ n = stack[i];
491
+ if (i === 0) {
492
+ n._color = BLACK;
493
+ return;
494
+ }
495
+ //console.log("visit node:", n.key, i, stack[i].key, stack[i-1].key)
496
+ p = stack[i - 1];
497
+ if (p.left === n) {
498
+ //console.log("left child")
499
+ s = p.right;
500
+ if (s.right && s.right._color === RED) {
501
+ //console.log("case 1: right sibling child red")
502
+ s = p.right = cloneNode(s);
503
+ z = s.right = cloneNode(s.right);
504
+ p.right = s.left;
505
+ s.left = p;
506
+ s.right = z;
507
+ s._color = p._color;
508
+ n._color = BLACK;
509
+ p._color = BLACK;
510
+ z._color = BLACK;
511
+ if (i > 1) {
512
+ var pp = stack[i - 2];
513
+ if (pp.left === p) {
514
+ pp.left = s;
515
+ }
516
+ else {
517
+ pp.right = s;
518
+ }
519
+ }
520
+ stack[i - 1] = s;
521
+ return;
522
+ }
523
+ else if (s.left && s.left._color === RED) {
524
+ //console.log("case 1: left sibling child red")
525
+ s = p.right = cloneNode(s);
526
+ z = s.left = cloneNode(s.left);
527
+ p.right = z.left;
528
+ s.left = z.right;
529
+ z.left = p;
530
+ z.right = s;
531
+ z._color = p._color;
532
+ p._color = BLACK;
533
+ s._color = BLACK;
534
+ n._color = BLACK;
535
+ if (i > 1) {
536
+ var pp = stack[i - 2];
537
+ if (pp.left === p) {
538
+ pp.left = z;
539
+ }
540
+ else {
541
+ pp.right = z;
542
+ }
543
+ }
544
+ stack[i - 1] = z;
545
+ return;
546
+ }
547
+ if (s._color === BLACK) {
548
+ if (p._color === RED) {
549
+ //console.log("case 2: black sibling, red parent", p.right.value)
550
+ p._color = BLACK;
551
+ p.right = repaint(RED, s);
552
+ return;
553
+ }
554
+ else {
555
+ //console.log("case 2: black sibling, black parent", p.right.value)
556
+ p.right = repaint(RED, s);
557
+ continue;
558
+ }
559
+ }
560
+ else {
561
+ //console.log("case 3: red sibling")
562
+ s = cloneNode(s);
563
+ p.right = s.left;
564
+ s.left = p;
565
+ s._color = p._color;
566
+ p._color = RED;
567
+ if (i > 1) {
568
+ var pp = stack[i - 2];
569
+ if (pp.left === p) {
570
+ pp.left = s;
571
+ }
572
+ else {
573
+ pp.right = s;
574
+ }
575
+ }
576
+ stack[i - 1] = s;
577
+ stack[i] = p;
578
+ if (i + 1 < stack.length) {
579
+ stack[i + 1] = n;
580
+ }
581
+ else {
582
+ stack.push(n);
583
+ }
584
+ i = i + 2;
585
+ }
586
+ }
587
+ else {
588
+ //console.log("right child")
589
+ s = p.left;
590
+ if (s.left && s.left._color === RED) {
591
+ //console.log("case 1: left sibling child red", p.value, p._color)
592
+ s = p.left = cloneNode(s);
593
+ z = s.left = cloneNode(s.left);
594
+ p.left = s.right;
595
+ s.right = p;
596
+ s.left = z;
597
+ s._color = p._color;
598
+ n._color = BLACK;
599
+ p._color = BLACK;
600
+ z._color = BLACK;
601
+ if (i > 1) {
602
+ var pp = stack[i - 2];
603
+ if (pp.right === p) {
604
+ pp.right = s;
605
+ }
606
+ else {
607
+ pp.left = s;
608
+ }
609
+ }
610
+ stack[i - 1] = s;
611
+ return;
612
+ }
613
+ else if (s.right && s.right._color === RED) {
614
+ //console.log("case 1: right sibling child red")
615
+ s = p.left = cloneNode(s);
616
+ z = s.right = cloneNode(s.right);
617
+ p.left = z.right;
618
+ s.right = z.left;
619
+ z.right = p;
620
+ z.left = s;
621
+ z._color = p._color;
622
+ p._color = BLACK;
623
+ s._color = BLACK;
624
+ n._color = BLACK;
625
+ if (i > 1) {
626
+ var pp = stack[i - 2];
627
+ if (pp.right === p) {
628
+ pp.right = z;
629
+ }
630
+ else {
631
+ pp.left = z;
632
+ }
633
+ }
634
+ stack[i - 1] = z;
635
+ return;
636
+ }
637
+ if (s._color === BLACK) {
638
+ if (p._color === RED) {
639
+ //console.log("case 2: black sibling, red parent")
640
+ p._color = BLACK;
641
+ p.left = repaint(RED, s);
642
+ return;
643
+ }
644
+ else {
645
+ //console.log("case 2: black sibling, black parent")
646
+ p.left = repaint(RED, s);
647
+ continue;
648
+ }
649
+ }
650
+ else {
651
+ //console.log("case 3: red sibling")
652
+ s = cloneNode(s);
653
+ p.left = s.right;
654
+ s.right = p;
655
+ s._color = p._color;
656
+ p._color = RED;
657
+ if (i > 1) {
658
+ var pp = stack[i - 2];
659
+ if (pp.right === p) {
660
+ pp.right = s;
661
+ }
662
+ else {
663
+ pp.left = s;
664
+ }
665
+ }
666
+ stack[i - 1] = s;
667
+ stack[i] = p;
668
+ if (i + 1 < stack.length) {
669
+ stack[i + 1] = n;
670
+ }
671
+ else {
672
+ stack.push(n);
673
+ }
674
+ i = i + 2;
675
+ }
676
+ }
677
+ }
678
+ }
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];
722
+ }
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;
732
+ }
733
+ else if (p.right === n) {
734
+ p.right = null;
735
+ }
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]);
752
+ }
753
+ else if (cstack.length === 1) {
754
+ //Third easy case: root
755
+ //console.log("ROOT")
756
+ return new RedBlackTree(this.tree._compare, null);
757
+ }
758
+ 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;
766
+ }
767
+ else {
768
+ parent.right = null;
769
+ }
770
+ }
771
+ }
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;
779
+ }
780
+ 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;
789
+ }
790
+ 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);
910
+ }
911
+ //# sourceMappingURL=functional-red-black-tree.js.map