neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
red_black_tree.hpp
Go to the documentation of this file.
1/*
2 * red_black_tree.hpp
3 *
4 * Copyright (c) 2007 Leigh Johnston.
5 *
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * * Neither the name of Leigh Johnston nor the names of any
20 * other contributors to this software may be used to endorse or
21 * promote products derived from this software without specific prior
22 * written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
26 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35*/
36
37#pragma once
38
39#include <neolib/neolib.hpp>
40
41namespace neolib
42{
44 {
45 public:
46 struct already_have_left_node : std::logic_error { already_have_left_node() : std::logic_error("neolib::red_black_tree::already_have_left_node") {} };
47 struct already_have_right_node : std::logic_error { already_have_right_node() : std::logic_error("neolib::red_black_tree::already_have_right_node") {} };
48 protected:
49 class node
50 {
51 public:
52 struct no_left_node : std::logic_error { no_left_node() : std::logic_error("neolib::red_black_tree::node::no_left_node") {} };
53 struct no_right_node : std::logic_error { no_right_node() : std::logic_error("neolib::red_black_tree::node::no_right_node") {} };
54 struct no_sibling : std::logic_error { no_sibling() : std::logic_error("neolib::red_black_tree::node::no_sibling") {} };
55 public:
57 {
60 RED
61 };
62
63 public:
64 node(color_e aColor = RED) :
65 iColor{ aColor }, iParent{ aColor != NIL ? nullptr : this }, iLeft{ aColor != NIL ? nullptr : this }, iRight{ aColor != NIL ? nullptr : this }
66 {
67 }
68 node(const node& aOther) :
69 iColor{ aOther.iColor }, iParent{ aOther.iColor != NIL ? nullptr : this }, iLeft{ aOther.iColor != NIL ? nullptr : this }, iRight{ aOther.iColor != NIL ? nullptr : this }
70 {
71 }
73 {
74 }
75
76 public:
77 bool is_nil() const
78 {
79 return iColor == NIL;
80 }
81 color_e color() const
82 {
83 return iColor != NIL ? iColor : BLACK;
84 }
85 void set_color(color_e aColor)
86 {
87 if (iColor != NIL)
88 iColor = aColor;
89 }
90 bool has_parent() const
91 {
92 return iParent != nullptr && !iParent->is_nil();
93 }
94 node* parent() const
95 {
96 return iParent;
97 }
98 void set_parent(node* aParent)
99 {
100 iParent = aParent;
101 }
102 bool has_left() const
103 {
104 return iLeft != nullptr && !iLeft->is_nil();
105 }
106 node* left() const
107 {
108 if (iLeft != nullptr)
109 return iLeft;
110 throw no_left_node();
111 }
112 void set_left(node* aLeft)
113 {
114 iLeft = aLeft;
115 }
116 bool has_right() const
117 {
118 return iRight != nullptr && !iRight->is_nil();
119 }
120 node* right() const
121 {
122 if (iRight != nullptr)
123 return iRight;
124 throw no_right_node();
125 }
126 void set_right(node* aRight)
127 {
128 iRight = aRight;
129 }
130 bool has_sibling() const
131 {
132 return has_parent() && ((parent()->left() == this && parent()->has_right()) || (parent()->right() == this && parent()->has_left()));
133 }
134 node* sibling() const
135 {
136 if (has_sibling())
137 return parent()->left() == this ? parent()->right() : parent()->left();
138 throw no_sibling();
139 }
140 void replace(node* aGarbage, node* aNil)
141 {
142 set_color(aGarbage->color());
143 set_parent(aGarbage->parent());
144 set_left(aGarbage->left());
145 set_right(aGarbage->right());
146 if (parent()->left() == aGarbage)
147 parent()->set_left(this);
148 else if (parent()->right() == aGarbage)
149 parent()->set_right(this);
150 if (!left()->is_nil())
151 left()->set_parent(this);
152 if (!right()->is_nil())
153 right()->set_parent(this);
154 aGarbage->set_parent(nullptr);
155 aGarbage->set_left(nullptr);
156 aGarbage->set_right(nullptr);
157 if (aNil->parent() == aGarbage)
158 aNil->set_parent(this);
159 if (aNil->left() == aGarbage)
160 aNil->set_left(this);
161 if (aNil->right() == aGarbage)
162 aNil->set_right(this);
163 }
164
165 private:
166 color_e iColor;
167 node* iParent;
168 node* iLeft;
169 node* iRight;
170 };
171
172 public:
174 iRoot{ nullptr }, iNil{ node::NIL }
175 {
177 }
179 {
180 }
181
182 public:
183 void clear()
184 {
185 *nil_node() = node{ node::NIL };
187 }
188 node* nil_node() const
189 {
190 return &iNil;
191 }
193 {
194 return iRoot;
195 }
196 void set_root_node(node* aRoot)
197 {
198 iRoot = aRoot;
199 }
200 template <typename Predicate>
201 void insert_node(node* aNode, Predicate aPredicate, node* aHint = nullptr)
202 {
203 node* z = aNode;
204 node* y = nil_node();
205 node* x = (aHint == nullptr ? root_node() : aHint);
206 while (x != nil_node())
207 {
208 y = x;
209 if (aPredicate(z, x))
210 x = x->left();
211 else
212 x = x->right();
213 }
214 z->set_parent(y);
215 if (y == nil_node())
216 set_root_node(z);
217 else
218 {
219 if (aPredicate(z, y))
220 y->set_left(z);
221 else
222 y->set_right(z);
223 }
224 z->set_left(nil_node());
225 z->set_right(nil_node());
226 insert_fixup(z);
227 }
228 void delete_node(node* aNode)
229 {
230 node* z = aNode;
231 node *y;
232 if (z->left() == nil_node() || z->right() == nil_node())
233 y = z;
234 else
235 y = tree_successor(z);
236 node* x;
237 if (y->left() != nil_node())
238 x = y->left();
239 else
240 x = y->right();
241 x->set_parent(y->parent());
242 if (y->parent() == nil_node())
243 set_root_node(x);
244 else
245 {
246 if (y == y->parent()->left())
247 y->parent()->set_left(x);
248 else
249 y->parent()->set_right(x);
250 }
251 bool performDeleteFixup = (y->color() == node::BLACK);
252 if (y != z)
253 {
254 y->replace(z, nil_node());
255 if (root_node() == z)
256 set_root_node(y);
257 }
258 if (performDeleteFixup)
259 delete_fixup(x);
260 }
261 void swap(red_black_tree& aOther)
262 {
263 std::swap(iRoot, aOther.iRoot);
264 std::swap(iNil, aOther.iNil);
265 }
266
267 private:
268 void insert_fixup(node* aNode)
269 {
270 node* z = aNode;
271 while (z->parent()->color() == node::RED)
272 {
273 if (z->parent() == z->parent()->parent()->left())
274 {
275 node* y = z->parent()->parent()->right();
276 if (y->color() == node::RED)
277 {
278 z->parent()->set_color(node::BLACK);
279 y->set_color(node::BLACK);
280 z->parent()->parent()->set_color(node::RED);
281 z = z->parent()->parent();
282 }
283 else
284 {
285 if (z == z->parent()->right())
286 {
287 z = z->parent();
288 left_rotate(z);
289 }
290 z->parent()->set_color(node::BLACK);
291 z->parent()->parent()->set_color(node::RED);
292 right_rotate(z->parent()->parent());
293 }
294 }
295 else
296 {
297 node* y = z->parent()->parent()->left();
298 if (y->color() == node::RED)
299 {
300 z->parent()->set_color(node::BLACK);
301 y->set_color(node::BLACK);
302 z->parent()->parent()->set_color(node::RED);
303 z = z->parent()->parent();
304 }
305 else
306 {
307 if (z == z->parent()->left())
308 {
309 z = z->parent();
310 right_rotate(z);
311 }
312 z->parent()->set_color(node::BLACK);
313 z->parent()->parent()->set_color(node::RED);
314 left_rotate(z->parent()->parent());
315 }
316 }
317 }
319 }
320 void left_rotate(node* aNode)
321 {
322 node* x = aNode;
323 node* y = x->right();
324 x->set_right(y->left());
325 if (y->left() != nil_node())
326 y->left()->set_parent(x);
327 y->set_parent(x->parent());
328 if (x->parent() == nil_node())
329 set_root_node(y);
330 else
331 {
332 if (x == x->parent()->left())
333 x->parent()->set_left(y);
334 else
335 x->parent()->set_right(y);
336 }
337 y->set_left(x);
338 x->set_parent(y);
339 }
340 void right_rotate(node* aNode)
341 {
342 node* y = aNode;
343 node* x = y->left();
344 y->set_left(x->right());
345 if (x->right() != nil_node())
346 x->right()->set_parent(y);
347 x->set_parent(y->parent());
348 if (y->parent() == nil_node())
349 set_root_node(x);
350 else
351 {
352 if (y == y->parent()->right())
353 y->parent()->set_right(x);
354 else
355 y->parent()->set_left(x);
356 }
357 x->set_right(y);
358 y->set_parent(x);
359 }
360 node* tree_minimum(node* aNode)
361 {
362 node* x = aNode;
363 while (x->left() != nil_node())
364 x = x->left();
365 return x;
366 }
367 node* tree_successor(node* aNode)
368 {
369 node* x = aNode;
370 if (x->right() != nil_node())
371 return tree_minimum(x->right());
372 node* y = x->parent();
373 while (y != nil_node() && x == y->right())
374 {
375 x = y;
376 y = y->parent();
377 }
378 return y;
379 }
380 void delete_fixup(node* aNode)
381 {
382 node* x = aNode;
383 while (x != root_node() && x->color() == node::BLACK)
384 {
385 if (x == x->parent()->left())
386 {
387 node* w = x->parent()->right();
388 if (w->color() == node::RED)
389 {
390 w->set_color(node::BLACK);
391 x->parent()->set_color(node::RED);
392 left_rotate(x->parent());
393 w = x->parent()->right();
394 }
395 if (w->left()->color() == node::BLACK && w->right()->color() == node::BLACK)
396 {
397 w->set_color(node::RED);
398 x = x->parent();
399 }
400 else
401 {
402 if (w->right()->color() == node::BLACK)
403 {
404 w->left()->set_color(node::BLACK);
405 w->set_color(node::RED);
406 right_rotate(w);
407 w = x->parent()->right();
408 }
409 w->set_color(x->parent()->color());
410 x->parent()->set_color(node::BLACK);
411 w->right()->set_color(node::BLACK);
412 left_rotate(x->parent());
413 x = root_node();
414 }
415 }
416 else
417 {
418 node* w = x->parent()->left();
419 if (w->color() == node::RED)
420 {
421 w->set_color(node::BLACK);
422 x->parent()->set_color(node::RED);
423 right_rotate(x->parent());
424 w = x->parent()->left();
425 }
426 if (w->right()->color() == node::BLACK && w->left()->color() == node::BLACK)
427 {
428 w->set_color(node::RED);
429 x = x->parent();
430 }
431 else
432 {
433 if (w->left()->color() == node::BLACK)
434 {
435 w->right()->set_color(node::BLACK);
436 w->set_color(node::RED);
437 left_rotate(w);
438 w = x->parent()->left();
439 }
440 w->set_color(x->parent()->color());
441 x->parent()->set_color(node::BLACK);
442 w->left()->set_color(node::BLACK);
443 right_rotate(x->parent());
444 x = root_node();
445 }
446 }
447 }
448 x->set_color(node::BLACK);
449 }
450
451 private:
452 node* iRoot;
453 mutable node iNil;
454 };
455}
void set_parent(node *aParent)
void replace(node *aGarbage, node *aNil)
void set_color(color_e aColor)
void swap(red_black_tree &aOther)
void delete_node(node *aNode)
void set_root_node(node *aRoot)
void insert_node(node *aNode, Predicate aPredicate, node *aHint=nullptr)
void swap(plf::hive< element_type, allocator_type > &a, plf::hive< element_type, allocator_type > &b) noexcept(std::allocator_traits< allocator_type >::propagate_on_container_swap::value||std::allocator_traits< allocator_type >::is_always_equal::value)
Definition plf_hive.h:4776