comparison doodle/containers/tree_set.d @ 40:1f97022e5c6d

Checkpoint. Development continues...
author daveb
date Mon, 12 Apr 2010 14:01:54 +0930
parents
children
comparison
equal deleted inserted replaced
39:b6c34f1fc7f3 40:1f97022e5c6d
1 module delve.util.set;
2
3 class Set(T) {
4 this() {
5 }
6
7 bool isEmpty() {
8 return _root is null;
9 }
10
11 size_t size() {
12 return 0; // FIXME
13 }
14
15 // Error if already present
16 void add(T t) {
17 }
18
19 // Error if not present
20 void remove(T t) {
21 }
22
23 bool contains(T t) {
24 return false; // FIXME
25 }
26
27 void clear() {
28 }
29
30 int opApply(int delegate (inout T) dg) {
31 return 0; // FIXME
32 }
33
34 /*
35 void erase(Iterator iter) {
36 }
37
38 class Iterator {
39 T element();
40
41 void goNext() {
42 }
43
44 void goPrevious() {
45 }
46
47 bool nextValid() {
48 }
49
50 bool previousValid() {
51 }
52
53 Cell _cell;
54 }
55 */
56
57 private {
58 void _add(T t) {
59 if (_root is null) {
60 _root = new Cell(t);
61 }
62 else {
63 }
64
65 ++_size;
66 }
67
68 class Cell {
69 static bool RED = false;
70 static bool BLACK = true;
71
72 /**
73 * The node color (RED, BLACK)
74 **/
75
76 bool color_;
77
78 /**
79 * Pointer to left child
80 **/
81
82 Cell left_;
83
84 /**
85 * Pointer to right child
86 **/
87
88 Cell right_;
89
90 T _element;
91
92 /**
93 * Pointer to parent (null if root)
94 **/
95
96 private Cell parent_;
97
98 /**
99 * Make a new Cell with given element, null links, and BLACK color.
100 * Normally only called to establish a new root.
101 **/
102
103 public this (T element) {
104 _element = element;
105 left_ = null;
106 right_ = null;
107 parent_ = null;
108 color_ = BLACK;
109 }
110
111 /**
112 * Return a new Cell with same element and color as self,
113 * but with null links. (Since it is never OK to have
114 * multiple identical links in a RB tree.)
115 **/
116
117 protected Cell duplicate() {
118 Cell t = new Cell(_element);
119 t.color_ = color_;
120 return t;
121 }
122
123
124 /**
125 * Return left child (or null)
126 **/
127
128 public final Cell left() {
129 return left_;
130 }
131
132 /**
133 * Return right child (or null)
134 **/
135
136 public final Cell right() {
137 return right_;
138 }
139
140 /**
141 * Return parent (or null)
142 **/
143 public final Cell parent() {
144 return parent_;
145 }
146
147
148 /**
149 * See_Also: tango.util.collection.model.View.View.checkImplementation.
150 **/
151 public void checkImplementation() {
152
153 // It's too hard to check the property that every simple
154 // path from node to leaf has same number of black nodes.
155 // So restrict to the following
156
157 assert(parent_ is null || this is parent_.left_ || this is parent_.right_);
158 assert(left_ is null || this is left_.parent_);
159 assert(right_ is null || this is right_.parent_);
160 assert(color_ is BLACK || (colorOf(left_) is BLACK) && (colorOf(right_) is BLACK));
161
162 if (left_ !is null)
163 left_.checkImplementation();
164 if (right_ !is null)
165 right_.checkImplementation();
166 }
167
168 /**
169 * Return the minimum element of the current (sub)tree
170 **/
171
172 public final Cell leftmost() {
173 auto p = this;
174 for ( ; p.left_ !is null; p = p.left_) {
175 }
176 return p;
177 }
178
179 /**
180 * Return the maximum element of the current (sub)tree
181 **/
182 public final Cell rightmost() {
183 auto p = this;
184 for ( ; p.right_ !is null; p = p.right_) {
185 }
186 return p;
187 }
188
189 /**
190 * Return the root (parentless node) of the tree
191 **/
192 public final Cell root() {
193 auto p = this;
194 for ( ; p.parent_ !is null; p = p.parent_) {
195 }
196 return p;
197 }
198
199 /**
200 * Return true if node is a root (i.e., has a null parent)
201 **/
202
203 public final bool isRoot() {
204 return parent_ is null;
205 }
206
207
208 /**
209 * Return the inorder successor, or null if no such
210 **/
211
212 public final Cell successor() {
213 if (right_ !is null)
214 return right_.leftmost();
215 else {
216 auto p = parent_;
217 auto ch = this;
218 while (p !is null && ch is p.right_) {
219 ch = p;
220 p = p.parent_;
221 }
222 return p;
223 }
224 }
225
226 /**
227 * Return the inorder predecessor, or null if no such
228 **/
229
230 public final Cell predecessor() {
231 if (left_ !is null)
232 return left_.rightmost();
233 else
234 {
235 auto p = parent_;
236 auto ch = this;
237 while (p !is null && ch is p.left_)
238 {
239 ch = p;
240 p = p.parent_;
241 }
242 return p;
243 }
244 }
245
246 /**
247 * Return the number of nodes in the subtree
248 **/
249 public final int size() {
250 int c = 1;
251 if (left_ !is null)
252 c += left_.size();
253 if (right_ !is null)
254 c += right_.size();
255 return c;
256 }
257
258
259 /**
260 * Return node of current subtree containing element as element(),
261 * if it exists, else null.
262 * Uses Comparator cmp to find and to check equality.
263 **/
264
265 /+
266 public Cell find(T element, Comparator!(T) cmp) {
267 auto t = this;
268 for (;;) {
269 int diff = cmp.compare(element, t.element());
270 if (diff is 0)
271 return t;
272 else
273 if (diff < 0)
274 t = t.left_;
275 else
276 t = t.right_;
277 if (t is null)
278 break;
279 }
280 return null;
281 }
282
283
284 /**
285 * Return number of nodes of current subtree containing element.
286 * Uses Comparator cmp to find and to check equality.
287 **/
288 public int count(T element, Comparator!(T) cmp) {
289 int c = 0;
290 auto t = this;
291 while (t !is null) {
292 int diff = cmp.compare(element, t.element());
293 if (diff is 0) {
294 ++c;
295 if (t.left_ is null)
296 t = t.right_;
297 else
298 if (t.right_ is null)
299 t = t.left_;
300 else {
301 c += t.right_.count(element, cmp);
302 t = t.left_;
303 }
304 }
305 else
306 if (diff < 0)
307 t = t.left_;
308 else
309 t = t.right_;
310 }
311 return c;
312 }
313 +/
314
315
316
317
318 /**
319 * Return a new subtree containing each element of current subtree
320 **/
321
322 public final Cell copyTree() {
323 auto t = cast(Cell)(duplicate());
324
325 if (left_ !is null) {
326 t.left_ = left_.copyTree();
327 t.left_.parent_ = t;
328 }
329 if (right_ !is null) {
330 t.right_ = right_.copyTree();
331 t.right_.parent_ = t;
332 }
333 return t;
334 }
335
336
337 /**
338 * There's no generic element insertion. Instead find the
339 * place you want to add a node and then invoke insertLeft
340 * or insertRight.
341 * <P>
342 * Insert Cell as the left child of current node, and then
343 * rebalance the tree it is in.
344 * @param Cell the Cell to add
345 * @param root, the root of the current tree
346 * Returns: the new root of the current tree. (Rebalancing
347 * can change the root!)
348 **/
349
350
351 public final Cell insertLeft(Cell Cell, Cell root) {
352 left_ = Cell;
353 Cell.parent_ = this;
354 return Cell.fixAfterInsertion(root);
355 }
356
357 /**
358 * Insert Cell as the right child of current node, and then
359 * rebalance the tree it is in.
360 * @param Cell the Cell to add
361 * @param root, the root of the current tree
362 * Returns: the new root of the current tree. (Rebalancing
363 * can change the root!)
364 **/
365
366 public final Cell insertRight(Cell Cell, Cell root) {
367 right_ = Cell;
368 Cell.parent_ = this;
369 return Cell.fixAfterInsertion(root);
370 }
371
372
373 /**
374 * Delete the current node, and then rebalance the tree it is in
375 * @param root the root of the current tree
376 * Returns: the new root of the current tree. (Rebalancing
377 * can change the root!)
378 **/
379
380
381 public final Cell remove (Cell root) {
382
383 // handle case where we are only node
384 if (left_ is null && right_ is null && parent_ is null)
385 return null;
386
387 // if strictly internal, swap places with a successor
388 if (left_ !is null && right_ !is null) {
389 auto s = successor();
390 // To work nicely with arbitrary subclasses of Cell, we don't want to
391 // just copy successor's fields. since we don't know what
392 // they are. Instead we swap positions _in the tree.
393 root = swapPosition(this, s, root);
394 }
395
396 // Start fixup at replacement node (normally a child).
397 // But if no children, fake it by using self
398
399 if (left_ is null && right_ is null) {
400
401 if (color_ is BLACK)
402 root = this.fixAfterDeletion(root);
403
404 // Unlink (Couldn't before since fixAfterDeletion needs parent ptr)
405
406 if (parent_ !is null) {
407 if (this is parent_.left_)
408 parent_.left_ = null;
409 else
410 if (this is parent_.right_)
411 parent_.right_ = null;
412 parent_ = null;
413 }
414
415 }
416 else {
417 auto replacement = left_;
418 if (replacement is null)
419 replacement = right_;
420
421 // link replacement to parent
422 replacement.parent_ = parent_;
423
424 if (parent_ is null)
425 root = replacement;
426 else
427 if (this is parent_.left_)
428 parent_.left_ = replacement;
429 else
430 parent_.right_ = replacement;
431
432 left_ = null;
433 right_ = null;
434 parent_ = null;
435
436 // fix replacement
437 if (color_ is BLACK)
438 root = replacement.fixAfterDeletion(root);
439
440 }
441
442 return root;
443 }
444
445 /**
446 * Swap the linkages of two nodes in a tree.
447 * Return new root, in case it changed.
448 **/
449
450 static final Cell swapPosition(Cell x, Cell y, Cell root) {
451
452 /* Too messy. TODO: find sequence of assigments that are always OK */
453
454 auto px = x.parent_;
455 bool xpl = px !is null && x is px.left_;
456 auto lx = x.left_;
457 auto rx = x.right_;
458
459 auto py = y.parent_;
460 bool ypl = py !is null && y is py.left_;
461 auto ly = y.left_;
462 auto ry = y.right_;
463
464 if (x is py) {
465 y.parent_ = px;
466 if (px !is null)
467 if (xpl)
468 px.left_ = y;
469 else
470 px.right_ = y;
471 x.parent_ = y;
472 if (ypl) {
473 y.left_ = x;
474 y.right_ = rx;
475 if (rx !is null)
476 rx.parent_ = y;
477 }
478 else {
479 y.right_ = x;
480 y.left_ = lx;
481 if (lx !is null)
482 lx.parent_ = y;
483 }
484 x.left_ = ly;
485 if (ly !is null)
486 ly.parent_ = x;
487 x.right_ = ry;
488 if (ry !is null)
489 ry.parent_ = x;
490 }
491 else
492 if (y is px) {
493 x.parent_ = py;
494 if (py !is null)
495 if (ypl)
496 py.left_ = x;
497 else
498 py.right_ = x;
499 y.parent_ = x;
500 if (xpl) {
501 x.left_ = y;
502 x.right_ = ry;
503 if (ry !is null)
504 ry.parent_ = x;
505 }
506 else {
507 x.right_ = y;
508 x.left_ = ly;
509 if (ly !is null)
510 ly.parent_ = x;
511 }
512 y.left_ = lx;
513 if (lx !is null)
514 lx.parent_ = y;
515 y.right_ = rx;
516 if (rx !is null)
517 rx.parent_ = y;
518 }
519 else {
520 x.parent_ = py;
521 if (py !is null)
522 if (ypl)
523 py.left_ = x;
524 else
525 py.right_ = x;
526 x.left_ = ly;
527 if (ly !is null)
528 ly.parent_ = x;
529 x.right_ = ry;
530 if (ry !is null)
531 ry.parent_ = x;
532
533 y.parent_ = px;
534 if (px !is null)
535 if (xpl)
536 px.left_ = y;
537 else
538 px.right_ = y;
539 y.left_ = lx;
540 if (lx !is null)
541 lx.parent_ = y;
542 y.right_ = rx;
543 if (rx !is null)
544 rx.parent_ = y;
545 }
546
547 bool c = x.color_;
548 x.color_ = y.color_;
549 y.color_ = c;
550
551 if (root is x) {
552 root = y;
553 }
554 else {
555 if (root is y)
556 root = x;
557 }
558 return root;
559 }
560
561
562
563 /**
564 * Return color of node p, or BLACK if p is null
565 * (In the CLR version, they use
566 * a special dummy `nil' node for such purposes, but that doesn't
567 * work well here, since it could lead to creating one such special
568 * node per real node.)
569 *
570 **/
571
572 static final bool colorOf(Cell p) {
573 return (p is null) ? BLACK : p.color_;
574 }
575
576 /**
577 * return parent of node p, or null if p is null
578 **/
579 static final Cell parentOf(Cell p) {
580 return (p is null) ? null : p.parent_;
581 }
582
583 /**
584 * Set the color of node p, or do nothing if p is null
585 **/
586
587 static final void setColor(Cell p, bool c) {
588 if (p !is null)
589 p.color_ = c;
590 }
591
592 /**
593 * return left child of node p, or null if p is null
594 **/
595
596 static final Cell leftOf(Cell p) {
597 return (p is null) ? null : p.left_;
598 }
599
600 /**
601 * return right child of node p, or null if p is null
602 **/
603
604 static final Cell rightOf(Cell p) {
605 return (p is null) ? null : p.right_;
606 }
607
608
609 /** From CLR **/
610 protected final Cell rotateLeft(Cell root) {
611 auto r = right_;
612 right_ = r.left_;
613 if (r.left_ !is null)
614 r.left_.parent_ = this;
615 r.parent_ = parent_;
616 if (parent_ is null)
617 root = r;
618 else {
619 if (parent_.left_ is this)
620 parent_.left_ = r;
621 else
622 parent_.right_ = r;
623 }
624 r.left_ = this;
625 parent_ = r;
626 return root;
627 }
628
629 /** From CLR **/
630 protected final Cell rotateRight(Cell root) {
631 auto l = left_;
632 left_ = l.right_;
633 if (l.right_ !is null)
634 l.right_.parent_ = this;
635 l.parent_ = parent_;
636 if (parent_ is null) {
637 root = l;
638 }
639 else {
640 if (parent_.right_ is this)
641 parent_.right_ = l;
642 else
643 parent_.left_ = l;
644 }
645 l.right_ = this;
646 parent_ = l;
647 return root;
648 }
649
650
651 /** From CLR **/
652 protected final Cell fixAfterInsertion(Cell root) {
653 color_ = RED;
654 auto x = this;
655
656 while (x !is null && x !is root && x.parent_.color_ is RED) {
657 if (parentOf(x) is leftOf(parentOf(parentOf(x)))) {
658 auto y = rightOf(parentOf(parentOf(x)));
659 if (colorOf(y) is RED) {
660 setColor(parentOf(x), BLACK);
661 setColor(y, BLACK);
662 setColor(parentOf(parentOf(x)), RED);
663 x = parentOf(parentOf(x));
664 }
665 else {
666 if (x is rightOf(parentOf(x))) {
667 x = parentOf(x);
668 root = x.rotateLeft(root);
669 }
670 setColor(parentOf(x), BLACK);
671 setColor(parentOf(parentOf(x)), RED);
672 if (parentOf(parentOf(x)) !is null) {
673 root = parentOf(parentOf(x)).rotateRight(root);
674 }
675 }
676 }
677 else {
678 auto y = leftOf(parentOf(parentOf(x)));
679 if (colorOf(y) is RED) {
680 setColor(parentOf(x), BLACK);
681 setColor(y, BLACK);
682 setColor(parentOf(parentOf(x)), RED);
683 x = parentOf(parentOf(x));
684 }
685 else {
686 if (x is leftOf(parentOf(x))) {
687 x = parentOf(x);
688 root = x.rotateRight(root);
689 }
690 setColor(parentOf(x), BLACK);
691 setColor(parentOf(parentOf(x)), RED);
692 if (parentOf(parentOf(x)) !is null)
693 root = parentOf(parentOf(x)).rotateLeft(root);
694 }
695 }
696 }
697 root.color_ = BLACK;
698 return root;
699 }
700
701
702
703 /** From CLR **/
704 protected final Cell fixAfterDeletion(Cell root) {
705 auto x = this;
706 while (x !is root && colorOf(x) is BLACK) {
707 if (x is leftOf(parentOf(x))) {
708 auto sib = rightOf(parentOf(x));
709 if (colorOf(sib) is RED) {
710 setColor(sib, BLACK);
711 setColor(parentOf(x), RED);
712 root = parentOf(x).rotateLeft(root);
713 sib = rightOf(parentOf(x));
714 }
715
716 if (colorOf(leftOf(sib)) is BLACK && colorOf(rightOf(sib)) is BLACK) {
717 setColor(sib, RED);
718 x = parentOf(x);
719 }
720 else {
721 if (colorOf(rightOf(sib)) is BLACK) {
722 setColor(leftOf(sib), BLACK);
723 setColor(sib, RED);
724 root = sib.rotateRight(root);
725 sib = rightOf(parentOf(x));
726 }
727 setColor(sib, colorOf(parentOf(x)));
728 setColor(parentOf(x), BLACK);
729 setColor(rightOf(sib), BLACK);
730 root = parentOf(x).rotateLeft(root);
731 x = root;
732 }
733 }
734 else {
735 auto sib = leftOf(parentOf(x));
736 if (colorOf(sib) is RED) {
737 setColor(sib, BLACK);
738 setColor(parentOf(x), RED);
739 root = parentOf(x).rotateRight(root);
740 sib = leftOf(parentOf(x));
741 }
742 if (colorOf(rightOf(sib)) is BLACK && colorOf(leftOf(sib)) is BLACK) {
743 setColor(sib, RED);
744 x = parentOf(x);
745 }
746 else {
747 if (colorOf(leftOf(sib)) is BLACK) {
748 setColor(rightOf(sib), BLACK);
749 setColor(sib, RED);
750 root = sib.rotateLeft(root);
751 sib = leftOf(parentOf(x));
752 }
753 setColor(sib, colorOf(parentOf(x)));
754 setColor(parentOf(x), BLACK);
755 setColor(leftOf(sib), BLACK);
756 root = parentOf(x).rotateRight(root);
757 x = root;
758 }
759 }
760 }
761 setColor(x, BLACK);
762 return root;
763 }
764 }
765
766 Cell _root;
767 size_t _size;
768 }
769 }
770 unittest {
771 auto s = new Set!(int);
772 }