1package ds.persistent.map;
2
3
4
5
6
7
8
9
10
11
12
13import ds.interfaces.Map;
14
15import ds.util.K;
16import ds.util.V;
17import ds.util.KV;
18import ds.util.Queue;
19import ds.util.Function2;
20import ds.util.NullIterator;
21
22import static ds.util.KV.mkPair;
23import static ds.util.Boolean.toInt;
24import static ds.util.Integer.max;
25import static ds.util.Integer.min;
26import static ds.util.Undef.undefined;
27
28import java.util.Iterator;
29
30import static java.lang.Integer.signum;
31
32
33
34public abstract
35 class RedBlackTree
36 implements Map {
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public static
54 RedBlackTree empty() {
55 return
56 EMPTY;
57 }
58
59
60 public static
61 RedBlackTree singleton(K k, V v) {
62 return
63 empty().insert(k, v);
64 }
65
66
67 public static
68 RedBlackTree fromIterator(Iterator<KV> elems) {
69
70 RedBlackTree res = empty();
71 while ( elems.hasNext() ) {
72 KV p = elems.next();
73 res = res.insert(p.fst, p.snd);
74 }
75 return
76 res;
77 }
78
79 public RedBlackTree
80 union(Map m2) {
81 return
82 unionWith(const2, m2);
83 }
84
85
86 public RedBlackTree
87 unionWith(Function2<V,V,V> op,
88 Map m2) {
89 Iterator<KV> i = m2.iterator();
90 RedBlackTree res = this;
91
92 while ( i.hasNext() ) {
93 KV kv2 = i.next();
94 K k2 = kv2.fst;
95 V v2 = kv2.snd;
96 V v1 = res.lookup(k2);
97 V vr = v1 == null ? v2 : op.apply(v1, v2);
98 res = res.insert(k2, vr);
99 }
100 return
101 res;
102 }
103
104 public RedBlackTree
105 difference(Map m2) {
106 return
107 differenceWith(null2, m2);
108 }
109
110
111 public RedBlackTree
112 differenceWith(Function2<V,V,V> op,
113 Map m2) {
114
115 Iterator<KV> i = m2.iterator();
116 RedBlackTree res = this;
117
118 while ( i.hasNext() ) {
119 KV kv2 = i.next();
120 K k2 = kv2.fst;
121 V v2 = kv2.snd;
122 V v1 = res.lookup(k2);
123
124 if ( v1 != null ) {
125 V vr = op.apply(v1, v2);
126 if ( vr == null )
127 res = res.remove(k2);
128 else
129 res = res.insert(k2, vr);
130 }
131 }
132 return
133 res;
134 }
135
136 public RedBlackTree copy() {
137 return
138 this;
139 }
140
141
142
143
144 abstract public int depth();
145 abstract public int minDepth();
146
147 public boolean member(K k) {
148 return
149 lookup(k) != null;
150 }
151
152
153
154
155
156 Node node() { return nodeExpected(); }
157 int color() { return nodeExpected(); }
158 K key() { return nodeExpected(); }
159 V value() { return nodeExpected(); }
160 RedBlackTree left() { return nodeExpected(); }
161 RedBlackTree right() { return nodeExpected(); }
162
163
164 public RedBlackTree insert(K k, V v) {
165 assert k != null;
166
167 return
168 insert1(k, v).paintItBlack();
169 }
170
171 public RedBlackTree remove(K k) {
172 assert k != null;
173
174 return
175 remove1(k).paintItBlack();
176 }
177
178
179
180 abstract public Iterator<KV> iteratorDesc();
181
182 public String toString() {
183 return
184 iterator().toString();
185 }
186
187 public boolean inv() {
188 return
189 invOrdered()
190 &&
191 invRedWithBlackChildren()
192 &&
193 noOfBlackNodes() != -1
194 &&
195 isBlack();
196 }
197
198
199
200
201
202 abstract RedBlackTree insert1(K k, V v);
203 abstract RedBlackTree remove1(K k);
204
205 abstract boolean invRedWithBlackChildren();
206 abstract int noOfBlackNodes();
207 abstract boolean invOrdered();
208 abstract boolean allLS(K k);
209 abstract boolean allGT(K k);
210
211
212 private static <A> A nodeExpected() {
213 return
214 undefined("Node expected");
215 }
216
217 private static Function2<V,V,V> const2
218 = new Function2<V,V,V>() {
219 public V apply(V x, V y) {
220 return y;
221 }
222 };
223
224 private static Function2<V,V,V> null2
225 = new Function2<V,V,V>() {
226 public V apply(V x, V y) {
227 return null;
228 }
229 };
230
231
232
233
234 static final int NEGATIVE_BLACK = -1;
235 static final int RED = 0;
236 static final int BLACK = 1;
237 static final int DOUBLE_BLACK = 2;
238
239 static int blacker(int c) {
240 assert c < DOUBLE_BLACK;
241 return
242 c + 1;
243 }
244
245 static int redder(int c) {
246 assert c > NEGATIVE_BLACK;
247 return
248 c - 1;
249 }
250
251 boolean isRed() { return color() == RED; }
252 boolean isBlack() { return color() == BLACK; }
253 boolean isDoubleBlack() { return color() == DOUBLE_BLACK; }
254 boolean isNegativeBlack() { return color() == NEGATIVE_BLACK; }
255 boolean isEmptyDoubleBlack() { return false; }
256
257 abstract RedBlackTree paintItRed();
258 abstract RedBlackTree paintItBlack();
259
260 abstract RedBlackTree blacker();
261 abstract RedBlackTree redder();
262
263
264
265
266
267
268 private static final RedBlackTree EMPTY
269 = new Empty();
270
271
272
273 private static
274 class Empty extends RedBlackTree {
275
276 public boolean isEmpty() {
277 return true;
278 }
279
280 public int size() {
281 return 0;
282 }
283
284 public int depth() {
285 return 0;
286 }
287
288 public int minDepth() {
289 return 0;
290 }
291
292 public V lookup(K k) {
293 return null;
294 }
295
296 public KV findMin() {
297 return nodeExpected();
298 }
299
300 public KV findMax() {
301 return nodeExpected();
302 }
303
304 public Iterator<KV> iterator() {
305 ++cntIter;
306 return
307 new NullIterator<KV>();
308 }
309 public Iterator<KV> iteratorDesc() {
310 return
311 iterator();
312 }
313
314
315
316
317
318
319
320
321
322
323
324 Empty() { }
325
326 boolean invRedWithBlackChildren() { return true; }
327 int noOfBlackNodes() { return 1; }
328 boolean invOrdered() { return true; }
329 boolean allLS(K k) { return true; }
330 boolean allGT(K k) { return true; }
331
332 int color() {
333 return BLACK;
334 }
335
336 RedBlackTree insert1(K k, V v) {
337 return
338 new Node(k, v, RED, EMPTY, EMPTY);
339 }
340 RedBlackTree remove1(K k) {
341 return
342 this;
343 }
344 RedBlackTree paintItBlack() {
345 return
346 empty();
347 }
348 RedBlackTree paintItRed() {
349 return
350 undefined("paintItRed on empty tree");
351 }
352 RedBlackTree blacker() {
353 return
354 doubleEmpty();
355 }
356 RedBlackTree redder() {
357 return
358 undefined("redder of empty tree");
359 }
360
361 }
362
363
364
365
366
367 private static
368 RedBlackTree doubleEmpty() {
369 return
370 DOUBLE_EMPTY;
371 }
372
373 private static final RedBlackTree DOUBLE_EMPTY
374 = new DoubleEmpty();
375
376
377
378 private static final
379 class DoubleEmpty extends Empty {
380
381
382
383
384
385
386
387
388 DoubleEmpty() { }
389
390 int color() {
391 return DOUBLE_BLACK;
392 }
393
394 boolean isEmptyDoubleBlack() {
395 return true;
396 }
397
398 RedBlackTree blacker() {
399 return
400 undefined("blacker of double black");
401 }
402 RedBlackTree redder() {
403 return
404 empty();
405 }
406 }
407
408
409
410
411 private static final
412 class Node extends RedBlackTree {
413
414
415 final K k;
416 final V v;
417 final int c;
418 final RedBlackTree l;
419 final RedBlackTree r;
420
421
422
423
424
425
426
427
428
429 Node(K k, V v, int c, RedBlackTree l, RedBlackTree r) {
430 assert k != null;
431
432 this.k = k;
433 this.v = v;
434 this.c = c;
435 this.l = l;
436 this.r = r;
437 ++cntNode;
438 }
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454 private static String c2s(int c) {
455 switch ( c ) {
456 case NEGATIVE_BLACK: return "N";
457 case RED: return "R";
458 case BLACK: return "B";
459 case DOUBLE_BLACK: return "D";
460 }
461 return "";
462 }
463
464
465
466
467 public boolean isEmpty() {
468 return false;
469 }
470
471 public int size() {
472 return
473 1 + l.size() + r.size();
474 }
475
476 public int depth() {
477 return
478 1 + max(l.depth(), r.depth());
479 }
480
481 public int minDepth() {
482 return
483 1 + min(l.minDepth(), r.minDepth());
484 }
485
486 public V lookup(K k) {
487 assert k != null;
488
489 switch (signum(k.compareTo(this.k))) {
490 case -1:
491 return
492 l.lookup(k);
493 case 0:
494 return
495 v;
496 case +1:
497 return
498 r.lookup(k);
499 }
500
501 return
502 null;
503 }
504
505
506
507
508 Node node() { return this; }
509 int color() { return c; }
510 K key() { return k; }
511 V value() { return v; }
512 RedBlackTree left() { return l; }
513 RedBlackTree right() { return r; }
514
515 public KV findMin() {
516 if ( l.isEmpty() )
517 return
518 mkPair(k, v);
519 return
520 l.findMin();
521 }
522
523 public KV findMax() {
524 if ( r.isEmpty() )
525 return
526 mkPair(k, v);
527 return
528 r.findMax();
529 }
530
531 public Iterator<KV> iterator() {
532 ++cntIter;
533 return
534 new NodeIterator(this);
535 }
536
537 public Iterator<KV> iteratorDesc() {
538 ++cntIter;
539 return
540 new NodeIteratorDescending(this);
541 }
542
543
544
545
546 boolean invRedWithBlackChildren() {
547 return
548 ( ! isRed()
549 ||
550 ( l.isBlack() && r.isBlack() ) )
551 &&
552 l.invRedWithBlackChildren()
553 &&
554 r.invRedWithBlackChildren();
555 }
556
557
558 int noOfBlackNodes() {
559 int nl = l.noOfBlackNodes();
560 int nr = r.noOfBlackNodes();
561 return
562 (nl == nr && nl != -1)
563 ? nl + toInt(isBlack())
564 : -1;
565 }
566
567 boolean invOrdered() {
568 return
569 l.allLS(k)
570 &&
571 r.allGT(k)
572 &&
573 l.invOrdered()
574 &&
575 r.invOrdered();
576 }
577
578 boolean allLS(K k) {
579 return
580 this.k.compareTo(k) < 0
581 &&
582 r.allLS(k)
583
584
585 ;
586 }
587 boolean allGT(K k) {
588 return
589 this.k.compareTo(k) > 0
590 &&
591 l.allGT(k)
592
593
594 ;
595 }
596
597
598
599
600
601
602
603
604 RedBlackTree paintItBlack() {
605 return
606 setColor(BLACK);
607 }
608 RedBlackTree paintItRed() {
609 return
610 setColor(RED);
611 }
612 RedBlackTree blacker() {
613 return
614 setColor(blacker(color()));
615 }
616 RedBlackTree redder() {
617 return
618 setColor(redder(color()));
619 }
620
621
622
623
624 Node balance(int c, RedBlackTree t1, K k, V v, RedBlackTree t2) {
625 if ( c == BLACK )
626 return
627 balanceBlack(t1, k, v, t2);
628
629
630 if ( c == DOUBLE_BLACK )
631 return
632 balanceDoubleBlack(t1, k, v, t2);
633
634
635 return
636 set(k, v, c, t1, t2);
637 }
638
639
640
641 Node balanceBlack(RedBlackTree l, K k, V v, RedBlackTree r) {
642
643
644 if ( l.isRed() ) {
645 Node ln = l.node();
646 if ( ln.l.isRed() ) {
647 Node lln = ln.l.node();
648 return
649 build3(RED, lln.l, lln.k, lln.v,
650 lln.r, ln.k, ln.v,
651 ln.r, k, v, r, ln, lln);
652 }
653 if ( ln.r.isRed() ) {
654 Node lrn = ln.r.node();
655 return
656 build3(RED, ln.l, ln.k, ln.v,
657 lrn.l, lrn.k, lrn.v,
658 lrn.r, k, v, r, ln, lrn);
659 }
660 }
661 if ( r.isRed() ) {
662 Node rn = r.node();
663 if ( rn.l.isRed() ) {
664 Node rln = rn.l.node();
665 return
666 build3(RED,
667 l, k, v,
668 rln.l, rln.k, rln.v,
669 rln.r, rn.k, rn.v,
670 rn.r,
671 rln, rn);
672 }
673 if ( rn.r.isRed() ) {
674 Node rrn = rn.r.node();
675 return
676 build3(RED,
677 l, k, v,
678 rn.l, rn.k, rn.v,
679 rrn.l, rrn.k, rrn.v,
680 rrn.r,
681 rrn, rn);
682 }
683 }
684 return
685 set(k, v, BLACK, l, r);
686 }
687
688 Node balanceDoubleBlack(RedBlackTree l, K k, V v, RedBlackTree r) {
689
690
691 if ( l.isRed() ) {
692 Node ln = l.node();
693 if ( ln.l.isRed() ) {
694 Node lln = ln.l.node();
695 return
696 build3(BLACK,
697 lln.l, lln.k, lln.v,
698 lln.r, ln.k, ln.v,
699 ln.r, k, v,
700 r,
701 ln, lln);
702 }
703 if ( ln.r.isRed() ) {
704 Node lrn = ln.r.node();
705 return
706 build3(BLACK,
707 ln.l, ln.k, ln.v,
708 lrn.l, lrn.k, lrn.v,
709 lrn.r, k, v,
710 r,
711 ln, lrn);
712 }
713 }
714 if ( r.isRed() ) {
715 Node rn = r.node();
716 if ( rn.l.isRed() ) {
717 Node rln = rn.l.node();
718 return
719 build3(BLACK,
720 l, k, v,
721 rln.l, rln.k, rln.v,
722 rln.r, rn.k, rn.v,
723 rn.r,
724 rln, rn);
725 }
726 if ( rn.r.isRed() ) {
727 Node rrn = rn.r.node();
728 return
729 build3(BLACK,
730 l, k, v,
731 rn.l, rn.k, rn.v,
732 rrn.l, rrn.k, rrn.v,
733 rrn.r,
734 rrn, rn);
735 }
736 }
737
738
739 if ( r.isNegativeBlack() ) {
740 Node rn = r.node();
741 if ( rn.l.isBlack()
742 &&
743 rn.r.isBlack() ) {
744 Node rln = rn.l.node();
745 return
746 rln.set(rln.k, rln.v, BLACK,
747 set(k, v, BLACK, l, rln.l),
748 rn.balanceBlack(rln.r, rn.k, rn.v, rn.r.paintItRed()));
749 }
750 }
751 if ( l.isNegativeBlack() ) {
752 Node ln = l.node();
753 if ( ln.l.isBlack()
754 &&
755 ln.r.isBlack() ) {
756 Node lrn = ln.r.node();
757 return
758 lrn.set(lrn.k, lrn.v, BLACK,
759 ln.balanceBlack(ln.l.paintItRed(), ln.k, ln.v, lrn.l),
760 set(k, v, BLACK, l, lrn.r));
761 }
762 }
763 return
764 set(k, v, DOUBLE_BLACK, l, r);
765 }
766
767 Node bubble(int c, RedBlackTree l, K k, V v, RedBlackTree r) {
768 if ( l.isDoubleBlack()
769 ||
770 r.isDoubleBlack() ) {
771 return
772 balance(blacker(c), l.redder(), k, v, r.redder());
773 }
774 return
775 balance(c, l, k, v, r);
776 }
777
778
779
780
781
782
783
784 Node build3(int rootColor,
785 RedBlackTree a, K xk, V xv,
786 RedBlackTree b, K yk, V yv,
787 RedBlackTree c, K zk, V zv,
788 RedBlackTree d,
789 Node l, Node r) {
790 return
791 set(yk, yv, rootColor,
792 l.set(xk, xv, BLACK, a, b),
793 r.set(zk, zv, BLACK, c, d));
794 }
795
796
797
798
799 private Node set(K k, V v, int c,
800 RedBlackTree l,
801 RedBlackTree r) {
802
803 if ( k == this.k && v == this.v
804 &&
805 c == this.c
806 &&
807 l == this.l && r == this.r )
808 return
809 this;
810 return
811 new Node(k, v, c, l, r);
812
813
814
815
816
817
818
819
820
821
822 }
823 private Node setV(V v) {
824
825 return
826 ( v == this.v )
827 ? this
828 : new Node(this.k, v, this.c, this.l, this.r);
829
830
831
832
833
834
835 }
836
837 private Node setColor(int c) {
838
839 return
840 c == this.c
841 ? this
842 : new Node(this.k, this.v, c, this.l, this.r);
843
844
845
846
847
848
849 }
850
851
852
853
854 RedBlackTree insert1(K k, V v) {
855 switch ( signum(k.compareTo(this.k)) ) {
856 case -1:
857 return
858 balance(c, l.insert1(k, v), this.k, this.v, r);
859 case 0:
860 return
861 setV(v);
862 case +1:
863 return
864 balance(c, l, this.k, this.v, r.insert1(k, v));
865 }
866
867 return
868 null;
869 }
870
871 RedBlackTree remove1(K k) {
872 switch ( signum(k.compareTo(this.k)) ) {
873 case -1:
874 return
875 bubble(c, l.remove1(k), this.k, this.v, r);
876 case 0:
877 return
878 removeRoot();
879
880 case +1:
881 return
882 bubble(c, l, this.k, this.v, r.remove1(k));
883 }
884
885 return
886 null;
887 }
888
889 RedBlackTree removeRoot() {
890 if ( isRed()
891 &&
892 l.isEmpty()
893 &&
894 r.isEmpty()
895 )
896 return
897 empty();
898 if ( isBlack() ) {
899 if ( l.isEmpty()
900 &&
901 r.isEmpty() )
902 return
903 doubleEmpty();
904 if ( l.isRed()
905 &&
906 r.isEmpty() )
907 return
908 l.blacker();
909 if ( r.isRed()
910 &&
911 l.isEmpty() )
912 return
913 r.blacker();
914 }
915 KV p = l.findMax();
916 return
917 bubble(c, l.node().removeMax(), p.fst, p.snd, r);
918 }
919
920 RedBlackTree removeMax() {
921 if ( r.isEmpty() )
922 return
923 removeRoot();
924 return
925 bubble(c, l, k, v, r.node().removeMax());
926 }
927
928
929
930
931
932
933 private static
934 class NodeIterator
935 extends ds.util.Iterator<KV> {
936
937 Queue queue;
938
939 NodeIterator(Node n) {
940 queue = Queue.empty();
941 add(n);
942 ++cntIter;
943 }
944
945 void add(Node n) {
946 queue = queue.cons(n);
947 if ( ! n.l.isEmpty() )
948 add(n.l.node());
949 }
950
951 void addSubNodes(Node n) {
952 if ( ! n.r.isEmpty() )
953 add(n.r.node());
954 }
955
956 public boolean hasNext() {
957 return
958 ! queue.isEmpty();
959 }
960
961 public KV next() {
962 if ( queue.isEmpty() )
963 return
964 undefined("empty tree");
965
966 Node n = (Node)queue.head();
967 queue = queue.tail();
968 addSubNodes(n);
969 return
970 mkPair(n.k, n.v);
971 }
972 }
973
974
975
976 private
977 class NodeIteratorDescending
978 extends NodeIterator {
979
980 NodeIteratorDescending(Node n) {
981 super(n);
982 }
983
984 void add(Node n) {
985 queue = queue.cons(n);
986 if ( ! n.r.isEmpty() )
987 add(n.r.node());
988 }
989
990 void addSubNodes(Node n) {
991 if ( ! n.l.isEmpty() )
992 add(n.l.node());
993 }
994 }
995 }
996
997
998
999
1000 private static int cntNode = 0;
1001 private static int cntIter = 0;
1002
1003 public static String stats() {
1004 return
1005 "stats for ds.persistent.map.RedBlackTree:\n" +
1006 "# new Node() : " + cntNode + "\n" +
1007 "# new Iterator() : " + cntIter + "\n";
1008 }
1009
1010 public String objStats() {
1011 int s = size();
1012 int o = s;
1013 int f = 5 * s;
1014 int m = o + f;
1015
1016 return
1017 "mem stats for ds.persistent.map.RedBlackTree object:\n" +
1018 "# elements (size) : " + s + "\n" +
1019 "# objects : " + o + "\n" +
1020 "# fields : " + f + "\n" +
1021 "# mem words : " + m + "\n";
1022 }
1023}