Iros
 
Loading...
Searching...
No Matches
rb_tree.h
Go to the documentation of this file.
1#pragma once
2
12#include "di/function/compare.h"
13#include "di/meta/compare.h"
14#include "di/meta/core.h"
15#include "di/util/create.h"
16#include "di/util/exchange.h"
18
19namespace di::container {
20namespace detail {
21 template<typename Value, typename Comp>
23 template<typename U>
24 struct Type {
26 };
27 };
28}
29
35template<typename Value, typename Comp, typename Tag, typename Interface, bool is_multi, typename Self = Void>
36class RBTree : public Interface {
37private:
38 using Node = RBTreeNode<Tag>;
39 using Iterator = RBTreeIterator<Value, Tag>;
40 using ConstIterator = container::ConstIteratorImpl<Iterator>;
41
42 using ConcreteNode = decltype(Tag::node_type(in_place_type<Value>));
43 using ConcreteSelf = meta::Conditional<concepts::SameAs<Void, Self>, RBTree, Self>;
44
45 constexpr auto down_cast_self() -> decltype(auto) {
46 if constexpr (concepts::SameAs<Void, Self>) {
47 return *this;
48 } else {
49 return static_cast<Self&>(*this);
50 }
51 }
52
53public:
54 RBTree() = default;
55 RBTree(RBTree const&) = delete;
56 auto operator=(RBTree const&) -> RBTree& = delete;
57
58 constexpr explicit RBTree(Comp comparator) : m_comparator(comparator) {}
59
60 constexpr RBTree(RBTree&& other)
61 : m_root(util::exchange(other.m_root, nullptr))
62 , m_minimum(util::exchange(other.m_minimum, nullptr))
63 , m_maximum(util::exchange(other.m_maximum, nullptr))
64 , m_size(util::exchange(other.m_size, 0))
65 , m_comparator(other.m_comparator) {}
66
67 constexpr auto operator=(RBTree&& other) -> RBTree& {
68 this->clear();
69 m_root = util::exchange(other.m_root, nullptr);
70 m_minimum = util::exchange(other.m_minimum, nullptr);
71 m_maximum = util::exchange(other.m_maximum, nullptr);
72 m_size = util::exchange(other.m_size, 0);
73 m_comparator = other.m_comparator;
74 return *this;
75 }
76
77 constexpr ~RBTree() { this->clear(); }
78
79 constexpr auto size() const -> usize { return m_size; }
80 constexpr auto empty() const -> bool { return !m_root; }
81
82 constexpr auto begin() -> Iterator { return unconst_iterator(util::as_const(*this).begin()); }
83 constexpr auto begin() const -> ConstIterator { return Iterator(m_minimum, !m_root); }
84 constexpr auto end() -> Iterator { return unconst_iterator(util::as_const(*this).end()); }
85 constexpr auto end() const -> ConstIterator { return Iterator(m_maximum, true); }
86
87 constexpr auto unconst_iterator(ConstIterator it) -> Iterator { return it.base(); }
88
89 constexpr auto insert_node(Node& node) {
90 auto position = this->insert_position(node_value(node));
91 if constexpr (!is_multi) {
92 if (position.parent && this->compare(node_value(*position.parent), node_value(node)) == 0) {
93 return Tuple(Iterator(position.parent, false), false);
94 }
95 }
96
97 this->insert_node(position, node);
98 if constexpr (!is_multi) {
99 return Tuple(Iterator(util::addressof(node), false), true);
100 } else {
101 return Iterator(util::addressof(node), false);
102 }
103 }
104
105 constexpr auto insert_node(ConstIterator, Node& node) {
106 auto position = this->insert_position(node_value(node));
107 if constexpr (!is_multi) {
108 if (position.parent && this->compare(node_value(*position.parent), node_value(node)) == 0) {
109 return Iterator(position.parent, false);
110 }
111 }
112
113 this->insert_node(position, node);
114 return Iterator(util::addressof(node), false);
115 }
116
117 constexpr auto erase_impl(ConstIterator position) -> Iterator {
118 DI_ASSERT(position != end());
119
120 auto result = container::next(position).base();
121 auto& node = position.base().node();
122 erase_node(node);
123
124 Tag::did_remove(down_cast_self(), static_cast<ConcreteNode&>(node));
125
126 return result;
127 }
128
129 template<typename U>
131 constexpr auto equal_range_impl(U&& needle) const {
132 return View<ConstIterator> { lower_bound_impl(needle), upper_bound_impl(needle) };
133 }
134
135 template<typename U>
137 constexpr auto lower_bound_impl(U&& needle) const -> ConstIterator {
138 Node* result = nullptr;
139 for (auto* node = m_root; node;) {
140 if (compare(node_value(*node), needle) < 0) {
141 node = node->right;
142 } else {
143 result = node;
144 node = node->left;
145 }
146 }
147 return result ? Iterator(result, false) : end();
148 }
149
150 template<typename U>
152 constexpr auto upper_bound_impl(U&& needle) const -> ConstIterator {
153 Node* result = nullptr;
154 for (auto* node = m_root; node;) {
155 if (compare(node_value(*node), needle) <= 0) {
156 node = node->right;
157 } else {
158 result = node;
159 node = node->left;
160 }
161 }
162 return result ? Iterator(result, false) : end();
163 }
164
165 template<typename U>
167 constexpr auto find_impl(U&& needle) const -> ConstIterator {
168 for (auto* node = m_root; node;) {
169 auto result = compare(needle, node_value(*node));
170 if (result == 0) {
171 return Iterator(node, false);
172 }
173 if (result < 0) {
174 node = node->left;
175 } else {
176 node = node->right;
177 }
178 }
179 return end();
180 }
181
182 constexpr void merge_impl(RBTree&& other) {
183 if (!m_root) {
184 *this = util::move(other);
185 return;
186 }
187
188 auto it = other.begin();
189 auto last = other.end();
190 while (it != last) {
191 auto save = it++;
192
193 auto position = insert_position(*save);
194 if (!is_multi && position.parent && compare(position.parent->value, *save) == 0) {
195 erase_impl(save);
196 } else {
197 do_insert_node(position, save.node());
198 }
199 }
200 }
201
202protected:
203 constexpr auto node_value(Node& node) const -> Value& {
204 return Tag::down_cast(in_place_type<Value>, static_cast<ConcreteNode&>(node));
205 }
206 constexpr auto node_value(Node const& node) const -> Value const& {
207 return const_cast<RBTree&>(*this).node_value(const_cast<Node&>(node));
208 }
209
210 // Compute the color of a node, defaulting to Black.
211 constexpr auto node_color(Node* node) const -> Node::Color {
212 if (!node) {
213 return Node::Color::Black;
214 }
215 return node->color;
216 }
217
218 // Swaps the passed node with its right child in the tree.
219 constexpr void rotate_left(Node& x) {
220 DI_ASSERT(x.right);
221
222 auto& y = *x.right;
223 x.right = y.left;
224 if (y.left != nullptr) {
225 y.left->parent = &x;
226 }
227 y.parent = x.parent;
228 if (x.parent == nullptr) {
229 m_root = &y;
230 } else if (x.is_left_child()) {
231 x.parent->left = &y;
232 } else {
233 x.parent->right = &y;
234 }
235 y.left = &x;
236 x.parent = &y;
237 }
238
239 // Swaps the passed node with its left child in the tree.
240 constexpr void rotate_right(Node& y) {
241 DI_ASSERT(y.left);
242
243 auto& x = *y.left;
244 y.left = x.right;
245 if (y.left != nullptr) {
246 y.left->parent = &y;
247 }
248 x.parent = y.parent;
249 if (y.parent == nullptr) {
250 m_root = &x;
251 } else if (y.is_left_child()) {
252 y.parent->left = &x;
253 } else {
254 y.parent->right = &x;
255 }
256 x.right = &y;
257 y.parent = &x;
258 }
259
261 Node* parent { nullptr };
262 bool left { true };
263 };
264
265 template<typename U>
267 constexpr auto insert_position(U&& needle) const -> InsertPosition {
268 // Find the parent node to insert under.
269 Node* y = nullptr;
270 auto* x = m_root;
271 while (x != nullptr) {
272 y = x;
273
274 // Early return to the caller if we're inserting a duplicate, making
275 // sure to provide the caller a node that is equal to needle.
276 if constexpr (!is_multi) {
277 if (compare(needle, node_value(*x)) == 0) {
278 return InsertPosition { x, false };
279 }
280 }
281
282 if (compare(needle, node_value(*x)) < 0) {
283 x = x->left;
284 } else {
285 x = x->right;
286 }
287 }
288
289 if (!y) {
290 return InsertPosition {};
291 }
292 if (compare(needle, node_value(*y)) < 0) {
293 return InsertPosition { y, true };
294 }
295 return InsertPosition { y, false };
296 }
297
298 constexpr void insert_node(InsertPosition position, Node& to_insert) {
299 do_insert_node(position, to_insert);
300
301 Tag::did_insert(down_cast_self(), static_cast<ConcreteNode&>(to_insert));
302 }
303
304 constexpr void do_insert_node(InsertPosition position, Node& to_insert) {
305 // Step 1: check if inserting the first node.
306 if (position.parent == nullptr) {
307 m_root = m_minimum = m_maximum = &to_insert;
308 m_size = 1;
309 return;
310 }
311
312 // Step 2: actually insert the node.
313 auto& parent = *position.parent;
314 to_insert.parent = &parent;
315 if (position.left) {
316 parent.left = &to_insert;
317 } else {
318 parent.right = &to_insert;
319 }
320
321 // Step 3: maintain the Red-Black properties.
322 do_insert_rebalancing(&to_insert);
323
324 // Step 4: update cached values.
325 m_size++;
326 if (m_minimum->left) {
327 m_minimum = &to_insert;
328 }
329 if (m_maximum->right) {
330 m_maximum = &to_insert;
331 }
332 }
333
334 constexpr void do_insert_rebalancing(Node* node) {
335 DI_ASSERT(node);
336 while (node->parent && node->parent->parent && node->parent->color == Node::Color::Red) {
337 auto* grand_parent = node->parent->parent;
338 if (node->parent->is_right_child()) {
339 auto* uncle = grand_parent->left;
340 if (node_color(uncle) == Node::Color::Red) {
342 uncle->color = Node::Color::Black;
343 grand_parent->color = Node::Color::Red;
344 node = grand_parent;
345 } else {
346 if (node->is_left_child()) {
347 node = node->parent;
348 rotate_right(*node);
349 }
351 grand_parent->color = Node::Color::Red;
352 rotate_left(*grand_parent);
353 }
354 } else {
355 auto* uncle = grand_parent->right;
356 if (node_color(uncle) == Node::Color::Red) {
358 uncle->color = Node::Color::Black;
359 grand_parent->color = Node::Color::Red;
360 node = grand_parent;
361 } else {
362 if (node->is_right_child()) {
363 node = node->parent;
364 rotate_left(*node);
365 }
367 grand_parent->color = Node::Color::Red;
368 rotate_right(*grand_parent);
369 }
370 }
371 }
372 m_root->color = Node::Color::Black;
373 }
374
375 constexpr void transplant(Node& u, Node* v) {
376 if (u.parent == nullptr) {
377 m_root = v;
378 } else if (u.is_left_child()) {
379 u.parent->left = v;
380 } else {
381 u.parent->right = v;
382 }
383 if (v) {
384 v->parent = u.parent;
385 }
386 }
387
388 constexpr void erase_node(Node& to_delete) {
389 Node* x = nullptr;
390 auto* y = &to_delete;
391 auto y_color = y->color;
392
393 // Step 1: Update cached values.
394 m_size--;
395 if (m_minimum == &to_delete) {
396 m_minimum = to_delete.successor();
397 }
398 if (m_maximum == &to_delete) {
399 m_maximum = to_delete.predecessor();
400 }
401
402 // Step 2: actually remove the node from the tree.
403 if (to_delete.left == nullptr) {
404 // Case 1: there is no left child, so promote the right child.
405 x = to_delete.right;
406 transplant(to_delete, to_delete.right);
407 } else if (to_delete.right == nullptr) {
408 // Case 2: there is no right child, so promote the left child.
409 x = to_delete.left;
410 transplant(to_delete, to_delete.left);
411 } else {
412 // Case 3: promote this node's successor
413 y = to_delete.successor();
414 y_color = y->color;
415 x = y->right;
416
417 if (y->parent == &to_delete) {
418 if (x) {
419 x->parent = y;
420 }
421 } else {
422 transplant(*y, y->right);
423 y->right = to_delete.right;
424 y->right->parent = y;
425 }
426 transplant(to_delete, y);
427 y->left = to_delete.left;
428 y->left->parent = y;
429 y->color = to_delete.color;
430 }
431
432 // Step 3: maintain the Red-Black properties.
433 if (y_color == Node::Color::Black && x) {
435 }
436 }
437
438 constexpr void do_erase_rebalancing(Node* x) {
439 DI_ASSERT(x);
440 while (x != m_root && x->color == Node::Color::Black) {
441 if (x->is_left_child()) {
442 auto* w = x->parent->right;
443 // FIXME: this NULL check appears to be necessary, but is not part of the reference implementation.
444 if (!w) {
445 break;
446 }
447
448 if (w->color == Node::Color::Red) {
451 rotate_left(*x->parent);
452 }
453 if (node_color(w->left) == Node::Color::Black && node_color(w->right) == Node::Color::Black) {
454 w->color = Node::Color::Red;
455 x = x->parent;
456 } else {
457 if (node_color(w->right) == Node::Color::Black) {
458 w->left->color = Node::Color::Black;
459 w->color = Node::Color::Red;
460 rotate_right(*w);
461 w = x->parent->right;
462 }
463 w->color = x->parent->color;
465 if (w->right) {
466 w->right->color = Node::Color::Black;
467 }
468 rotate_left(*x->parent);
469 break;
470 }
471 } else {
472 auto* w = x->parent->left;
473 // FIXME: this NULL check appears to be necessary, but is not part of the reference implementation.
474 if (!w) {
475 break;
476 }
477
478 if (w->color == Node::Color::Red) {
481 rotate_right(*x->parent);
482 }
483 if (node_color(w->right) == Node::Color::Black && node_color(w->left) == Node::Color::Black) {
484 w->color = Node::Color::Red;
485 x = x->parent;
486 } else {
487 if (node_color(w->left) == Node::Color::Black) {
488 w->right->color = Node::Color::Black;
489 w->color = Node::Color::Red;
490 rotate_left(*w);
491 w = x->parent->left;
492 }
493 w->color = x->parent->color;
495 if (w->left) {
496 w->left->color = Node::Color::Black;
497 }
498 rotate_right(*x->parent);
499 break;
500 }
501 }
502 }
504 }
505
506 constexpr auto compare(Node const& a, Node const& b) const { return compare(node_value(a), node_value(b)); }
507
508 template<typename T, typename U>
510 constexpr auto compare(T const& a, U&& b) const {
511 return function::invoke(m_comparator, a, b);
512 }
513
514 constexpr friend auto operator==(ConcreteSelf const& a, ConcreteSelf const& b) -> bool
516 {
517 return container::equal(a, b);
518 }
519 constexpr friend auto operator<=>(ConcreteSelf const& a, ConcreteSelf const& b)
521 {
522 return container::compare(a, b);
523 }
524
525 Node* m_root { nullptr };
526 Node* m_minimum { nullptr };
527 Node* m_maximum { nullptr };
529 [[no_unique_address]] Comp m_comparator;
530};
531}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Definition const_iterator_impl.h:19
Definition rb_tree_iterator.h:10
constexpr void do_erase_rebalancing(Node *x)
Definition rb_tree.h:438
constexpr auto node_color(Node *node) const -> Node::Color
Definition rb_tree.h:211
constexpr void do_insert_node(InsertPosition position, Node &to_insert)
Definition rb_tree.h:304
Node * m_minimum
Definition rb_tree.h:526
constexpr void transplant(Node &u, Node *v)
Definition rb_tree.h:375
constexpr auto equal_range_impl(U &&needle) const
Definition rb_tree.h:131
constexpr friend auto operator==(ConcreteSelf const &a, ConcreteSelf const &b) -> bool requires(concepts::EqualityComparable< Value >)
Definition rb_tree.h:514
auto operator=(RBTree const &) -> RBTree &=delete
constexpr auto operator=(RBTree &&other) -> RBTree &
Definition rb_tree.h:67
constexpr auto lower_bound_impl(U &&needle) const -> ConstIterator
Definition rb_tree.h:137
Comp m_comparator
Definition rb_tree.h:529
constexpr auto find_impl(U &&needle) const -> ConstIterator
Definition rb_tree.h:167
constexpr auto begin() -> Iterator
Definition rb_tree.h:82
constexpr auto insert_node(Node &node)
Definition rb_tree.h:89
constexpr auto compare(T const &a, U &&b) const
Definition rb_tree.h:510
constexpr void merge_impl(RBTree &&other)
Definition rb_tree.h:182
constexpr auto size() const -> usize
Definition rb_tree.h:79
constexpr friend auto operator<=>(ConcreteSelf const &a, ConcreteSelf const &b)
Definition rb_tree.h:519
usize m_size
Definition rb_tree.h:528
constexpr auto upper_bound_impl(U &&needle) const -> ConstIterator
Definition rb_tree.h:152
constexpr auto empty() const -> bool
Definition rb_tree.h:80
constexpr RBTree(Comp comparator)
Definition rb_tree.h:58
constexpr ~RBTree()
Definition rb_tree.h:77
constexpr RBTree(RBTree &&other)
Definition rb_tree.h:60
Node * m_root
Definition rb_tree.h:525
constexpr auto end() -> Iterator
Definition rb_tree.h:84
constexpr auto insert_position(U &&needle) const -> InsertPosition
Definition rb_tree.h:267
constexpr auto erase_impl(ConstIterator position) -> Iterator
Definition rb_tree.h:117
constexpr auto end() const -> ConstIterator
Definition rb_tree.h:85
constexpr auto begin() const -> ConstIterator
Definition rb_tree.h:83
constexpr auto compare(Node const &a, Node const &b) const
Definition rb_tree.h:506
constexpr auto insert_node(ConstIterator, Node &node)
Definition rb_tree.h:105
constexpr void insert_node(InsertPosition position, Node &to_insert)
Definition rb_tree.h:298
constexpr auto unconst_iterator(ConstIterator it) -> Iterator
Definition rb_tree.h:87
constexpr void erase_node(Node &to_delete)
Definition rb_tree.h:388
constexpr void rotate_left(Node &x)
Definition rb_tree.h:219
constexpr auto node_value(Node const &node) const -> Value const &
Definition rb_tree.h:206
RBTree(RBTree const &)=delete
constexpr void do_insert_rebalancing(Node *node)
Definition rb_tree.h:334
Node * m_maximum
Definition rb_tree.h:527
constexpr auto node_value(Node &node) const -> Value &
Definition rb_tree.h:203
constexpr void rotate_right(Node &y)
Definition rb_tree.h:240
Definition view.h:35
Definition tuple_forward_declaration.h:5
Definition compare.h:82
Definition core.h:114
Definition relation.h:31
Definition compare.h:91
Definition sequence.h:13
Definition sequence.h:12
constexpr auto next
Definition next.h:35
constexpr auto equal
Definition equal.h:46
constexpr auto compare
Definition compare.h:40
constexpr auto invoke
Definition invoke.h:100
detail::ConditionalHelper< value, T, U >::Type Conditional
Definition core.h:88
size_t usize
Definition integers.h:33
Definition vocab.h:96
constexpr auto exchange(T &object, U &&new_value) -> T
Definition exchange.h:8
constexpr auto exchange(T &object, U &&new_value) -> T
Definition exchange.h:8
constexpr auto in_place_type
Definition in_place_type.h:12
Definition rb_tree_node.h:9
constexpr auto successor() const -> RBTreeNode *
Definition rb_tree_node.h:48
constexpr auto is_right_child() const -> bool
Definition rb_tree_node.h:16
constexpr auto predecessor() const -> RBTreeNode *
Definition rb_tree_node.h:34
RBTreeNode * right
Definition rb_tree_node.h:65
RBTreeNode * left
Definition rb_tree_node.h:64
constexpr auto is_left_child() const -> bool
Definition rb_tree_node.h:15
RBTreeNode * parent
Definition rb_tree_node.h:63
Color
Definition rb_tree_node.h:11
@ Black
Definition rb_tree_node.h:11
@ Red
Definition rb_tree_node.h:11
Color color
Definition rb_tree_node.h:62
bool left
Definition rb_tree.h:262
Node * parent
Definition rb_tree.h:261
static constexpr bool value
Definition rb_tree.h:25