TRIQS/triqs_cthyb 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
rbt.hpp
1/*******************************************************************************
2 *
3 * TRIQS: a Toolbox for Research in Interacting Quantum Systems
4 *
5 * Copyright (C) 2014 by O. Parcollet, M. Ferrero, P. Seth
6 * Adapted from Algorithms (fourth edition) by R. Sedgewick
7 *
8 * TRIQS is free software: you can redistribute it and/or modify it under the
9 * terms of the GNU General Public License as published by the Free Software
10 * Foundation, either version 3 of the License, or (at your option) any later
11 * version.
12 *
13 * TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 * details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * TRIQS. If not, see <http://www.gnu.org/licenses/>.
20 *
21 ******************************************************************************/
22#pragma once
23#include <triqs/utility/first_include.hpp>
24#include <triqs/utility/exceptions.hpp>
25#include <limits>
26#include <iostream>
27#include <stack>
28#include <vector>
29#include "./rbt_iterators.hpp"
30
31namespace triqs {
32 namespace utility {
33
34 struct rbt_insert_error {};
35
36 // Key: must be a regular type, ie. with comparison operators
37 // Value: semi-regular type, wth a reset method void reset (T&&...)
38 // Compare: compare operator for the Keys
39 template <typename Key, typename Value, typename Compare = std::less<Key>> class rb_tree {
40
41 static const bool RED = true;
42 static const bool BLACK = false;
43 Compare compare;
44
45 public:
46 struct node_t;
47 using node = node_t *;
48
49 // node type node_t is inherited from Value, and is the type of the data stored on the node
50 struct node_t : public Value {
51 Key key; // key
52 bool color; // color of parent link
53 int N; // subtree count
54 node left = nullptr, right = nullptr; // links to left and right subtrees
55 bool modified, delete_flag;
56
57 node_t(Key const &key, Value const &val, bool color, int N)
58 : Value(val), key(key), color(color), N(N), left{nullptr}, right{nullptr}, modified(true), delete_flag(false) {}
59
60 node_t(node_t const &n)
61 : Value(n),
62 key(n.key),
63 color(n.color),
64 N(n.N),
65 left(n.left ? new node_t(*n.left) : nullptr),
66 right(n.right ? new node_t(*n.right) : nullptr),
67 modified(n.modified),
68 delete_flag(n.delete_flag) {}
69 node_t &operator=(node_t const &) = delete;
70 template <typename... T> void reset(Key const &k, T &&... x) {
71 key = k;
72 left = nullptr;
73 right = nullptr;
74 Value::reset(std::forward<T>(x)...);
75 }
76 };
77
78 using iterator = detail::rbt_iterator<rb_tree, node>;
79 using const_iterator = detail::rbt_iterator<const rb_tree, const node>;
80 iterator begin() noexcept { return {this, false}; }
81 iterator end() noexcept { return {this, true}; }
82 const_iterator begin() const noexcept { return {this, false}; }
83 const_iterator end() const noexcept { return {this, true}; }
84 const_iterator cbegin() const noexcept { return {this, false}; }
85 const_iterator cend() const noexcept { return {this, true}; }
86
87 /*************************************************************************
88 * Private functions
89 *************************************************************************/
90 private:
91 node root; // root of the BST
92
93 template <typename Fnt> void apply_recursive(Fnt const &f, node n) const {
94 if (n->left) apply_recursive(f, n->left);
95 f(n);
96 if (n->right) apply_recursive(f, n->right);
97 }
98
99 template <typename Fnt> void apply_recursive_reverse(Fnt const &f, node n) const {
100 if (n->right) apply_recursive_reverse(f, n->right);
101 f(n);
102 if (n->left) apply_recursive_reverse(f, n->left);
103 }
104
105 template <typename Fnt> void apply_recursive_subtree_first(Fnt const &f, node n) const {
106 if (n->left) apply_recursive_subtree_first(f, n->left);
107 if (n->right) apply_recursive_subtree_first(f, n->right);
108 f(n);
109 }
110
111 // is node x red; false if x is nullptr ?
112 bool is_red(node x) {
113 if (x == nullptr) return false;
114 return (x->color == RED);
115 }
116
117 // number of node in subtree rooted at x; 0 if x is nullptr
118 int size(node x) const {
119 if (x == nullptr) return 0;
120 return x->N;
121 }
122
123 void rec_free(node n) {
124 if (n == nullptr) return;
125 rec_free(n->left);
126 rec_free(n->right);
127 delete n;
128 }
129
130 /*************************************************************************
131 * Public functions
132 *************************************************************************/
133 public:
134 /*************************************************************************
135 * Foreach functions
136 -- each function starts either at the root or at a given node
137 -- traversal order is different for each function
138 *************************************************************************/
139 // in the order of increasing keys
140 template <typename Fnt> friend void foreach (rb_tree const &tr, Fnt const &f) {
141 if (tr.root) tr.apply_recursive(f, tr.root);
142 }
143 template <typename Fnt> friend void foreach (rb_tree const &tr, node n, Fnt const &f) {
144 if (n) tr.apply_recursive(f, n);
145 }
146
147 // in the order of decreasing keys
148 template <typename Fnt> friend void foreach_reverse(rb_tree const &tr, Fnt const &f) {
149 if (tr.root) tr.apply_recursive_reverse(f, tr.root);
150 }
151 template <typename Fnt> friend void foreach_reverse(rb_tree const &tr, node n, Fnt const &f) {
152 if (n) tr.apply_recursive_reverse(f, n);
153 }
154
155 // in the order left subtree, right subtree, node
156 template <typename Fnt> friend void foreach_subtree_first(rb_tree const &tr, node n, Fnt const &f) {
157 if (n) tr.apply_recursive_subtree_first(f, n);
158 }
159 template <typename Fnt> friend void foreach_subtree_first(rb_tree const &tr, Fnt const &f) { foreach_subtree_first(tr, tr.root, f); }
160
161 rb_tree() : root(nullptr) {}
162 ~rb_tree() { rec_free(root); }
163 //rb_tree(rb_tree const& n) =delete;
164 // not tested enough
165 rb_tree(rb_tree const &n) : compare(n.compare) {
166 if (n.root) root = new node_t(*n.root);
167 }
168
170 int size() const { return size(root); }
172 bool empty() const { return root == nullptr; }
174 node const &get_root() const { return root; }
175 node &get_root() { return root; }
176
178 Compare const &get_comparator() const { return compare; }
179
181 void print(std::ostream &out) const {
182 apply_recursive([&out](node n) { out << n->key << std::endl; }, root);
183 }
184
185 // Simple helper to print a node as double(n->key)
186 struct print_key_as_double {
187 void operator()(std::ostream &os, node n) { os << double(n->key); }
188 };
189
191 template <typename NodePrinter = print_key_as_double> void graphviz(std::ostream &&out, NodePrinter np = {}) const { graphviz(out, np); }
192
193 template <typename NodePrinter = print_key_as_double> void graphviz(std::ostream &out, NodePrinter np = {}) const {
194 auto color_node_to_string = [](node n) -> std::string {
195 if (n->delete_flag) return "green";
196 if (n->modified) return "red";
197 return "black";
198 };
199 out << "digraph G{ graph [ordering=\"out\"];" << std::endl;
200 if (root) {
201 np(out, root);
202 out << "[color = " << color_node_to_string(root) << "];" << std::endl;
203 }
204 auto f = [&out, &color_node_to_string, &np](node n) {
205 if (!n) return;
206 if (n->left) {
207 np(out, n->left);
208 out << "[color = " << color_node_to_string(n->left) << "];\n";
209 np(out, n);
210 out << " -> ";
211 np(out, n->left);
212 out << (n->left->color == RED ? "[color = red];" : ";") << std::endl;
213 }
214 if (n->right) {
215 np(out, n->right);
216 out << "[color = " << color_node_to_string(n->right) << "];\n";
217 np(out, n);
218 out << " -> ";
219 np(out, n->right);
220 out << (n->right->color == RED ? "[color = red];" : ";") << std::endl;
221 }
222 };
223 foreach (*this, f)
224 ;
225 out << "}" << std::endl;
226 }
227
228 void check_no_node_modified() const {
229 foreach_subtree_first(*this, [&](node y) {
230 if (y && y->modified) std::cout << "node modified " << y->key << std::endl;
231 });
232 }
233 void check_no_node_flagged_for_delete() const {
234 foreach_subtree_first(*this, [&](node y) {
235 if (y && y->modified) std::cout << "node flagged for deletion " << y->key << std::endl;
236 });
237 }
238
239 int clear_modified() {
240 int r = clear_modified_impl(root);
241#ifdef TRIQS_RBT_CHECKS
242 check_no_node_modified();
243 check_no_node_flagged_for_delete();
244#endif
245 return r;
246 }
247
248 private:
249 int clear_modified_impl(node n) {
250 int r = 0;
251 if (n && n->modified) {
252 n->modified = false;
253 r++;
254 if (n->delete_flag) TRIQS_RUNTIME_ERROR << " node " << n->key << " is flagged for delete";
255 n->delete_flag = false;
256 r += clear_modified_impl(n->left);
257 r += clear_modified_impl(n->right);
258 }
259 return r;
260 }
261
262 public:
263 /*************************************************************************
264 * Apply a function from root to key (or null)
265 *************************************************************************/
266
267 private:
268 template <typename Fnt> void apply_until_key_impl(node x, Key const &key, Fnt const &f) const {
269 while (x != nullptr) {
270 f(x);
271 if (compare(key, x->key))
272 x = x->left;
273 else if (compare(x->key, key))
274 x = x->right;
275 else
276 return;
277 }
278 }
279
280 public:
281 void set_modified_from_root_to(Key const &key) {
282 apply_until_key_impl(root, key, [](node y) { y->modified = true; });
283 }
284
285 /*************************************************************************
286 * Standard BST search
287 *************************************************************************/
288
289 // value associated with the given key; nullptr if no such key
290 node get(Key const &key) const { return get(root, key); }
291
292 // is there a key-value pair with the given key?
293 bool contains(Key const &key) const { return (get(key) != nullptr); }
294
295 // is there a key-value pair with the given key in the subtree rooted at x?
296 bool contains(node x, Key const &key) const { return (get(x, key) != nullptr); }
297
298 // value associated with the given key in subtree rooted at x; nullptr if no such key
299 private:
300 node get(node x, Key const &key) const {
301 while (x != nullptr) {
302 if (compare(key, x->key))
303 x = x->left;
304 else if (compare(x->key, key))
305 x = x->right;
306 else
307 return x;
308 }
309 return nullptr;
310 }
311 /*************************************************************************
312 * find_if, traversing in an ordered way (traversal order is fixed).
313 *************************************************************************/
314
315 // value associated with the given key; nullptr if no such key
316 template <typename Fnt> friend node find_if(rb_tree const &tr, Fnt f) { return tr.find_if_impl(tr.root, f); }
317
318 // value associated with the given key in subtree rooted at x; nullptr if no such key
319 private:
320 template <typename Fnt> node find_if_impl(node x, Fnt &f) const {
321 if (x == nullptr) return nullptr;
322 auto r = find_if_impl(x->left, f);
323 if (r) return r;
324 if (f(x)) return x;
325 return find_if_impl(x->right, f);
326 }
327
328 /*************************************************************************
329 * Red-black insertion
330 *************************************************************************/
331 public:
332 // insert the key-value pair; overwrite the old value with the new value
333 // if the key is already present
334 void insert(Key const &key, Value const &val) {
335 root = insert(root, key, val);
336 root->color = BLACK;
337 check();
338 }
339
340 private:
341 // insert the key-value pair in the subtree rooted at h
342 node insert(node h, Key const &key, Value const &val) {
343 if (h == nullptr) return new node_t(key, val, true, 1);
344
345 if (compare(key, h->key))
346 h->left = insert(h->left, key, val);
347 else if (compare(h->key, key))
348 h->right = insert(h->right, key, val);
349 else
350 throw rbt_insert_error{};
351
352 // fix-up any right-leaning links
353 if (is_red(h->right) && !is_red(h->left)) h = rotateLeft(h);
354 if (is_red(h->left) && is_red(h->left->left)) h = rotateRight(h);
355 if (is_red(h->left) && is_red(h->right)) flipColors(h);
356 h->N = size(h->left) + size(h->right) + 1;
357
358 h->modified = true;
359 return h;
360 }
361
362 /*************************************************************************
363 * Red-black deletion
364 *************************************************************************/
365 private:
366 // delete the key-value pair with the minimum key rooted at h
367 node deleteMin(node h) {
368 if (h->left == nullptr) {
369 delete h;
370 return nullptr;
371 }
372 if (!is_red(h->left) && !is_red(h->left->left)) h = moveRedLeft(h);
373 h->left = deleteMin(h->left);
374 return balance(h);
375 }
376
377 // delete the key-value pair with the maximum key rooted at h
378 node deleteMax(node h) {
379 if (is_red(h->left)) h = rotateRight(h);
380 if (h->right == nullptr) {
381 // std::cout << " deleting " << h->key << std::endl;
382 delete h;
383 return nullptr;
384 }
385 if (!is_red(h->right) && !is_red(h->right->left)) h = moveRedRight(h);
386 h->right = deleteMax(h->right);
387 return balance(h);
388 }
389
390 public:
391 // delete the key-value pair with the minimum key
392 void deleteMin() {
393 if (empty()) TRIQS_RUNTIME_ERROR << "BST underflow";
394 // if both children of root are black, set root to red
395 if (!is_red(root->left) && !is_red(root->right)) root->color = RED;
396 root = deleteMin(root);
397 if (!empty()) root->color = BLACK;
398 check();
399 }
400
401 // delete the key-value pair with the maximum key
402 void deleteMax() {
403 if (empty()) TRIQS_RUNTIME_ERROR << "BST underflow";
404 // if both children of root are black, set root to red
405 if (!is_red(root->left) && !is_red(root->right)) root->color = RED;
406 root = deleteMax(root);
407 if (!empty()) root->color = BLACK;
408 check();
409 }
410
411 // delete the key-value pair with the given key
412 void delete_node(Key const &key) {
413 if (!contains(key)) TRIQS_RUNTIME_ERROR << "symbol table does not contain " << key;
414 // if both children of root are black, set root to red
415 if (!is_red(root->left) && !is_red(root->right)) root->color = RED;
416 root = delete_node(root, key);
417 if (!empty()) root->color = BLACK;
418 check();
419 }
420
421 private:
422 // delete the key-value pair with the given key rooted at h
423 node delete_node(node h, Key const &key) {
424 if (!contains(h, key)) TRIQS_RUNTIME_ERROR << " oops";
425
426 if (compare(key, h->key)) {
427 if (!is_red(h->left) && !is_red(h->left->left)) h = moveRedLeft(h);
428 h->left = delete_node(h->left, key);
429 } else {
430
431 if (is_red(h->left)) h = rotateRight(h);
432 if (key == h->key && (h->right == nullptr)) {
433 delete h;
434 return nullptr;
435 }
436 if (!is_red(h->right) && !is_red(h->right->left)) h = moveRedRight(h);
437 if (key == h->key) {
438 node x = min(h->right);
439 h->key = x->key;
440 h->Value::operator=(*x);
441 h->modified = true; // not sure it is needed
442 h->delete_flag = false; // CRUCIAL!
443 h->right = deleteMin(h->right);
444 } else
445 h->right = delete_node(h->right, key);
446 }
447 return balance(h);
448 }
449
450 /*************************************************************************
451 * red-black tree helper functions
452 *************************************************************************/
453
454 private:
455 // make a left-leaning link lean to the right
456 node rotateRight(node h) {
457 rbt_assert((h != nullptr) && is_red(h->left));
458 node x = h->left;
459 h->left = x->right;
460 x->right = h;
461 x->color = x->right->color;
462 x->right->color = RED;
463 x->N = h->N;
464 h->N = size(h->left) + size(h->right) + 1;
465 h->modified = true;
466 x->modified = true;
467 return x;
468 }
469
470 // make a right-leaning link lean to the left
471 node rotateLeft(node h) {
472 rbt_assert((h != nullptr) && is_red(h->right));
473 node x = h->right;
474 h->right = x->left;
475 x->left = h;
476 x->color = x->left->color;
477 x->left->color = RED;
478 x->N = h->N;
479 h->N = size(h->left) + size(h->right) + 1;
480 h->modified = true;
481 x->modified = true;
482 return x;
483 }
484
485 // flip the colors of a node and its two children
486 void flipColors(node h) {
487 // h must have opposite color of its two children
488 rbt_assert((h != nullptr) && (h->left != nullptr) && (h->right != nullptr));
489 rbt_assert((!is_red(h) && is_red(h->left) && is_red(h->right)) || ((is_red(h) && !is_red(h->left) && !is_red(h->right))));
490 h->color = !h->color;
491 h->left->color = !h->left->color;
492 h->right->color = !h->right->color;
493 }
494
495 // Assuming that h is red and both h->left and h->left->left
496 // are black, make h->left or one of its children red.
497 node moveRedLeft(node h) {
498 rbt_assert((h != nullptr));
499 rbt_assert(is_red(h) && !is_red(h->left) && !is_red(h->left->left));
500
501 flipColors(h);
502 if (is_red(h->right->left)) {
503 h->right = rotateRight(h->right);
504 h = rotateLeft(h);
505 }
506 return h;
507 }
508
509 // Assuming that h is red and both h->right and h->right->left
510 // are black, make h->right or one of its children red.
511 node moveRedRight(node h) {
512 rbt_assert((h != nullptr));
513 rbt_assert(is_red(h) && !is_red(h->right) && !is_red(h->right->left));
514 flipColors(h);
515 if (is_red(h->left->left)) { h = rotateRight(h); }
516 return h;
517 }
518
519 // restore red-black tree invariant
520 node balance(node h) {
521 rbt_assert((h != nullptr));
522
523 if (is_red(h->right)) h = rotateLeft(h);
524 if (is_red(h->left) && is_red(h->left->left)) h = rotateRight(h);
525 if (is_red(h->left) && is_red(h->right)) flipColors(h);
526
527 h->N = size(h->left) + size(h->right) + 1;
528 h->modified = true;
529 return h;
530 }
531
532 /*************************************************************************
533 * Utility functions
534 *************************************************************************/
535
536 public:
538 int height() const { return height(root); }
539
540 private:
541 int height(node x) const {
542 if (x == nullptr) return -1;
543 return 1 + std::max(height(x->left), height(x->right));
544 }
545
546 /*************************************************************************
547 * Ordered symbol table methods
548 *************************************************************************/
549 public:
551 Key min_key() const {
552 if (empty()) TRIQS_RUNTIME_ERROR << "rbt: taking max_key of an empty tree.";
553 return min(root)->key;
554 }
555
556 Key min_key(node x) const { return min(x)->key; }
557
559 node min(node x) const {
560 rbt_assert(x != nullptr);
561 if (x->left == nullptr)
562 return x;
563 else
564 return min(x->left);
565 }
566
568 Key max_key() const {
569 if (empty()) TRIQS_RUNTIME_ERROR << "rbt: taking max_key of an empty tree.";
570 return max(root)->key;
571 }
572
573 Key max_key(node x) const { return max(x)->key; }
574
576 node max(node x) const {
577 rbt_assert(x != nullptr);
578 if (x->right == nullptr)
579 return x;
580 else
581 return max(x->right);
582 }
583
585 Key floor(Key const &key) const {
586 node x = floor(root, key);
587 if (x == nullptr)
588 return nullptr;
589 else
590 return x->key;
591 }
592
593 private:
594 // the largest key in the subtree rooted at x less than or equal to the given key
595 node floor(node x, Key const &key) const {
596 if (x == nullptr) return nullptr;
597 if (key == x->key) return x;
598 if (compare(key, x->key)) return floor(x->left, key);
599 node t = floor(x->right, key);
600 if (t != nullptr)
601 return t;
602 else
603 return x;
604 }
605
606 public:
608 Key ceiling(Key const &key) const {
609 node x = ceiling(root, key);
610 if (x == nullptr)
611 return nullptr;
612 else
613 return x->key;
614 }
615
616 private:
617 // the smallest key in the subtree rooted at x greater than or equal to the given key
618 node ceiling(node x, Key const &key) const {
619 if (x == nullptr) return nullptr;
620 if (key == x->key) return x;
621 if (compare(x->key, key)) return ceiling(x->right, key);
622 node t = ceiling(x->left, key);
623 if (t != nullptr)
624 return t;
625 else
626 return x;
627 }
628
629 public:
631 Key select(int k) const {
632 if (k < 0 || k >= size()) TRIQS_RUNTIME_ERROR << " unknow key"; // return nullptr;
633 node x = select(root, k);
634 return x->key;
635 }
636
637 private:
638 // the key of rank k in the subtree rooted at x
639 node select(node x, int k) const {
640 rbt_assert(x != nullptr);
641 rbt_assert(k >= 0 && k < size(x));
642 int t = size(x->left);
643 if (t > k)
644 return select(x->left, k);
645 else if (t < k)
646 return select(x->right, k - t - 1);
647 else
648 return x;
649 }
650
651 public:
653 int rank(Key const &key) const { return rank(key, root); }
654
655 private:
656 // number of keys less than key in the subtree rooted at x
657 int rank(Key const &key, node x) const {
658 if (x == nullptr) return 0;
659 if (compare(key, x->key))
660 return rank(key, x->left);
661 else if (compare(x->key, key))
662 return 1 + size(x->left) + rank(key, x->right);
663 else
664 return size(x->left);
665 }
666
667 // TODO this section needs to be reread/redone
668 /*************************************************************************
669 * DEBUG CODE : Check integrity of red-black BST data structure
670 *************************************************************************/
671 private:
672 void rbt_assert(bool c) const {
673 if (!c) TRIQS_RUNTIME_ERROR << "Error";
674 }
675
676 bool check() {
677
678 return true;
679
680 /* if (!isBST()) TRIQS_RUNTIME_ERROR << "Not in symmetric order";
681 if (!isSizeConsistent()) TRIQS_RUNTIME_ERROR << "Subtree counts not consistent";
682 if (!isRankConsistent()) TRIQS_RUNTIME_ERROR << "Ranks not consistent";
683 if (!is23()) TRIQS_RUNTIME_ERROR << "Not a 2-3 tree";
684 if (!isBalanced()) TRIQS_RUNTIME_ERROR << "Not balanced";
685 return isBST() && isSizeConsistent() && isRankConsistent() && is23() && isBalanced();
686 */
687 }
688
689 // does this binary tree satisfy symmetric order?
690 // Note: this test also ensures that data structure is a binary tree since order is strict
691 bool isBST() { return isBST(root, std::numeric_limits<int>::min(), std::numeric_limits<int>::max()); }
692 // bool isBST() { return isBST(root, std::numeric_limits<int>::min(), std::numeric_limits<int>::max()); }
693
694 // is the tree rooted at x a BST with all keys strictly between min and max
695 // (if min or max is nullptr, treat as empty constraint)
696 // Credit: Bob Dondero's elegant solution
697 bool isBST(node x, Key min, Key max) {
698 if (x == nullptr) return true;
699 // if (min != nullptr && x->key <= min) return false;
700 // if (max != nullptr && x->key >= max) return false;
701 return isBST(x->left, min, x->key) && isBST(x->right, x->key, max);
702 }
703
704 // are the size fields correct?
705 bool isSizeConsistent() { return isSizeConsistent(root); }
706
707 bool isSizeConsistent(node x) {
708 if (x == nullptr) return true;
709 if (x->N != size(x->left) + size(x->right) + 1) return false;
710 return isSizeConsistent(x->left) && isSizeConsistent(x->right);
711 }
712
713 // check that ranks are consistent
714 bool isRankConsistent() {
715 for (int i = 0; i < size(); i++)
716 if (i != rank(select(i))) return false;
717 // for (Key const& key : keys())
718 // if (key != select(rank(key))) return false;
719 return true;
720 }
721
722 // Does the tree have no red right links, and at most one (left)
723 // red links in a row on any path?
724 bool is23() { return is23(root); }
725 bool is23(node x) {
726 if (x == nullptr) return true;
727 if (is_red(x->right)) return false;
728 if (x != root && is_red(x) && is_red(x->left)) return false;
729 return is23(x->left) && is23(x->right);
730 }
731
732 // do all paths from root to leaf have same number of black edges?
733 bool isBalanced() {
734 int black = 0; // number of black links on path from root to min
735 node x = root;
736 while (x != nullptr) {
737 if (!is_red(x)) black++;
738 x = x->left;
739 }
740 return isBalanced(root, black);
741 }
742
743 // does every path from the root to a leaf have the given number of black links?
744 bool isBalanced(node x, int black) {
745 if (x == nullptr) return black == 0;
746 if (!is_red(x)) black--;
747 return isBalanced(x->left, black) && isBalanced(x->right, black);
748 }
749 };
750 }
751}