31#ifndef FENNEC_CONTAINERS_RDTREE_H
32#define FENNEC_CONTAINERS_RDTREE_H
48template<
typename TypeT,
typename AllocT = allocator<TypeT>>
56 using value_t = TypeT;
58 static constexpr size_t root = 0;
59 static constexpr size_t npos = -1;
64 size_t parent, child, prev, next;
65 size_t depth, num_children;
69 , parent(npos), child(npos)
70 , prev(npos), next(npos)
71 , depth(0), num_children(0) {
74 template<
typename...ArgsT>
75 constexpr node(
size_t p,
size_t c,
size_t v,
size_t n,
size_t d, ArgsT&&...args)
76 : value(fennec::forward<ArgsT>(args)...)
77 , parent(p), child(c), prev(v), next(n)
78 , depth(d), num_children(0) {
102 template<
typename...ArgsT>
103 explicit constexpr rdtree(ArgsT&&...args)
104 : _table(), _freed(), _size(1) {
106 fennec::construct(&_table[0], npos, npos, npos, npos, 0, fennec::forward<ArgsT>(args)...);
113 : _table(tree._table), _freed(tree._freed), _size(tree._size) {
120 : _table(fennec::move(tree._table)), _freed(fennec::move(tree._freed)), _size(tree._size) {
136 for (value_t* it : this->_table) {
137 fennec::destruct(it);
150 for (value_t* it : _table) {
151 fennec::destruct(it);
168 constexpr size_t size()
const {
190 constexpr size_t parent(
size_t i)
const {
191 if (i >= _table.
capacity())
return npos;
192 return i == npos ? npos : _table[i].parent;
198 constexpr size_t child(
size_t i,
size_t n = 0)
const {
199 if (i >= _table.
capacity() && n != npos)
return npos;
200 size_t c = i == npos ? npos : _table[i].child;
202 return next(c, n == npos ? npos : n - 1);
209 constexpr size_t next(
size_t i,
size_t n = 0)
const {
210 if (i >= _table.
capacity() && n != npos)
return npos;
216 size_t nxt = _table[i].next;
217 while (nxt != npos) {
219 nxt = _table[i].next;
227 return i == org && n != npos ? npos : i;
233 constexpr size_t prev(
size_t i,
size_t n = 0)
const {
234 if (i >= _table.
capacity())
return npos;
240 size_t prv = _table[i].prev;
241 while (prv != npos) {
243 prv = _table[i].prev;
251 return i == org && n != npos ? npos : i;
258 if (i >= _table.
capacity())
return npos;
260 if ((n =
child(n)) == npos) {
265 if ((n =
child(n)) == npos) {
275 if (i >= _table.
capacity())
return npos;
276 if ((i =
child(i)) == npos) {
281 while ((n =
next(i)) != npos) {
285 if ((i =
child(i)) == npos) {
294 constexpr size_t depth(
size_t i)
const {
295 if (i >= _table.
capacity())
return npos;
296 return i == npos ? npos : _table[i].depth;
303 if (i >= _table.
capacity())
return 0;
304 return i == npos ? 0 : _table[i].num_children;
311 if (not _freed.
empty()) {
321 return _table[i].value;
328 return _table[i].value;
351 return this->_insert(
parent,
next, fennec::forward<value_t>(val));
359 while (not visit.
empty()) {
360 auto node = visit.
front();
363 size_t p = this->_insert(node.second, node.second ==
parent ?
next : npos, tree[node.first]);
365 res = (res == npos) ? p : res;
367 size_t c = tree.
child(node.first, npos);
370 c = tree._table[c].prev;
383 template<
typename...ArgsT>
385 return this->_insert(
parent,
next, fennec::forward<ArgsT>(args)...);
392 constexpr void swap(
size_t i0,
size_t i1) {
393 assertf(i0 != root and i1 != root,
"Cannot Swap With Root");
405 if (
child(p0) == i0) _table[p0].child = i1;
406 if (
child(p1) == i1) _table[p1].child = i0;
433 template<
typename OrderT,
typename VisitorT>
434 constexpr void traverse(VisitorT&& visit,
size_t i = root) {
438 uint8_t mode = traversal_control_continue;
439 if (_table[i].value) {
440 mode = visit(_table[i].value, i);
442 if (mode == traversal_control_break) {
445 i = order[*
this, i, mode];
449 struct breadth_first {
453 constexpr size_t operator()(
const rdtree&,
size_t start) {
458 constexpr size_t operator[](
const rdtree& tree,
size_t node, uint8_t mode) {
463 size_t nxt = tree.next(node);
464 size_t chd = tree.next(node);
466 if (nxt != npos && node != head) {
470 if (chd != npos && mode != traversal_control_jump_over) {
474 if (not visit.
empty()) {
475 node = visit.
front();
489 constexpr size_t operator()(
const rdtree&,
size_t start) {
494 constexpr size_t operator[](
const rdtree& tree,
size_t node, uint8_t mode) {
499 size_t nxt = tree.next(node);
500 size_t chd = tree.child(node);
502 if (nxt != npos && node != head) {
506 if (chd != npos && mode != traversal_control_jump_over) {
507 visit.push_front(chd);
510 if (not visit.empty()) {
511 node = visit.front();
525 constexpr size_t operator()(
const rdtree& tree,
size_t start) {
527 return tree.left_most(start);
530 constexpr size_t operator[](
const rdtree& tree,
size_t node, uint8_t) {
535 size_t prnt = tree.parent(node);
536 size_t next = tree.next(node);
538 if (tree.child(prnt) == node) {
539 visit.push_back(prnt);
541 visit.push_back(tree.left_most(
next));
543 }
else if (
next != npos) {
544 visit.push_front(tree.left_most(
next));
548 if (not visit.empty()) {
549 node = visit.front();
563 constexpr size_t operator()(
const rdtree& tree,
size_t start) {
565 return tree.left_most(start);
568 constexpr size_t operator[](
const rdtree& tree,
size_t node, uint8_t) {
573 size_t prnt = tree.parent(node);
574 size_t next = tree.next(node);
578 visit.push_front(tree.left_most(
next));
580 visit.push_front(prnt);
584 if (not visit.empty()) {
585 node = visit.front();
597 allocation<node, alloc_t> _table;
602 _table.creallocate(_table.capacity() * 2);
605 size_t _next_free() {
607 if (not _freed.empty()) {
608 next = _freed.front();
618 template<
typename...ArgsT>
619 constexpr size_t _insert(
size_t p,
size_t n, ArgsT&&...args) {
621 fennec::construct(&_table[root], npos, npos, npos, npos, 0, fennec::forward<ArgsT>(args)...);
627 _table[root].value = value_t(fennec::forward<ArgsT>(args)...);
628 _size = _size == 0 ? 1 : _size;
632 size_t idx = _next_free();
633 size_t nxt =
child(p, n);
634 size_t prv = n == npos ? npos :
prev(n);
636 ++_table[p].num_children;
637 if ((nxt ==
child(p) && n != npos) || nxt == npos) {
638 _table[p].child = idx;
643 _table[nxt].next = idx;
645 fennec::construct(&_table[idx], p, npos, nxt, npos,
depth(p) + 1, fennec::forward<ArgsT>(args)...);
648 _table[nxt].prev = idx;
651 _table[prv].next = idx;
653 fennec::construct(&_table[idx], p, npos, prv, nxt,
depth(p) + 1, fennec::forward<ArgsT>(args)...);
658 constexpr void _erase(
size_t i) {
660 queue.push_back(
child(i));
661 while (not queue.empty()) {
662 size_t n = queue.front(); queue.pop_front();
663 if (n == npos)
continue;
664 queue.push_back(
next(n));
665 queue.push_back(
child(n));
666 fennec::destruct(&_table[n]);
671 fennec::destruct(&_table[i]);
672 if (i != root) _freed.push_back(i);
This header contains structures and classes related to allocating blocks of memory.
A header containing the definition for a linked list of values.
A header containing the definition for a container with an optionally present variable.
A header containing the definition for a container holding a pair of values.
constexpr size_t capacity() const
Getter for the number of elements n of type T that the allocation can hold.
Definition allocator.h:617
constexpr void creallocate(size_t n, align_t align=zero< align_t >()) noexcept
Reallocate the block with a new size. Contents are copied to the new allocation.
Definition allocator.h:541
typename _rebind< Alloc, TypeT >::type rebind
Rebinds the allocator type to produce an element type of type TypeT
Definition allocator.h:134
Data Structure defining lists of elements.
Definition list.h:67
constexpr void pop_front()
Pop Front, erases first element.
Definition list.h:380
constexpr bool empty() const
Definition list.h:181
constexpr size_t push_back(const value_t &x)
Push Back Copy.
Definition list.h:342
constexpr size_t push_front(const value_t &x)
Push Front Copy.
Definition list.h:319
constexpr value_t & front()
Access Front Element.
Definition list.h:222
Rooted-Directed Tree.
Definition rdtree.h:49
constexpr const value_t & operator[](size_t i) const
Definition rdtree.h:327
constexpr size_t next(size_t i, size_t n=0) const
Definition rdtree.h:209
constexpr void swap(size_t i0, size_t i1)
Swap two nodes.
Definition rdtree.h:392
constexpr void traverse(VisitorT &&visit, size_t i=root)
Traverse the tree using a specified order and visiting functor.
Definition rdtree.h:434
constexpr bool empty() const
Definition rdtree.h:180
constexpr size_t next_id() const
Definition rdtree.h:309
constexpr size_t capacity() const
Definition rdtree.h:174
constexpr size_t parent(size_t i) const
Definition rdtree.h:190
constexpr rdtree & operator=(rdtree &&rhs) noexcept
Move Assignment Operator.
Definition rdtree.h:149
constexpr void erase(size_t i)
Erase a node in the tree and all of it's children.
Definition rdtree.h:413
constexpr size_t emplace(size_t parent, size_t next, ArgsT &&...args)
Insertion, creates a node in the tree with parent parent
Definition rdtree.h:384
constexpr rdtree(ArgsT &&...args)
Root Constructor, constructs the root node of the tree.
Definition rdtree.h:103
constexpr size_t depth(size_t i) const
Definition rdtree.h:294
constexpr size_t num_children(size_t i) const
Definition rdtree.h:302
constexpr size_t left_most(size_t i) const
Definition rdtree.h:257
constexpr size_t insert(size_t parent, size_t next, value_t &&val)
Insertion, creates a node in the tree with parent parent
Definition rdtree.h:350
constexpr rdtree & operator=(const rdtree &rhs)
Copy Assignment Operator.
Definition rdtree.h:135
constexpr rdtree(rdtree &&tree) noexcept
Move Constructor, takes ownership over the contents of tree
Definition rdtree.h:119
constexpr rdtree(const rdtree &tree)
Copy Constructor, copies the contents of tree
Definition rdtree.h:112
constexpr value_t & operator[](size_t i)
Definition rdtree.h:320
constexpr size_t right_most(size_t i) const
Definition rdtree.h:274
constexpr size_t size() const
Definition rdtree.h:168
constexpr size_t insert(size_t parent, size_t next, const value_t &val)
Insertion, creates a node in the tree with parent parent
Definition rdtree.h:340
constexpr size_t child(size_t i, size_t n=0) const
Definition rdtree.h:198
constexpr size_t prev(size_t i, size_t n=0) const
Definition rdtree.h:233
a header containing constants and utilities related to traversal
::uint8_t uint8_t
Unsigned 8-bit integer.
Definition types.h:272
constexpr void swap(T &x, T &y) noexcept
Swaps x and y.
Definition utility.h:114
constexpr remove_reference_t< T > && move(T &&x) noexcept
produces an x-value type to indicate x may be "moved"
Definition utility.h:92