- "Finished" sequence.h, there's more to do, but the basic functionality is there
- bintree.h is implemented according to the needs of sequence.h at present
This commit is contained in:
@@ -371,7 +371,7 @@ class RDTreePrinter:
|
|||||||
index += '└'
|
index += '└'
|
||||||
|
|
||||||
index += '─'
|
index += '─'
|
||||||
index += '[{}, {}]'.format(node, i)
|
index += '[{}]'.format(node)
|
||||||
return index, value
|
return index, value
|
||||||
|
|
||||||
|
|
||||||
@@ -389,6 +389,66 @@ class RDTreePrinter:
|
|||||||
return self.Iterator(self.tree, 0, self.capacity)
|
return self.Iterator(self.tree, 0, self.capacity)
|
||||||
|
|
||||||
|
|
||||||
|
# BINTREE ==============================================================================================================
|
||||||
|
|
||||||
|
class BinTreePrinter:
|
||||||
|
"""Print a fennec::bintree"""
|
||||||
|
|
||||||
|
class Iterator:
|
||||||
|
def __init__(self, tree, node, capacity):
|
||||||
|
self.tree = tree
|
||||||
|
self.capacity = capacity
|
||||||
|
self.visit = deque()
|
||||||
|
|
||||||
|
self.visit.append((node, 0, 0))
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
if len(self.visit) == 0:
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
node = self.visit[0][0]
|
||||||
|
i = self.visit[0][1]
|
||||||
|
depth = self.visit[0][2]
|
||||||
|
self.visit.popleft()
|
||||||
|
|
||||||
|
value = self.tree[node]['value']
|
||||||
|
left = self.tree[node]['left']
|
||||||
|
right = self.tree[node]['right']
|
||||||
|
|
||||||
|
if right < self.capacity:
|
||||||
|
self.visit.appendleft((right, 1, depth + 1))
|
||||||
|
if left < self.capacity:
|
||||||
|
self.visit.appendleft((left, 0, depth + 1))
|
||||||
|
|
||||||
|
index = '⠀' * depth * 2 # Uses Braille Space, otherwise it would get eaten as whitespace by parsers
|
||||||
|
if i == 0:
|
||||||
|
index += '├'
|
||||||
|
else:
|
||||||
|
index += '└'
|
||||||
|
|
||||||
|
index += '─'
|
||||||
|
index += '[{}]'.format(node)
|
||||||
|
return index, value
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, val):
|
||||||
|
self.tree = val['_table']['_data']
|
||||||
|
self.size = val['_size']
|
||||||
|
self.root = val['_root']
|
||||||
|
self.capacity = val['_table']['_capacity']
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
if self.size == 0:
|
||||||
|
return "{ empty }"
|
||||||
|
return "{ size = " + str(self.size) + " }"
|
||||||
|
|
||||||
|
def children(self):
|
||||||
|
return self.Iterator(self.tree, self.root, self.capacity)
|
||||||
|
|
||||||
|
|
||||||
# Graph ================================================================================================================
|
# Graph ================================================================================================================
|
||||||
|
|
||||||
class GraphPrinter:
|
class GraphPrinter:
|
||||||
@@ -475,6 +535,8 @@ def register_printers():
|
|||||||
pp.add_printer('fennec::pair', '^fennec::pair<.*>$', PairPrinter)
|
pp.add_printer('fennec::pair', '^fennec::pair<.*>$', PairPrinter)
|
||||||
pp.add_printer('fennec::set', '^fennec::set<.*>$', SetPrinter)
|
pp.add_printer('fennec::set', '^fennec::set<.*>$', SetPrinter)
|
||||||
pp.add_printer('fennec::rdtree', '^fennec::rdtree<.*>$', RDTreePrinter)
|
pp.add_printer('fennec::rdtree', '^fennec::rdtree<.*>$', RDTreePrinter)
|
||||||
|
pp.add_printer('fennec::bintree', '^fennec::bintree<.*>$', BinTreePrinter)
|
||||||
|
pp.add_printer('fennec::sequence', '^fennec::sequence<.*>$', BinTreePrinter)
|
||||||
pp.add_printer('fennec::tuple', '^fennec::tuple<.*>$', TuplePrinter)
|
pp.add_printer('fennec::tuple', '^fennec::tuple<.*>$', TuplePrinter)
|
||||||
return pp
|
return pp
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,10 @@ protected:
|
|||||||
right = npos;
|
right = npos;
|
||||||
depth = npos;
|
depth = npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t& operator[](bool d) {
|
||||||
|
return d ? right : left;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using table_t = allocation<node, alloc_t>;
|
using table_t = allocation<node, alloc_t>;
|
||||||
@@ -144,6 +148,12 @@ public:
|
|||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns `true` when there are no elements in the tree, `false` otherwise.
|
||||||
|
constexpr bool empty() const {
|
||||||
|
return _size == 0;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \returns The capacity of the underlying allocation
|
/// \returns The capacity of the underlying allocation
|
||||||
constexpr size_t capacity() const {
|
constexpr size_t capacity() const {
|
||||||
@@ -206,6 +216,27 @@ public:
|
|||||||
return i >= _table.size() ? npos : _table[i].right;
|
return i >= _table.size() ? npos : _table[i].right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(1)\f$
|
||||||
|
/// \param i The node id
|
||||||
|
/// \param dir The direction to go `true` for right, `false` for left
|
||||||
|
/// \returns The child in the direction specified by `dir`
|
||||||
|
constexpr size_t child(size_t i, bool dir) const {
|
||||||
|
return dir ? right(i) : left(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \details \f$O(1)\f$
|
||||||
|
/// \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);
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief \f$O(1)\f$
|
/// \brief \f$O(1)\f$
|
||||||
/// \param i The id of the node
|
/// \param i The id of the node
|
||||||
@@ -415,6 +446,32 @@ public:
|
|||||||
_table[l].right = r;
|
_table[l].right = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Perform a Tree Rotation at `i` in the specified direction
|
||||||
|
/// \param i The root node for the rotation
|
||||||
|
/// \param dir The direction to rotate, `true` for right, `false` for left
|
||||||
|
constexpr size_t rotate(size_t sub, bool dir) {
|
||||||
|
if (sub >=_table.size()) {
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
size_t sub_parent = parent(sub);
|
||||||
|
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;
|
||||||
|
|
||||||
|
parent(new_root) = sub_parent;
|
||||||
|
parent(sub) = new_root;
|
||||||
|
if (sub_parent != npos) {
|
||||||
|
child(sub_parent, sub == right(sub_parent)) = new_root;
|
||||||
|
} else {
|
||||||
|
_root = new_root;
|
||||||
|
}
|
||||||
|
return new_root;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Clears the tree, destroying all elements
|
/// \brief Clears the tree, destroying all elements
|
||||||
constexpr void clear() {
|
constexpr void clear() {
|
||||||
@@ -640,6 +697,10 @@ public:
|
|||||||
_order(*tree, root);
|
_order(*tree, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t index() const {
|
||||||
|
return _n;
|
||||||
|
}
|
||||||
|
|
||||||
iterator& operator++() {
|
iterator& operator++() {
|
||||||
return _n = _order[*_tree, _n, traversal_control_continue], *this;
|
return _n = _order[*_tree, _n, traversal_control_continue], *this;
|
||||||
}
|
}
|
||||||
@@ -745,6 +806,10 @@ protected:
|
|||||||
return i >= _table.size() ? sink : _table[i].right;
|
return i >= _table.size() ? sink : _table[i].right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 p = parent(i);
|
||||||
size_t& l = left(p);
|
size_t& l = left(p);
|
||||||
|
|||||||
@@ -92,18 +92,25 @@ protected:
|
|||||||
|
|
||||||
using base_t::left;
|
using base_t::left;
|
||||||
using base_t::right;
|
using base_t::right;
|
||||||
|
using base_t::child;
|
||||||
|
using base_t::direction;
|
||||||
using base_t::parent;
|
using base_t::parent;
|
||||||
using base_t::grandparent;
|
using base_t::grandparent;
|
||||||
using base_t::sibling;
|
using base_t::sibling;
|
||||||
using base_t::parsib;
|
using base_t::parsib;
|
||||||
|
|
||||||
|
using base_t::left_most;
|
||||||
|
using base_t::right_most;
|
||||||
|
|
||||||
using base_t::insert_left;
|
using base_t::insert_left;
|
||||||
using base_t::insert_right;
|
using base_t::insert_right;
|
||||||
|
|
||||||
|
using base_t::rotate;
|
||||||
using base_t::rotate_left;
|
using base_t::rotate_left;
|
||||||
using base_t::rotate_right;
|
using base_t::rotate_right;
|
||||||
|
|
||||||
using base_t::_table;
|
using base_t::_table;
|
||||||
|
using base_t::_freed;
|
||||||
using base_t::_root;
|
using base_t::_root;
|
||||||
using base_t::_size;
|
using base_t::_size;
|
||||||
|
|
||||||
@@ -179,6 +186,10 @@ public:
|
|||||||
/// \returns The capacity of the underlying allocation
|
/// \returns The capacity of the underlying allocation
|
||||||
using base_t::capacity;
|
using base_t::capacity;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \returns `true` when there are no elements in the sequence, `false` otherwise.
|
||||||
|
using base_t::empty;
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
// Modifiers ===========================================================================================================
|
// Modifiers ===========================================================================================================
|
||||||
@@ -213,8 +224,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
constexpr void erase(const value_t& val) {
|
constexpr void erase(const value_t& val) {
|
||||||
size_t i = find(val)._n;
|
_erase_bst(val);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -289,11 +299,11 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool& _color(size_t i) {
|
constexpr bool& _color(size_t i) {
|
||||||
return i >= _table.capacity() ? color_sink : _table[i].value.second;
|
return i >= _table.capacity() ? color_sink = false : _table[i].value.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool _color(size_t i) const {
|
constexpr bool _color(size_t i) const {
|
||||||
return i >= _table.capacity() ? color_sink : _table[i].value.second;
|
return i >= _table.capacity() ? color_sink = false : _table[i].value.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename...ArgsT>
|
template<typename...ArgsT>
|
||||||
@@ -352,6 +362,92 @@ protected:
|
|||||||
}
|
}
|
||||||
_color(_root) = black;
|
_color(_root) = black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr void _shift(size_t u, size_t v) {
|
||||||
|
if (parent(u) == npos) {
|
||||||
|
_root = v;
|
||||||
|
} else {
|
||||||
|
child(parent(u), direction(u)) = v;
|
||||||
|
}
|
||||||
|
if (v != npos) {
|
||||||
|
parent(v) = parent(u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void _erase_bst(const value_t& val) {
|
||||||
|
size_t z = find(val).index();
|
||||||
|
size_t y = z;
|
||||||
|
size_t x = npos;
|
||||||
|
bool c = _color(y);
|
||||||
|
size_t p = npos;
|
||||||
|
|
||||||
|
if (left(z) == npos) {
|
||||||
|
x = right(z);
|
||||||
|
p = parent(z);
|
||||||
|
_shift(z, x);
|
||||||
|
} else if (right(z) == npos) {
|
||||||
|
x = left(z);
|
||||||
|
p = parent(z);
|
||||||
|
_shift(z, x);
|
||||||
|
} else {
|
||||||
|
y = left_most(right(z));
|
||||||
|
c = _color(y);
|
||||||
|
x = right(y);
|
||||||
|
p = (parent(y) == z) ? y : parent(y);
|
||||||
|
if (parent(y) != z) {
|
||||||
|
_shift(y, right(y));
|
||||||
|
right(y) = right(z);
|
||||||
|
parent(right(y)) = y;
|
||||||
|
}
|
||||||
|
_shift(z, y);
|
||||||
|
left(y) = left(z);
|
||||||
|
if (left(y))
|
||||||
|
parent(left(y)) = y;
|
||||||
|
_color(y) = _color(z);
|
||||||
|
}
|
||||||
|
|
||||||
|
fennec::destruct(&_table[z]);
|
||||||
|
--_size;
|
||||||
|
|
||||||
|
if (c == black) {
|
||||||
|
_fix_erase(x, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void _fix_erase(size_t x, size_t p) {
|
||||||
|
while (x != _root && _color(x) == black) {
|
||||||
|
bool dir = direction(x);
|
||||||
|
size_t w = child(p, not dir);
|
||||||
|
|
||||||
|
if (_color(w) == red) {
|
||||||
|
_color(w) = black;
|
||||||
|
_color(p) = red;
|
||||||
|
w = rotate(p, dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w == npos || (_color(left(w)) == black && _color(right(w)) == black)) {
|
||||||
|
_color(w) = red;
|
||||||
|
x = p;
|
||||||
|
p = parent(x);
|
||||||
|
} else {
|
||||||
|
if (_color(child(w, not dir)) == black) {
|
||||||
|
_color(child(w, dir)) = black;
|
||||||
|
_color(w) = red;
|
||||||
|
rotate(w, not dir);
|
||||||
|
w = child(p, not dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
_color(w) = _color(p);
|
||||||
|
_color(p) = black;
|
||||||
|
_color(child(w, not dir)) = black;
|
||||||
|
rotate(p, dir);
|
||||||
|
x = _root;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_color(x) = black;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,10 @@ inline void fennec_test_containers_sequence() {
|
|||||||
|
|
||||||
for (size_t v : ref) {
|
for (size_t v : ref) {
|
||||||
assertf(test.contains(v), "Failed Sequence Test!");
|
assertf(test.contains(v), "Failed Sequence Test!");
|
||||||
|
test.erase(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fennec_test_run(test.empty(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user