- Fixed some missing and erroneous testing logic for containers

- Lots of bug-fixing for containers
 - Performance optimization for containers
This commit is contained in:
2025-09-17 17:13:52 -04:00
parent 80925965d4
commit a35f2a699d
15 changed files with 886 additions and 262 deletions

View File

@@ -56,7 +56,6 @@ public:
using value_t = TypeT;
using alloc_t = allocator_traits<AllocT>::template rebind<node>;
static constexpr size_t npos = -1;
inline static size_t sink = npos;
friend class iterator;
friend class const_iterator;
@@ -189,7 +188,7 @@ public:
/// \param i The node id
/// \returns The parent of node `i`
constexpr size_t parent(size_t i) const {
return i >= _table.size() ? npos : _table[i].parent;
return i == npos ? npos : _table[i].parent;
}
///
@@ -205,7 +204,7 @@ public:
/// \param i The node id
/// \returns The left child of node `i`
constexpr size_t left(size_t i) const {
return i >= _table.size() ? npos : _table[i].left;
return i == npos ? npos : _table[i].left;
}
///
@@ -213,7 +212,7 @@ public:
/// \param i The node id
/// \returns The right child of node `i`
constexpr size_t right(size_t i) const {
return i >= _table.size() ? npos : _table[i].right;
return i == npos ? npos : _table[i].right;
}
///
@@ -230,11 +229,7 @@ public:
/// \param i The node id
/// \returns `true` if `i` is the right node of `parent(i)`, `false` otherwise
constexpr bool direction(size_t i) const {
size_t p = parent(i);
if (p >= _table.capacity()) {
return false;
}
return i == right(p);
return i == npos ? false : i == right(parent(i));
}
///
@@ -245,15 +240,7 @@ public:
size_t p = parent(i);
size_t l = left(p);
size_t r = right(p);
return i == l ? l : r;
}
///
/// \brief Short for "Parent Sibling," \f$O(1)\f$
/// \param i The id of the node
/// \returns The id of the parents' sibling of `i`
constexpr size_t parsib(size_t i) const {
return sibling(parent(i));
return i == l ? r : l;
}
///
@@ -305,22 +292,18 @@ public:
/// \details \f$O(1)\f$
/// \param i The node id
/// \returns `nullptr` if node `i` does not exist, otherwise, a pointer to the value of node `i`
constexpr value_t* operator[](size_t i) {
if (i >= _table.size()) {
return nullptr;
}
return _table[i] ? &*_table[i] : nullptr;
constexpr value_t& operator[](size_t i) {
assertd(i < _table.size(), "Index out of bounds.");
return _table[i].value;
}
///
/// \details Const Access, \f$O(1)\f$
/// \param i The node id
/// \returns `nullptr` if node `i` does not exist, otherwise, a pointer to the value of node `i`
constexpr const value_t* operator[](size_t i) const {
if (i >= _table.size()) {
return nullptr;
}
return _table[i] ? &*_table[i] : nullptr;
constexpr const value_t& operator[](size_t i) const {
assertd(i < _table.size(), "Index out of bounds.");
return _table[i].value;
}
/// @}
@@ -458,14 +441,16 @@ public:
size_t new_root = child(sub, not dir);
size_t new_child = child(new_root, dir);
child(sub, not dir) = new_child;
parent(new_child) = sub;
child(new_root, dir) = sub;
_child(sub, not dir) = new_child;
if (new_child != npos) {
_parent(new_child) = sub;
}
_child(new_root, dir) = sub;
parent(new_root) = sub_parent;
parent(sub) = new_root;
_parent(new_root) = sub_parent;
_parent(sub) = new_root;
if (sub_parent != npos) {
child(sub_parent, sub == right(sub_parent)) = new_root;
_child(sub_parent, sub == right(sub_parent)) = new_root;
} else {
_root = new_root;
}
@@ -516,13 +501,13 @@ public:
/// \param visit The visiting object
/// \param i The node to start at
template<typename OrderT, typename VisitorT>
constexpr void traverse(VisitorT&& visit, size_t i = root) {
constexpr void traverse(VisitorT&& visit, size_t i) {
OrderT order;
i = order(*this, i);
while (i != npos) {
uint8_t mode = traversal_control_continue;
if (_table[i].value) {
mode = visit(*_table[i].value, i);
mode = visit(_table[i].value, i);
}
if (mode == traversal_control_break) {
break;
@@ -581,7 +566,7 @@ public:
return npos;
}
size_t nxt = tree.sibling(node);
size_t nxt = tree.right(tree.parent(node));
size_t chd = tree.left(node);
nxt = node == nxt ? npos : nxt;
@@ -618,19 +603,16 @@ public:
return npos;
}
size_t prnt = tree.parent(node);
size_t next = tree.sibling(node);
next = node == next ? npos : next;
size_t parent = tree.parent(node);
size_t pright = tree.right(parent);
size_t next = tree.left_most(tree.right(node));
if (node != head) {
if (tree.left(prnt) == node) {
visit.push_back(prnt);
if (next != npos) {
visit.push_back(tree.left_most(next));
}
} else if (next != npos) {
visit.push_front(tree.left_most(next));
}
if (node != pright && parent != npos) {
visit.push_front(parent);
}
if (next != npos) {
visit.push_front(next);
}
if (not visit.empty()) {
@@ -648,9 +630,23 @@ public:
list<size_t> visit;
size_t head;
constexpr size_t successor(const bintree& tree, size_t n) {
size_t s = tree.left_most(n);
while (n == s) {
size_t r = tree.right(n);
if (r != npos) {
n = r;
s = tree.left_most(n);
} else {
break;
}
}
return s == npos ? n : s;
}
constexpr size_t operator()(const bintree& tree, size_t start) {
head = start;
return tree.left_most(start);
return this->successor(tree, start);
}
constexpr size_t operator[](const bintree& tree, size_t node, uint8_t) {
@@ -658,16 +654,15 @@ public:
return npos;
}
size_t prnt = tree.parent(node);
size_t next = tree.sibling(node);
next = node == next ? npos : next;
size_t parent = tree.parent(node);
size_t pright = tree.right(parent);
if (node != head) {
if (next != npos) {
visit.push_front(tree.left_most(next));
} else {
visit.push_front(prnt);
if (node == pright) {
if (parent != npos) {
visit.push_front(parent);
}
} else if (pright != npos) {
visit.push_front(this->successor(tree, pright));
}
if (not visit.empty()) {
@@ -677,6 +672,7 @@ public:
node = npos;
}
return node;
}
};
@@ -690,6 +686,12 @@ public:
size_t _n;
public:
constexpr iterator(bintree* tree, size_t root)
: _tree(tree)
, _order()
, _n(_order(*tree, root)) {
}
constexpr iterator(bintree* tree, size_t root, size_t node)
: _tree(tree)
, _order()
@@ -706,19 +708,19 @@ public:
}
value_t& operator*() {
return _tree[_n];
return (*_tree)[_n];
}
value_t* operator->() {
return &_tree[_n];
return &(*_tree)[_n];
}
const value_t& operator*() const {
return _tree[_n];
return (*_tree)[_n];
}
const value_t* operator->() const {
return &_tree[_n];
return &(*_tree)[_n];
}
constexpr bool operator==(const iterator& it) {
@@ -754,7 +756,8 @@ protected:
template<typename...ArgsT>
constexpr size_t _insert_left(size_t p, ArgsT&&...args) {
size_t i = p == npos ? _root : left(p);
size_t i = p >= capacity() ? npos : p;
i = i == npos ? _root : _left(i);
if (i != npos) {
_table[i].value = value_t(fennec::forward<ArgsT>(args)...);
} else {
@@ -764,6 +767,9 @@ protected:
d = depth(p) + 1;
_table[p].left = i;
}
if (_root == npos) {
_root = i;
}
fennec::construct(&_table[i], p, npos, npos, d, fennec::forward<ArgsT>(args)...);
}
return i;
@@ -771,7 +777,7 @@ protected:
template<typename...ArgsT>
constexpr size_t _insert_right(size_t p, ArgsT&&...args) {
size_t i = p == npos ? _root : right(p);
size_t i = p == npos ? _root : _right(p);
if (i != npos) {
_table[i].value = value_t(fennec::forward<ArgsT>(args)...);
if (p == npos || _root == npos) {
@@ -784,42 +790,41 @@ protected:
d = depth(p) + 1;
_table[p].right = i;
}
if (_root == npos) {
_root = i;
}
fennec::construct(&_table[i], p, npos, npos, d, fennec::forward<ArgsT>(args)...);
}
return i;
}
constexpr size_t& parent(size_t i) {
return i >= _table.size() ? sink : _table[i].parent;
constexpr size_t& _parent(size_t i) {
return _table[i].parent;
}
constexpr size_t& grandparent(size_t i) {
return parent(parent(i));
constexpr size_t& _grandparent(size_t i) {
return _parent(parent(i));
}
constexpr size_t& left(size_t i) {
return i >= _table.size() ? sink : _table[i].left;
constexpr size_t& _left(size_t i) {
return _table[i].left;
}
constexpr size_t& right(size_t i) {
return i >= _table.size() ? sink : _table[i].right;
constexpr size_t& _right(size_t i) {
return _table[i].right;
}
constexpr size_t& child(size_t i, bool dir) {
return dir ? right(i) : left(i);
constexpr size_t& _child(size_t i, bool dir) {
return dir ? _right(i) : _left(i);
}
constexpr size_t& sibling(size_t i) {
constexpr size_t& _sibling(size_t i) {
size_t p = parent(i);
size_t& l = left(p);
size_t& r = right(p);
size_t& l = _left(p);
size_t& r = _right(p);
return i == l ? l : r;
}
constexpr size_t& parsib(size_t i) {
return sibling(parent(i));
}
};
}