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