31#ifndef FENNEC_CONTAINERS_BINTREE_H
32#define FENNEC_CONTAINERS_BINTREE_H
47template<
typename TypeT,
class AllocT = allocator<TypeT>>
55 using value_t = TypeT;
57 static constexpr size_t npos = -1;
59 friend class iterator;
60 friend class const_iterator;
70 , parent(npos), child{ npos, npos } {
73 template<
typename...ArgsT>
74 constexpr node(
size_t p,
size_t l,
size_t r, ArgsT&&...args)
75 : value(fennec::forward<ArgsT>(args)...)
76 , parent(p), child{ l, r } {
85 size_t& operator[](
bool d) {
112 : _table(fennec::move(tree._table))
113 , _freed(fennec::move(tree._freed))
115 , _size(tree._size) {
122 : _table(tree._table)
123 , _freed(tree._freed)
125 , _size(tree._size) {
142 constexpr size_t size()
const {
162 if (not _freed.
empty()) {
170 constexpr size_t root()
const {
186 constexpr size_t parent(
size_t i)
const {
187 return i == npos ? npos : _table[i].parent;
202 constexpr size_t left(
size_t i)
const {
203 return i == npos ? npos : _table[i].child[
false];
210 constexpr size_t right(
size_t i)
const {
211 return i == npos ? npos : _table[i].child[
true];
219 constexpr size_t child(
size_t i,
bool dir)
const {
220 return i == npos ? npos : _table[i].child[dir];
228 return i == npos ? false : i ==
right(_parent(i));
242 size_t p = _parent(i);
243 bool d = i == _right(p);
244 return _child(p, !d);
251 constexpr size_t depth(
size_t i)
const {
265 if (i >= _table.
size()) {
268 while (_table[i].
child[
false] != npos) {
269 i = _table[i].child[
false];
279 if (i >= _table.
size()) {
282 while (_table[i].
right[
false] != npos) {
283 i = _table[i].right[
false];
302 assertd(i < _table.
size(),
"Index out of bounds.");
303 return _table[i].value;
311 assertd(i < _table.
size(),
"Index out of bounds.");
312 return _table[i].value;
329 return this->_insert_left(p, fennec::forward<value_t>(val));
339 return this->_insert_left(p, val);
348 template<
typename...ArgsT>
350 return this->_insert_left(p, fennec::forward<ArgsT>(args)...);
360 return this->_insert_right(p, fennec::forward<value_t>(val));
370 return this->_insert_right(p, val);
379 template<
typename...ArgsT>
381 return this->_insert_right(p, fennec::forward<ArgsT>(args)...);
390 constexpr size_t rotate(
size_t sub,
bool dir) {
394 size_t sub_parent = _parent(sub);
395 size_t new_root = _child(sub, not dir);
396 size_t new_child = _child(new_root, dir);
398 _child(sub, not dir) = new_child;
399 if (new_child != npos) {
400 _parent(new_child) = sub;
402 _child(new_root, dir) = sub;
404 _parent(new_root) = sub_parent;
405 _parent(sub) = new_root;
406 if (sub_parent != npos) {
407 _child(sub_parent, sub == _right(sub_parent)) = new_root;
421 constexpr size_t insert(
size_t p,
bool d, value_t&& val) {
422 return this->_insert(p, d, fennec::forward<value_t>(val));
432 constexpr size_t insert(
size_t p,
bool d,
const value_t& val) {
433 return this->_insert(p, d, val);
443 template<
typename...ArgsT>
444 constexpr size_t emplace(
size_t p,
bool d, ArgsT&&...args) {
445 return this->_insert(p, d, fennec::forward<ArgsT>(args)...);
457 while (not queue.
empty()) {
458 size_t i = queue.
front();
461 if (_right(i) != npos) {
464 if (_left(i) != npos) {
468 fennec::destruct(&_table[i]);
491 template<
typename OrderT,
typename VisitorT>
492 constexpr void traverse(VisitorT&& visit,
size_t i) {
496 uint8_t mode = traversal_control_continue;
497 if (_table[i].value) {
498 mode = visit(_table[i].value, i);
500 if (mode == traversal_control_break) {
503 i = order[*
this, i, mode];
507 struct breadth_first {
511 size_t operator()(
const bintree&,
size_t start) {
515 size_t operator[](
const bintree& tree,
size_t node, uint8_t mode) {
520 size_t lft = tree.left(tree.parent(node));
521 size_t nxt = lft == node ? tree.right(tree.parent(node)) : npos;
522 size_t chd = tree.left(node);
524 if (nxt != npos && node != head) {
528 if (chd != npos && mode != traversal_control_jump_over) {
532 if (not visit.
empty()) {
533 node = visit.
front();
547 constexpr size_t operator()(
const bintree&,
size_t start) {
552 constexpr size_t operator[](
const bintree& tree,
size_t node, uint8_t mode) {
557 size_t nxt = tree.right(tree.parent(node));
558 size_t chd = tree.left(node);
559 nxt = node == nxt ? npos : nxt;
561 if (nxt != npos && node != head) {
565 if (chd != npos && mode != traversal_control_jump_over) {
566 visit.push_front(chd);
569 if (not visit.empty()) {
570 node = visit.front();
584 constexpr size_t operator()(
const bintree& tree,
size_t start) {
586 return tree.left_most(start);
589 constexpr size_t operator[](
const bintree& tree,
size_t node, uint8_t) {
594 size_t parent = tree.parent(node);
595 size_t pright = tree.right(
parent);
596 size_t next = tree.left_most(tree.right(node));
598 if (node != pright &&
parent != npos) {
603 visit.push_front(next);
606 if (not visit.empty()) {
607 node = visit.front();
621 constexpr size_t successor(
const bintree& tree,
size_t n) {
622 size_t s = tree.left_most(n);
624 size_t r = tree.right(n);
627 s = tree.left_most(n);
632 return s == npos ? n : s;
635 constexpr size_t operator()(
const bintree& tree,
size_t start) {
637 return this->successor(tree, start);
640 constexpr size_t operator[](
const bintree& tree,
size_t node, uint8_t) {
645 size_t parent = tree.parent(node);
646 size_t pright = tree.right(
parent);
648 if (node == pright) {
652 }
else if (pright != npos) {
653 visit.push_front(this->successor(tree, pright));
656 if (not visit.empty()) {
657 node = visit.front();
680 , _n(_order(*tree,
root)) {
683 constexpr iterator(
bintree* tree,
size_t root,
size_t node)
690 size_t index()
const {
694 iterator& operator++() {
695 return _n = _order[*_tree, _n, traversal_control_continue], *
this;
698 value_t& operator*() {
702 value_t* operator->() {
703 return &(*_tree)[_n];
706 const value_t& operator*()
const {
710 const value_t* operator->()
const {
711 return &(*_tree)[_n];
714 constexpr bool operator==(
const iterator& it) {
715 return _tree == it._tree and _n == it._n;
718 constexpr bool operator!=(
const iterator& it) {
719 return _tree != it._tree or _n != it._n;
732 constexpr size_t _next_free() {
734 if (not _freed.empty()) {
738 if (i >= _table.capacity()) {
739 _table.creallocate(2 * fennec::max(_table.capacity(),
size_t(4)));
745 template<
typename...ArgsT>
746 constexpr size_t _insert_left(
size_t p, ArgsT&&...args) {
747 size_t i = p >=
capacity() ? npos : p;
748 i = i == npos ? _root : _left(i);
750 _table[i].value = value_t(fennec::forward<ArgsT>(args)...);
759 fennec::construct(&_table[i], p, npos, npos, fennec::forward<ArgsT>(args)...);
764 template<
typename...ArgsT>
765 constexpr size_t _insert_right(
size_t p, ArgsT&&...args) {
766 size_t i = p == npos ? _root : _right(p);
768 _table[i].value = value_t(fennec::forward<ArgsT>(args)...);
777 fennec::construct(&_table[i], p, npos, npos, fennec::forward<ArgsT>(args)...);
782 template<
typename...ArgsT>
783 constexpr size_t _insert(
size_t p,
bool d, ArgsT&&...args) {
784 size_t i = p == npos ? _root : _child(p, d);
786 _table[i].value = value_t(fennec::forward<ArgsT>(args)...);
797 fennec::construct(&_table[i], p, npos, npos, fennec::forward<ArgsT>(args)...);
802 constexpr size_t& _parent(
size_t i) {
803 return _table[i].parent;
806 constexpr size_t& _grandparent(
size_t i) {
807 return _parent(_parent(i));
810 constexpr size_t& _left(
size_t i) {
811 return _table[i].child[
false];
814 constexpr size_t& _right(
size_t i) {
815 return _table[i].child[
true];
818 constexpr size_t& _child(
size_t i,
bool dir) {
819 return _table[i].child[dir];
822 constexpr size_t& _sibling(
size_t i) {
823 size_t p = _parent(i);
824 bool d = i == _right(p);
825 return _child(p, !d);
This header contains structures and classes related to allocating blocks of memory.
A header containing the definition for a dynamically allocated array.
A header containing the definition for a linked list of values.
A header containing the definition for a container with an optionally present variable.
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 size_t size() const
Getter for the byte size of the allocation.
Definition allocator.h:610
Helper structure for obtaining traits of an allocator class.
Definition allocator.h:61
Structure defining a binary tree.
Definition bintree.h:48
constexpr size_t parent(size_t i) const
Definition bintree.h:186
constexpr size_t left(size_t i) const
Definition bintree.h:202
constexpr size_t insert_left(size_t p, const value_t &val)
Copy Left Insertion, constructs a new node as the left child of p
Definition bintree.h:338
constexpr bintree(const bintree &tree)
Copy Constructor, copies a tree.
Definition bintree.h:121
constexpr const value_t & operator[](size_t i) const
Definition bintree.h:310
constexpr size_t sibling(size_t i) const
Definition bintree.h:235
constexpr bintree(bintree &&tree) noexcept
Move Constructor, takes ownership of a tree.
Definition bintree.h:111
constexpr size_t size() const
Definition bintree.h:142
constexpr size_t capacity() const
Definition bintree.h:154
constexpr value_t & operator[](size_t i)
Definition bintree.h:301
constexpr size_t left_most(size_t i) const
Definition bintree.h:264
constexpr size_t insert_right(size_t p, value_t &&val)
Move Right Insertion, constructs a new node as the right child of p
Definition bintree.h:359
constexpr void clear()
Clears the tree, destroying all elements.
Definition bintree.h:450
constexpr void traverse(VisitorT &&visit, size_t i)
Traverse the tree using a specified order and visiting functor.
Definition bintree.h:492
constexpr size_t rotate(size_t sub, bool dir)
Perform a Tree Rotation at i in the specified direction.
Definition bintree.h:390
constexpr size_t right(size_t i) const
Definition bintree.h:210
constexpr size_t right_most(size_t i) const
Definition bintree.h:278
constexpr size_t root() const
Definition bintree.h:170
constexpr size_t grandparent(size_t i) const
Definition bintree.h:194
constexpr bool direction(size_t i) const
Definition bintree.h:227
constexpr size_t emplace_left(size_t p, ArgsT &&...args)
Emplace Left Insertion, constructs a new node as the left child of p
Definition bintree.h:349
constexpr size_t emplace(size_t p, bool d, ArgsT &&...args)
Emplace Insertion, constructs a new node as the child of p
Definition bintree.h:444
constexpr size_t insert(size_t p, bool d, value_t &&val)
Move Insertion, bool d, constructs a new node as the child of p
Definition bintree.h:421
constexpr ~bintree()
Destructor, clears the tree.
Definition bintree.h:130
constexpr bool empty() const
Definition bintree.h:148
constexpr size_t next_id() const
Definition bintree.h:160
constexpr size_t insert_left(size_t p, value_t &&val)
Move Left Insertion, constructs a new node as the left child of p
Definition bintree.h:328
constexpr bintree()
Default Constructor, initializes an empty tree.
Definition bintree.h:101
constexpr size_t child(size_t i, bool dir) const
Definition bintree.h:219
constexpr size_t insert(size_t p, bool d, const value_t &val)
Copy Insertion, bool d, constructs a new node as the child of p
Definition bintree.h:432
constexpr size_t emplace_right(size_t p, ArgsT &&...args)
Emplace Right Insertion, constructs a new node as the right child of p
Definition bintree.h:380
constexpr size_t insert_right(size_t p, const value_t &val)
Copy Right Insertion, constructs a new node as the right child of p
Definition bintree.h:369
constexpr size_t depth(size_t i) const
Definition bintree.h:251
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
a header containing constants and utilities related to traversal
::uint8_t uint8_t
Unsigned 8-bit integer.
Definition types.h:272