neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
array_tree.hpp
Go to the documentation of this file.
1/*
2 * array_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{
43 template <typename Alloc>
45 {
46 public:
47 typedef std::size_t size_type;
48 typedef std::ptrdiff_t difference_type;
49 typedef Alloc allocator_type;
50 protected:
51 class node
52 {
53 friend array_tree;
54
55 public:
56 struct no_left_node : std::logic_error { no_left_node() : std::logic_error("neolib::array_tree::node::no_left_node") {} };
57 struct no_right_node : std::logic_error { no_right_node() : std::logic_error("neolib::array_tree::node::no_right_node") {} };
58
59 public:
61 {
64 RED
65 };
66
67 public:
68 node(color_e aColor = RED) :
69 iColor{ aColor }, iParent{ aColor != NIL ? nullptr : this }, iLeft{ aColor != NIL ? nullptr : this }, iRight{ aColor != NIL ? nullptr : this }, iPrevious{ nullptr }, iNext{ nullptr }, iSize { 0 }
70 {
71 }
72 node(const node& aOther) :
73 iColor{ aOther.iColor }, iParent{ aOther.iColor != NIL ? nullptr : this }, iLeft{ aOther.iColor != NIL ? nullptr : this }, iRight{ aOther.iColor != NIL ? nullptr : this }, iPrevious{ nullptr }, iNext{ nullptr }, iSize{ 0 }
74 {
75 }
77 {
78 }
79
80 public:
81 bool is_nil() const
82 {
83 return iColor == NIL;
84 }
85 color_e color() const
86 {
87 return iColor != NIL ? iColor : BLACK;
88 }
89 void set_color(color_e aColor)
90 {
91 if (iColor != NIL)
92 iColor = aColor;
93 }
94 node* parent() const
95 {
96 return iParent;
97 }
98 void set_parent(node* aParent)
99 {
100 iParent = aParent;
101 }
102 node* left() const
103 {
104 if (iLeft != nullptr)
105 return iLeft;
106 throw no_left_node();
107 }
108 void set_left(node* aLeft)
109 {
110 iLeft = aLeft;
111 }
112 node* right() const
113 {
114 if (iRight != nullptr)
115 return iRight;
116 throw no_right_node();
117 }
118 void set_right(node* aRight)
119 {
120 iRight = aRight;
121 }
122 node* previous() const
123 {
124 return iPrevious;
125 }
126 void set_previous(node* aPrevoius)
127 {
128 iPrevious = aPrevoius;
129 }
130 node* next() const
131 {
132 return iNext;
133 }
134 void set_next(node* aNext)
135 {
136 iNext = aNext;
137 }
139 {
140 return iColor != NIL ? iSize : 0;
141 }
143 {
144 return left() ? left()->size() : 0;
145 }
147 {
148 return right() ? right()->size() : 0;
149 }
150 void set_size(size_type aSize)
151 {
152 if (!is_nil())
153 {
154 difference_type difference = aSize - iSize;
155 if (difference != 0)
156 {
157 iSize += difference;
158 if (parent() != nullptr && !parent()->is_nil())
159 parent()->set_size(parent()->size() + difference);
160 }
161 }
162 }
163 void replace(node* aGarbage, node* aNil)
164 {
165 set_color(aGarbage->color());
166 set_parent(aGarbage->parent());
167 set_left(aGarbage->left());
168 set_right(aGarbage->right());
169 if (parent()->left() == aGarbage)
170 parent()->set_left(this);
171 else if (parent()->right() == aGarbage)
172 parent()->set_right(this);
173 if (!left()->is_nil())
174 left()->set_parent(this);
175 if (!right()->is_nil())
176 right()->set_parent(this);
177 aGarbage->set_parent(nullptr);
178 aGarbage->set_left(nullptr);
179 aGarbage->set_right(nullptr);
180 if (aNil->parent() == aGarbage)
181 aNil->set_parent(this);
182 if (aNil->left() == aGarbage)
183 aNil->set_left(this);
184 if (aNil->right() == aGarbage)
185 aNil->set_right(this);
186 }
187
188 private:
189 color_e iColor;
190 node* iParent;
191 node* iLeft;
192 node* iRight;
193 node* iPrevious;
194 node* iNext;
195 size_type iSize;
196 };
197 private:
198 typedef typename std::allocator_traits<allocator_type>:: template rebind_alloc<node> node_allocator_type;
199
200 public:
201 array_tree(const Alloc& aAllocator = Alloc()) :
202 iAllocator{ aAllocator },
203 iRoot{ nullptr },
204 iFront{ nullptr },
205 iBack{ nullptr },
206 iNil{ nullptr }
207 {
208 iNil = std::allocator_traits<node_allocator_type>::allocate(iAllocator, 1);
209 try
210 {
211 std::allocator_traits<node_allocator_type>::construct(iAllocator, iNil, node(node::NIL));
212 }
213 catch (...)
214 {
215 std::allocator_traits<node_allocator_type>::deallocate(iAllocator, iNil, 1);
216 throw;
217 }
218 set_root_node(iNil);
219 }
220 array_tree(const array_tree& aOther) :
221 iAllocator{ aOther.iAllocator },
222 iRoot{ nullptr },
223 iFront{ nullptr },
224 iBack{ nullptr },
225 iNil{ nullptr }
226 {
227 iNil = std::allocator_traits<node_allocator_type>::allocate(iAllocator, 1);
228 try
229 {
230 std::allocator_traits<node_allocator_type>::construct(iAllocator, iNil, node(node::NIL));
231 }
232 catch (...)
233 {
234 std::allocator_traits<node_allocator_type>::deallocate(iAllocator, iNil, 1);
235 throw;
236 }
237 set_root_node(iNil);
238 }
240 iAllocator{ std::move(other.iAllocator) },
241 iRoot{ nullptr },
242 iFront{ nullptr },
243 iBack{ nullptr },
244 iNil{ nullptr }
245 {
246 std::swap(iRoot, other.iRoot);
247 std::swap(iFront, other.iFront);
248 std::swap(iBack, other.iBack);
249 std::swap(iNil, other.iNil);
250 }
252 {
253 std::allocator_traits<node_allocator_type>::destroy(iAllocator, iNil);
254 std::allocator_traits<node_allocator_type>::deallocate(iAllocator, iNil, 1);
255 }
256
257 public:
258 node* nil_node() const
259 {
260 return iNil;
261 }
263 {
264 return iRoot;
265 }
266 void set_root_node(node* aRoot)
267 {
268 iRoot = aRoot;
269 }
271 {
272 return iFront;
273 }
274 void set_front_node(node* aFront)
275 {
276 iFront = aFront;
277 }
279 {
280 return iBack;
281 }
282 void set_back_node(node* aBack)
283 {
284 iBack = aBack;
285 }
286 static size_type size(node* aNode)
287 {
288 return aNode ? aNode->size() : 0;
289 }
291 {
292 return aNode && aNode->parent() ? aNode->parent()->size() : 0;
293 }
294 static size_type size_left(node* aNode)
295 {
296 return aNode && aNode->left() ? aNode->left()->size() : 0;
297 }
298 static size_type size_right(node* aNode)
299 {
300 return aNode && aNode->right() ? aNode->right()->size() : 0;
301 }
302 node* find_node(size_type aPosition, size_type& aNodeIndex) const
303 {
304 node* x = root_node();
305 size_type index = size_left(x);
306 while (x != nil_node() && (aPosition < index || aPosition >= index + (size(x) - size_left(x) - size_right(x))))
307 {
308 if (aPosition < index)
309 {
310 x = x->left();
311 index -= (size(x) - size_left(x));
312 }
313 else
314 {
315 index += size(x) - size_left(x) - size_right(x) + size_left(x->right());
316 x = x->right();
317 }
318 }
319 aNodeIndex = index;
320 return x;
321 }
322 void insert_node(node* aNode, size_type aPosition)
323 {
324 node* z = aNode;
325 node* y = nil_node();
326 node* x = root_node();
327 size_type index = size_left(x);
328 size_type previousIndex = index;
329 while (x != nil_node())
330 {
331 previousIndex = index;
332 y = x;
333 if (aPosition <= index)
334 {
335 x = x->left();
336 index -= (size(x) - size_left(x));
337 }
338 else
339 {
340 index += size(x) - size_left(x) - size_right(x) + size_left(x->right());
341 x = x->right();
342 }
343 }
344 z->set_parent(y);
345 if (y == nil_node())
346 set_root_node(z);
347 else
348 {
349 if (aPosition <= previousIndex)
350 y->set_left(z);
351 else
352 y->set_right(z);
353 }
354 z->set_left(nil_node());
355 z->set_right(nil_node());
356 if (z->parent() != nil_node())
357 z->parent()->set_size(z->parent()->size() + z->size());
358 insert_fixup(z);
359 }
360 void delete_node(node* aNode)
361 {
362 node* z = aNode;
363 z->set_size(z->left_size() + z->right_size());
364 node *y;
365 if (z->left() == nil_node() || z->right() == nil_node())
366 y = z;
367 else
368 y = tree_successor(z);
369 node* x;
370 if (y->left() != nil_node())
371 x = y->left();
372 else
373 x = y->right();
374 if (y != z)
375 {
376 y->parent()->set_size(y->parent()->size() - y->size());
377 y->parent()->set_size(y->parent()->size() + x->size());
378 }
379 x->set_parent(y->parent());
380 if (y->parent() == nil_node())
381 set_root_node(x);
382 else
383 {
384 if (y == y->parent()->left())
385 y->parent()->set_left(x);
386 else
387 y->parent()->set_right(x);
388 }
389 bool performDeleteFixup = (y->color() == node::BLACK);
390 if (y != z)
391 {
392 z->parent()->set_size(z->parent()->size() - z->size());
393 y->iSize = y->size() - size_left(y) - size_right(y);
394 y->replace(z, nil_node());
395 if (root_node() == z)
396 set_root_node(y);
397 y->iSize = y->size() + size_left(y) + size_right(y);
398 y->parent()->set_size(y->parent()->size() + y->size());
399 }
400 if (performDeleteFixup)
401 delete_fixup(x);
402 }
403 void swap(array_tree& aOther)
404 {
405 std::swap(iAllocator, aOther.iAllocator);
406 std::swap(iRoot, aOther.iRoot);
407 std::swap(iFront, aOther.iFront);
408 std::swap(iBack, aOther.iBack);
409 std::swap(iNil, aOther.iNil);
410 }
411
412 private:
413 void insert_fixup(node* aNode)
414 {
415 node* z = aNode;
416 while (z->parent()->color() == node::RED)
417 {
418 if (z->parent() == z->parent()->parent()->left())
419 {
420 node* y = z->parent()->parent()->right();
421 if (y->color() == node::RED)
422 {
423 z->parent()->set_color(node::BLACK);
424 y->set_color(node::BLACK);
425 z->parent()->parent()->set_color(node::RED);
426 z = z->parent()->parent();
427 }
428 else
429 {
430 if (z == z->parent()->right())
431 {
432 z = z->parent();
433 left_rotate(z);
434 }
435 z->parent()->set_color(node::BLACK);
436 z->parent()->parent()->set_color(node::RED);
437 right_rotate(z->parent()->parent());
438 }
439 }
440 else
441 {
442 node* y = z->parent()->parent()->left();
443 if (y->color() == node::RED)
444 {
445 z->parent()->set_color(node::BLACK);
446 y->set_color(node::BLACK);
447 z->parent()->parent()->set_color(node::RED);
448 z = z->parent()->parent();
449 }
450 else
451 {
452 if (z == z->parent()->left())
453 {
454 z = z->parent();
455 right_rotate(z);
456 }
457 z->parent()->set_color(node::BLACK);
458 z->parent()->parent()->set_color(node::RED);
459 left_rotate(z->parent()->parent());
460 }
461 }
462 }
464 }
465 void left_rotate(node* aNode)
466 {
467 node* x = aNode;
468 node* y = x->right();
469 x->set_right(y->left());
470 if (y->left() != nil_node())
471 y->left()->set_parent(x);
472 y->set_parent(x->parent());
473 if (x->parent() == nil_node())
474 set_root_node(y);
475 else
476 {
477 if (x == x->parent()->left())
478 x->parent()->set_left(y);
479 else
480 x->parent()->set_right(y);
481 }
482 y->set_left(x);
483 x->set_parent(y);
484 size_type previousSize = y->size();
485 /* do not use set_size() as we don't want to propagate to ancestors */
486 y->iSize = x->size();
487 x->iSize -= previousSize;
488 x->iSize += x->right()->size();
489 }
490 void right_rotate(node* aNode)
491 {
492 node* y = aNode;
493 node* x = y->left();
494 y->set_left(x->right());
495 if (x->right() != nil_node())
496 x->right()->set_parent(y);
497 x->set_parent(y->parent());
498 if (y->parent() == nil_node())
499 set_root_node(x);
500 else
501 {
502 if (y == y->parent()->right())
503 y->parent()->set_right(x);
504 else
505 y->parent()->set_left(x);
506 }
507 x->set_right(y);
508 y->set_parent(x);
509 size_type previousSize = x->size();
510 /* do not use set_size() as we don't want to propagate to ancestors */
511 x->iSize = y->size();
512 y->iSize -= previousSize;
513 y->iSize += y->left()->size();
514 }
515 node* tree_minimum(node* aNode)
516 {
517 node* x = aNode;
518 while (x->left() != nil_node())
519 x = x->left();
520 return x;
521 }
522 node* tree_successor(node* aNode)
523 {
524 node* x = aNode;
525 if (x->right() != nil_node())
526 return tree_minimum(x->right());
527 node* y = x->parent();
528 while (y != nil_node() && x == y->right())
529 {
530 x = y;
531 y = y->parent();
532 }
533 return y;
534 }
535 void delete_fixup(node* aNode)
536 {
537 node* x = aNode;
538 while (x != root_node() && x->color() == node::BLACK)
539 {
540 if (x == x->parent()->left())
541 {
542 node* w = x->parent()->right();
543 if (w->color() == node::RED)
544 {
545 w->set_color(node::BLACK);
546 x->parent()->set_color(node::RED);
547 left_rotate(x->parent());
548 w = x->parent()->right();
549 }
550 if (w->left()->color() == node::BLACK && w->right()->color() == node::BLACK)
551 {
552 w->set_color(node::RED);
553 x = x->parent();
554 }
555 else
556 {
557 if (w->right()->color() == node::BLACK)
558 {
559 w->left()->set_color(node::BLACK);
560 w->set_color(node::RED);
561 right_rotate(w);
562 w = x->parent()->right();
563 }
564 w->set_color(x->parent()->color());
565 x->parent()->set_color(node::BLACK);
566 w->right()->set_color(node::BLACK);
567 left_rotate(x->parent());
568 x = root_node();
569 }
570 }
571 else
572 {
573 node* w = x->parent()->left();
574 if (w->color() == node::RED)
575 {
576 w->set_color(node::BLACK);
577 x->parent()->set_color(node::RED);
578 right_rotate(x->parent());
579 w = x->parent()->left();
580 }
581 if (w->right()->color() == node::BLACK && w->left()->color() == node::BLACK)
582 {
583 w->set_color(node::RED);
584 x = x->parent();
585 }
586 else
587 {
588 if (w->left()->color() == node::BLACK)
589 {
590 w->right()->set_color(node::BLACK);
591 w->set_color(node::RED);
592 left_rotate(w);
593 w = x->parent()->left();
594 }
595 w->set_color(x->parent()->color());
596 x->parent()->set_color(node::BLACK);
597 w->left()->set_color(node::BLACK);
598 right_rotate(x->parent());
599 x = root_node();
600 }
601 }
602 }
603 x->set_color(node::BLACK);
604 }
605
606 private:
607 node_allocator_type iAllocator;
608 node* iRoot;
609 node* iFront;
610 node* iBack;
611 node* iNil;
612 };
613}
node(const node &aOther)
color_e color() const
node(color_e aColor=RED)
void replace(node *aGarbage, node *aNil)
void set_parent(node *aParent)
void set_color(color_e aColor)
size_type size() const
void set_size(size_type aSize)
void set_right(node *aRight)
void set_next(node *aNext)
void set_left(node *aLeft)
size_type left_size() const
void set_previous(node *aPrevoius)
size_type right_size() const
static size_type size_left(node *aNode)
array_tree(const Alloc &aAllocator=Alloc())
static size_type size(node *aNode)
array_tree(array_tree &&other)
node * find_node(size_type aPosition, size_type &aNodeIndex) const
node * back_node() const
node * root_node() const
static size_type size_right(node *aNode)
node * front_node() const
array_tree(const array_tree &aOther)
node * nil_node() const
void insert_node(node *aNode, size_type aPosition)
void set_front_node(node *aFront)
void delete_node(node *aNode)
std::size_t size_type
void swap(array_tree &aOther)
std::ptrdiff_t difference_type
void set_back_node(node *aBack)
static size_type size_parent(node *aNode)
void set_root_node(node *aRoot)
Definition plf_hive.h:79
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