CPPX 2.1.0
A Modern C++ Utility Library
Loading...
Searching...
No Matches
rbt.tpp
Go to the documentation of this file.
1#pragma once
2#include "../include/cppx.h"
3
4namespace stl_ext
5{
6
7template <typename T> bool RBTree<T>::is_red(const Node<T> *node)
8{
9 return node != nullptr && node->m_color == Color::RED;
10}
11
12template <typename T> bool RBTree<T>::is_black(const Node<T> *node)
13{
14 return node == nullptr || node->m_color == Color::BLACK;
15}
16
17template <typename T> Color RBTree<T>::get_color(const Node<T> *node)
18{
19 return (node == nullptr) ? Color::BLACK : node->m_color;
20}
21
22template <typename T> Color RBTree<T>::node_color(const Node<T> *node) const
23{
24 return (node == nullptr) ? Color::BLACK : node->m_color;
25}
26
27template <typename T> Node<T> *RBTree<T>::tree_minimum(Node<T> *node) const
28{
29 while (node->p_left)
30 node = node->p_left;
31 return node;
32}
33
34template <typename T> void RBTree<T>::rotate_left(Node<T> *x)
35{
36 Node<T> *y = x->p_right;
37 Node<T> *p = x->p_parent;
38
39 x->p_right = y->p_left;
40 if (y->p_left)
41 y->p_left->p_parent = x;
42
43 y->p_left = x;
44 x->p_parent = y;
45
46 y->p_parent = p;
47 if (!p)
48 this->p_head = y;
49 else if (p->p_left == x)
50 p->p_left = y;
51 else
52 p->p_right = y;
53}
54
55template <typename T> void RBTree<T>::rotate_right(Node<T> *x)
56{
57 Node<T> *y = x->p_left;
58 Node<T> *p = x->p_parent;
59
60 x->p_left = y->p_right;
61 if (y->p_right)
62 y->p_right->p_parent = x;
63
64 y->p_right = x;
65 x->p_parent = y;
66
67 y->p_parent = p;
68 if (!p)
69 this->p_head = y;
70 else if (p->p_left == x)
71 p->p_left = y;
72 else
73 p->p_right = y;
74}
75
76template <typename T> void RBTree<T>::insert(const T &val)
77{
78 Node<T> *z = this->m_pool.allocate(val);
79 z->m_color = Color::RED;
80 z->p_left = nullptr;
81 z->p_right = nullptr;
82
83 if (!this->p_head)
84 {
85 z->m_color = Color::BLACK;
86 z->p_parent = nullptr;
87 this->p_head = z;
88 return;
89 }
90
91 Node<T> *curr = this->p_head;
92 Node<T> *parent = nullptr;
93
94 while (curr)
95 {
96 parent = curr;
97 if (val < curr->m_data)
98 curr = curr->p_left;
99 else if (val > curr->m_data)
100 curr = curr->p_right;
101 else
102 {
103 this->m_pool.deallocate(z);
104 return;
105 }
106 }
107
108 z->p_parent = parent;
109 if (val < parent->m_data)
110 parent->p_left = z;
111 else
112 parent->p_right = z;
113
114 fix_insert_violation(z);
115}
116
117template <typename T> void RBTree<T>::fix_insert_violation(Node<T> *z)
118{
119 while (z->p_parent && z->p_parent->m_color == Color::RED)
120 {
121 Node<T> *parent = z->p_parent;
122 Node<T> *grandparent = parent->p_parent;
123
124 if (!grandparent)
125 break;
126
127 if (parent == grandparent->p_left)
128 {
129 Node<T> *uncle = grandparent->p_right;
130
131 if (node_color(uncle) == Color::RED)
132 {
133 parent->m_color = Color::BLACK;
134 uncle->m_color = Color::BLACK;
135 grandparent->m_color = Color::RED;
136 z = grandparent;
137 }
138 else
139 {
140 if (z == parent->p_right)
141 {
142 z = parent;
143 rotate_left(z);
144 parent = z->p_parent;
145 grandparent = parent->p_parent;
146 }
147
148 parent->m_color = Color::BLACK;
149 grandparent->m_color = Color::RED;
150 rotate_right(grandparent);
151 }
152 }
153 else
154 {
155 Node<T> *uncle = grandparent->p_left;
156
157 if (node_color(uncle) == Color::RED)
158 {
159 parent->m_color = Color::BLACK;
160 uncle->m_color = Color::BLACK;
161 grandparent->m_color = Color::RED;
162 z = grandparent;
163 }
164 else
165 {
166 if (z == parent->p_left)
167 {
168 z = parent;
169 rotate_right(z);
170 parent = z->p_parent;
171 grandparent = parent->p_parent;
172 }
173
174 parent->m_color = Color::BLACK;
175 grandparent->m_color = Color::RED;
176 rotate_left(grandparent);
177 }
178 }
179 }
180
181 this->p_head->m_color = Color::BLACK;
182}
183
184template <typename T> void RBTree<T>::remove(const T &val)
185{
186 Node<T> *z = this->p_head;
187 while (z)
188 {
189 if (val < z->m_data)
190 z = z->p_left;
191 else if (val > z->m_data)
192 z = z->p_right;
193 else
194 break;
195 }
196 if (!z)
197 return;
198
199 Node<T> *y = z;
200 Color y_original_color = y->m_color;
201 Node<T> *x = nullptr;
202 Node<T> *x_parent = nullptr;
203
204 if (!z->p_left)
205 {
206 x = z->p_right;
207 x_parent = z->p_parent;
208
209 if (x)
210 x->p_parent = z->p_parent;
211
212 if (!z->p_parent)
213 this->p_head = x;
214 else if (z->p_parent->p_left == z)
215 z->p_parent->p_left = x;
216 else
217 z->p_parent->p_right = x;
218
219 this->m_pool.deallocate(z);
220 }
221 else if (!z->p_right)
222 {
223 x = z->p_left;
224 x_parent = z->p_parent;
225
226 if (x)
227 x->p_parent = z->p_parent;
228
229 if (!z->p_parent)
230 this->p_head = x;
231 else if (z->p_parent->p_left == z)
232 z->p_parent->p_left = x;
233 else
234 z->p_parent->p_right = x;
235
236 this->m_pool.deallocate(z);
237 }
238 else
239 {
240 y = tree_minimum(z->p_right);
241 y_original_color = y->m_color;
242 x = y->p_right;
243
244 if (y->p_parent == z)
245 {
246 x_parent = y;
247
248 if (x)
249 x->p_parent = y;
250
251 y->p_left = z->p_left;
252 if (z->p_left)
253 z->p_left->p_parent = y;
254
255 if (!z->p_parent)
256 this->p_head = y;
257 else if (z->p_parent->p_left == z)
258 z->p_parent->p_left = y;
259 else
260 z->p_parent->p_right = y;
261
262 y->p_parent = z->p_parent;
263 y->m_color = z->m_color;
264 this->m_pool.deallocate(z);
265 }
266 else
267 {
268 x_parent = y->p_parent;
269
270 if (x)
271 x->p_parent = y->p_parent;
272
273 if (y->p_parent->p_left == y)
274 y->p_parent->p_left = x;
275 else
276 y->p_parent->p_right = x;
277
278 y->p_left = z->p_left;
279 if (z->p_left)
280 z->p_left->p_parent = y;
281
282 y->p_right = z->p_right;
283 if (z->p_right)
284 z->p_right->p_parent = y;
285
286 if (!z->p_parent)
287 this->p_head = y;
288 else if (z->p_parent->p_left == z)
289 z->p_parent->p_left = y;
290 else
291 z->p_parent->p_right = y;
292
293 y->p_parent = z->p_parent;
294 y->m_color = z->m_color;
295 this->m_pool.deallocate(z);
296 }
297 }
298
300 {
301 fix_delete_violation(x, x_parent);
302 }
303}
304
305template <typename T> void RBTree<T>::fix_delete_violation(Node<T> *x, Node<T> *x_parent)
306{
307 while (x != this->p_head && node_color(x) == Color::BLACK)
308 {
309 if (x_parent == nullptr)
310 break;
311
312 if (x == x_parent->p_left)
313 {
314 Node<T> *w = x_parent->p_right;
315
316 if (!w)
317 break;
318
319 if (node_color(w) == Color::RED)
320 {
321 w->m_color = Color::BLACK;
322 x_parent->m_color = Color::RED;
323 rotate_left(x_parent);
324 w = x_parent->p_right;
325 if (!w)
326 break;
327 }
328
329 if (node_color(w->p_left) == Color::BLACK && node_color(w->p_right) == Color::BLACK)
330 {
331 w->m_color = Color::RED;
332 x = x_parent;
333 x_parent = x->p_parent;
334 }
335 else
336 {
337 if (node_color(w->p_right) == Color::BLACK)
338 {
339 if (w->p_left)
340 w->p_left->m_color = Color::BLACK;
341 w->m_color = Color::RED;
342 rotate_right(w);
343 w = x_parent->p_right;
344 }
345
346 w->m_color = x_parent->m_color;
347 x_parent->m_color = Color::BLACK;
348 if (w->p_right)
349 w->p_right->m_color = Color::BLACK;
350 rotate_left(x_parent);
351 x = this->p_head;
352 }
353 }
354 else
355 {
356 Node<T> *w = x_parent->p_left;
357
358 if (!w)
359 break;
360
361 if (node_color(w) == Color::RED)
362 {
363 w->m_color = Color::BLACK;
364 x_parent->m_color = Color::RED;
365 rotate_right(x_parent);
366 w = x_parent->p_left;
367 if (!w)
368 break;
369 }
370
371 if (node_color(w->p_left) == Color::BLACK && node_color(w->p_right) == Color::BLACK)
372 {
373 w->m_color = Color::RED;
374 x = x_parent;
375 x_parent = x->p_parent;
376 }
377 else
378 {
379 if (node_color(w->p_left) == Color::BLACK)
380 {
381 if (w->p_right)
382 w->p_right->m_color = Color::BLACK;
383 w->m_color = Color::RED;
384 rotate_left(w);
385 w = x_parent->p_left;
386 }
387
388 w->m_color = x_parent->m_color;
389 x_parent->m_color = Color::BLACK;
390 if (w->p_left)
391 w->p_left->m_color = Color::BLACK;
392 rotate_right(x_parent);
393 x = this->p_head;
394 }
395 }
396 }
397
398 if (x)
399 x->m_color = Color::BLACK;
400}
401
402template <typename T> void RBTree<T>::clear()
403{
404 this->destroy_subtree(this->p_head);
405 this->p_head = nullptr;
406}
407
408template <typename T> int RBTree<T>::compute_black_height(const Node<T> *node) const
409{
410 if (!node)
411 return 1;
412
413 int left_bh = compute_black_height(node->p_left);
414 int right_bh = compute_black_height(node->p_right);
415
416 if (left_bh == -1 || right_bh == -1 || left_bh != right_bh)
417 return -1;
418
419 return left_bh + (node->m_color == Color::BLACK ? 1 : 0);
420}
421
422template <typename T> int RBTree<T>::get_black_height() const
423{
424 return compute_black_height(this->p_head);
425}
426
427template <typename T> bool RBTree<T>::validate_rb_helper(const Node<T> *node) const
428{
429 if (!node)
430 return true;
431
432 if (node->m_color == Color::RED)
433 {
434 if (node_color(node->p_left) == Color::RED || node_color(node->p_right) == Color::RED)
435 {
436 return false;
437 }
438 }
439
440 if (node->p_left && node->p_left->p_parent != node)
441 return false;
442 if (node->p_right && node->p_right->p_parent != node)
443 return false;
444
445 return validate_rb_helper(node->p_left) && validate_rb_helper(node->p_right);
446}
447
448template <typename T> bool RBTree<T>::validate_rb_properties() const
449{
450 if (!this->p_head)
451 return true;
452
453 if (this->p_head->m_color != Color::BLACK)
454 return false;
455
456 if (!validate_rb_helper(this->p_head))
457 return false;
458
459 if (compute_black_height(this->p_head) == -1)
460 return false;
461
462 if (this->p_head->p_parent != nullptr)
463 return false;
464
465 return true;
466}
467
468template <typename T> std::vector<T> RBTree<T>::to_sorted_vector() const
469{
470 std::vector<T> result;
471 std::stack<const Node<T> *> s;
472 const Node<T> *curr = this->p_head;
473
474 while (curr || !s.empty())
475 {
476 while (curr)
477 {
478 s.push(curr);
479 curr = curr->p_left;
480 }
481 curr = s.top();
482 s.pop();
483 result.push_back(curr->m_data);
484 curr = curr->p_right;
485 }
486
487 return result;
488}
489
490} // namespace stl_ext
static bool is_black(const Node< T > *node)
Definition rbt.tpp:12
static bool is_red(const Node< T > *node)
Definition rbt.tpp:7
bool validate_rb_properties() const
Definition rbt.tpp:448
static Color get_color(const Node< T > *node)
Definition rbt.tpp:17
std::vector< T > to_sorted_vector() const
Definition rbt.tpp:468
void remove(const T &val) override
Definition rbt.tpp:184
int get_black_height() const
Definition rbt.tpp:422
void insert(const T &val) override
Definition rbt.tpp:76
void clear()
Definition rbt.tpp:402
Definition cppx.h:17
Color
Definition cppx.h:20