HAllocator
A Simple C++ Memory Allocator
Loading...
Searching...
No Matches
rb-tree.hpp
Go to the documentation of this file.
1
22#pragma once
23
24#include <cstddef>
25
26namespace hh::rb_tree {
43template <typename RbNode>
44void insert(RbNode*& root, RbNode* new_node);
45
62template <typename RbNode>
63void remove(RbNode*& root, RbNode* node);
64
81template <typename RbNode>
82RbNode* lower_bound(RbNode* root, std::size_t key, bool (*cmp)(std::size_t, std::size_t));
83} // namespace hh::rb_tree
84
85namespace hh::rb_tree {
86
95inline void set_color_red(std::size_t& value) {
96 value |= (1ull << 63);
97}
98
107inline void set_color_black(std::size_t& value) {
108 value &= ~(1ull << 63);
109}
110
117inline bool is_red(const std::size_t& value) {
118 return (value & (1ull << 63));
119}
120
127inline bool is_black(const std::size_t& value) {
128 return !(value & (1ull << 63));
129}
130
139inline std::size_t get_value(const std::size_t& value) {
140 return value & ~(1ull << 63);
141}
142
149inline bool get_color(const std::size_t& value) {
150 return is_red(value);
151}
152
173template <typename RbNode>
174void left_rotate(RbNode*& root, RbNode* node) {
175 RbNode* right_child = node->right;
176 node->right = right_child->left;
177
178 if (right_child->left)
179 right_child->left->parent = node;
180
181 right_child->parent = node->parent;
182
183 if (!node->parent)
184 root = right_child;
185 else if (node == node->parent->left)
186 node->parent->left = right_child;
187 else
188 node->parent->right = right_child;
189
190 right_child->left = node;
191 node->parent = right_child;
192}
193
214template <typename RbNode>
215void right_rotate(RbNode*& root, RbNode* node) {
216 RbNode* left_child = node->left;
217 node->left = left_child->right;
218
219 if (left_child->right)
220 left_child->right->parent = node;
221
222 left_child->parent = node->parent;
223
224 if (!node->parent)
225 root = left_child;
226 else if (node == node->parent->left)
227 node->parent->left = left_child;
228 else
229 node->parent->right = left_child;
230
231 left_child->right = node;
232 node->parent = left_child;
233}
234
254template <typename RbNode>
255void fix_insert(RbNode*& root, RbNode* z) {
256 while (z->parent && is_red(z->parent->value)) {
257 if (z->parent == z->parent->parent->left) {
258 RbNode* y = z->parent->parent->right;
259 if (y && is_red(y->value)) {
260 set_color_black(y->value);
261 set_color_black(z->parent->value);
262 set_color_red(z->parent->parent->value);
263 z = z->parent->parent;
264 } else {
265 if (z == z->parent->right) {
266 z = z->parent;
267 left_rotate(root, z);
268 }
269 set_color_black(z->parent->value);
270 set_color_red(z->parent->parent->value);
271 right_rotate(root, z->parent->parent);
272 }
273 } else {
274 RbNode* y = z->parent->parent->left;
275 if (y && is_red(y->value)) {
276 set_color_black(z->parent->value);
277 set_color_black(y->value);
278 set_color_red(z->parent->parent->value);
279 z = z->parent->parent;
280 } else {
281 if (z == z->parent->left) {
282 z = z->parent;
283 right_rotate(root, z);
284 }
285 set_color_black(z->parent->value);
286 set_color_red(z->parent->parent->value);
287 left_rotate(root, z->parent->parent);
288 }
289 }
290 }
291 set_color_black(root->value);
292}
293
317template <typename RbNode>
318void insert(RbNode*& root, RbNode* new_node) {
319 RbNode* y = nullptr;
320 RbNode* x = root;
321
322 std::size_t new_val = get_value(new_node->value);
323
324 while (x) {
325 y = x;
326 std::size_t curr_val = get_value(x->value);
327 if (new_val < curr_val)
328 x = x->left;
329 else
330 x = x->right;
331 }
332
333 new_node->parent = y;
334
335 if (!y)
336 root = new_node;
337 else if (new_val < get_value(y->value))
338 y->left = new_node;
339 else
340 y->right = new_node;
341
342 new_node->left = nullptr;
343 new_node->right = nullptr;
344
345 set_color_red(new_node->value);
346 fix_insert(root, new_node);
347}
348
363template <typename RbNode>
364void transplant(RbNode*& root, RbNode* u, RbNode* v) {
365 if (!u->parent)
366 root = v;
367 else if (u == u->parent->left)
368 u->parent->left = v;
369 else
370 u->parent->right = v;
371
372 if (v)
373 v->parent = u->parent;
374}
375
398template <typename RbNode>
399void fix_remove(RbNode*& root, RbNode* x, RbNode* x_parent) {
400 while (x != root && (x == nullptr || is_black(x->value))) {
401 if (x == (x_parent ? x_parent->left : nullptr)) {
402 RbNode* w = x_parent->right;
403 if (is_red(w->value)) {
404 set_color_black(w->value);
405 set_color_red(x_parent->value);
406 left_rotate(root, x_parent);
407 w = x_parent->right;
408 }
409 if ((w->left == nullptr || is_black(w->left->value)) &&
410 (w->right == nullptr || is_black(w->right->value))) {
411 set_color_red(w->value);
412 x = x_parent;
413 x_parent = x->parent;
414 } else {
415 if (w->right == nullptr || is_black(w->right->value)) {
416 if (w->left)
417 set_color_black(w->left->value);
418 set_color_red(w->value);
419 right_rotate(root, w);
420 w = x_parent->right;
421 }
422 // w takes the color of x_parent
423 auto parent_color = get_color(x_parent->value);
424 if (parent_color)
425 set_color_red(w->value);
426 else
427 set_color_black(w->value);
428 set_color_black(x_parent->value);
429 if (w->right)
430 set_color_black(w->right->value);
431 left_rotate(root, x_parent);
432 x = root;
433 }
434 } else {
435 RbNode* w = x_parent->left;
436 if (is_red(w->value)) {
437 set_color_black(w->value);
438 set_color_red(x_parent->value);
439 right_rotate(root, x_parent);
440 w = x_parent->left;
441 }
442 if ((w->right == nullptr || is_black(w->right->value)) &&
443 (w->left == nullptr || is_black(w->left->value))) {
444 set_color_red(w->value);
445 x = x_parent;
446 x_parent = x->parent;
447 } else {
448 if (w->left == nullptr || is_black(w->left->value)) {
449 if (w->right)
450 set_color_black(w->right->value);
451 set_color_red(w->value);
452 left_rotate(root, w);
453 w = x_parent->left;
454 }
455 // w takes the color of x_parent
456 auto parent_color = get_color(x_parent->value);
457 if (parent_color)
458 set_color_red(w->value);
459 else
460 set_color_black(w->value);
461 set_color_black(x_parent->value);
462 if (w->left)
463 set_color_black(w->left->value);
464 right_rotate(root, x_parent);
465 x = root;
466 }
467 }
468 }
469 if (x)
470 set_color_black(x->value);
471}
472
498template <typename RbNode>
499void remove(RbNode*& root, RbNode* z) {
500 if (!z or !root)
501 return;
502
503 RbNode* y = z;
504 RbNode* x = nullptr;
505 RbNode* x_parent = nullptr;
506 bool is_y_original_black = is_black(y->value);
507
508 if (!z->left) {
509 x = z->right;
510 x_parent = z->parent;
511 transplant(root, z, z->right);
512 } else if (!z->right) {
513 x = z->left;
514 x_parent = z->parent;
515 transplant(root, z, z->left);
516 } else {
517 // Find successor (minimum in right subtree)
518 y = z->right;
519 while (y->left)
520 y = y->left;
521
522 is_y_original_black = is_black(y->value);
523 x = y->right;
524
525 if (y->parent == z) {
526 // y is the right child of z
527 // After transplanting y to z's position, x will be y's right child
528 // So x's parent will be y after the transplant
529 x_parent = y;
530 if (x)
531 x->parent = y;
532 } else {
533 // y is deeper in the tree
534 x_parent = y->parent;
535 // First, replace y with its right child
536 transplant(root, y, y->right);
537
538 // Now connect z's right subtree to y
539 y->right = z->right;
540 if (y->right)
541 y->right->parent = y;
542 }
543
544 // Replace z with y
545 transplant(root, z, y);
546 y->left = z->left;
547 if (y->left)
548 y->left->parent = y;
549
550 // y takes z's color
551 auto z_color = get_color(z->value);
552 if (z_color == true)
553 set_color_red(y->value);
554 else
555 set_color_black(y->value);
556 }
557
558 if (is_y_original_black) {
559 fix_remove(root, x, x_parent);
560 }
561}
562
591template <typename RbNode>
592RbNode* lower_bound(RbNode* root, std::size_t value, bool (*cmp)(std::size_t, std::size_t)) {
593 auto current = root;
594 RbNode* result = nullptr;
595 while (current) {
596 std::size_t curr_val = get_value(current->value);
597 if (cmp(value, curr_val)) {
598 result = current;
599 current = current->left;
600 } else {
601 current = current->right;
602 }
603 }
604 return result;
605}
606} // namespace hh::rb_tree
Definition rb-tree.hpp:26
RbNode * lower_bound(RbNode *root, std::size_t key, bool(*cmp)(std::size_t, std::size_t))
Finds the smallest node with value >= key.
Definition rb-tree.hpp:592
std::size_t get_value(const std::size_t &value)
Extracts the actual value without the color bit.
Definition rb-tree.hpp:139
void fix_insert(RbNode *&root, RbNode *z)
Fixes Red-Black tree properties after insertion.
Definition rb-tree.hpp:255
void fix_remove(RbNode *&root, RbNode *x, RbNode *x_parent)
Fixes Red-Black tree properties after deletion.
Definition rb-tree.hpp:399
void left_rotate(RbNode *&root, RbNode *node)
Performs a left rotation around a node.
Definition rb-tree.hpp:174
void right_rotate(RbNode *&root, RbNode *node)
Performs a right rotation around a node.
Definition rb-tree.hpp:215
bool is_red(const std::size_t &value)
Checks if a node is RED.
Definition rb-tree.hpp:117
void transplant(RbNode *&root, RbNode *u, RbNode *v)
Replaces one subtree with another.
Definition rb-tree.hpp:364
bool is_black(const std::size_t &value)
Checks if a node is BLACK.
Definition rb-tree.hpp:127
void set_color_red(std::size_t &value)
Sets the color of a node to RED.
Definition rb-tree.hpp:95
void insert(RbNode *&root, RbNode *new_node)
Inserts a new node into the Red-Black tree.
Definition rb-tree.hpp:318
bool get_color(const std::size_t &value)
Gets the color bit value.
Definition rb-tree.hpp:149
void set_color_black(std::size_t &value)
Sets the color of a node to BLACK.
Definition rb-tree.hpp:107
void remove(RbNode *&root, RbNode *node)
Removes a node from the Red-Black tree.
Definition rb-tree.hpp:499