- More optimization on fennec::sequence. There are areas that could be improved, but the running time is now within margin. It can be revisited later if this data-structure becomes the focus of a performance critical task.
This commit is contained in:
@@ -63,31 +63,28 @@ public:
|
||||
protected:
|
||||
struct node {
|
||||
value_t value;
|
||||
size_t parent, left, right;
|
||||
size_t depth;
|
||||
size_t parent;
|
||||
size_t child[2];
|
||||
|
||||
constexpr node()
|
||||
: value(nullopt)
|
||||
, parent(npos), left(npos), right(npos)
|
||||
, depth(0) {
|
||||
: value()
|
||||
, parent(npos), child{ npos, npos } {
|
||||
}
|
||||
|
||||
template<typename...ArgsT>
|
||||
constexpr node(size_t p, size_t l, size_t r, size_t d, ArgsT&&...args)
|
||||
constexpr node(size_t p, size_t l, size_t r, ArgsT&&...args)
|
||||
: value(fennec::forward<ArgsT>(args)...)
|
||||
, parent(p), left(l), right(r)
|
||||
, depth(d) {
|
||||
, parent(p), child{ l, r } {
|
||||
}
|
||||
|
||||
constexpr ~node() {
|
||||
parent = npos;
|
||||
left = npos;
|
||||
right = npos;
|
||||
depth = npos;
|
||||
parent = npos;
|
||||
child[0] = npos;
|
||||
child[1] = npos;
|
||||
}
|
||||
|
||||
size_t& operator[](bool d) {
|
||||
return d ? right : left;
|
||||
return child[d];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -204,7 +201,7 @@ public:
|
||||
/// \param i The node id
|
||||
/// \returns The left child of node `i`
|
||||
constexpr size_t left(size_t i) const {
|
||||
return i == npos ? npos : _table[i].left;
|
||||
return i == npos ? npos : _table[i].child[false];
|
||||
}
|
||||
|
||||
///
|
||||
@@ -212,7 +209,7 @@ public:
|
||||
/// \param i The node id
|
||||
/// \returns The right child of node `i`
|
||||
constexpr size_t right(size_t i) const {
|
||||
return i == npos ? npos : _table[i].right;
|
||||
return i == npos ? npos : _table[i].child[true];
|
||||
}
|
||||
|
||||
///
|
||||
@@ -221,7 +218,7 @@ public:
|
||||
/// \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);
|
||||
return i == npos ? npos : _table[i].child[dir];
|
||||
}
|
||||
|
||||
///
|
||||
@@ -237,10 +234,15 @@ public:
|
||||
/// \param i The id of the node
|
||||
/// \returns The id of the sibling of `i`
|
||||
constexpr size_t sibling(size_t i) const {
|
||||
size_t p = parent(i);
|
||||
size_t l = left(p);
|
||||
size_t r = right(p);
|
||||
return i == l ? r : l;
|
||||
if (i == npos) {
|
||||
return npos;
|
||||
}
|
||||
if (i == _root) {
|
||||
return npos;
|
||||
}
|
||||
size_t p = _parent(i);
|
||||
bool d = i == _right(p);
|
||||
return _child(p, d);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -248,7 +250,12 @@ public:
|
||||
/// \param i The node id
|
||||
/// \returns The depth of node `i`
|
||||
constexpr size_t depth(size_t i) const {
|
||||
return i >= _table.size() ? npos : _table[i].depth;
|
||||
size_t d = 0;
|
||||
while (i != npos) {
|
||||
i = _parent(i);
|
||||
++d;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
///
|
||||
@@ -259,8 +266,8 @@ public:
|
||||
if (i >= _table.size()) {
|
||||
return npos;
|
||||
}
|
||||
while (_table[i].left != npos) {
|
||||
i = _table[i].left;
|
||||
while (_table[i].child[false] != npos) {
|
||||
i = _table[i].child[false];
|
||||
}
|
||||
return i;
|
||||
}
|
||||
@@ -273,8 +280,8 @@ public:
|
||||
if (i >= _table.size()) {
|
||||
return npos;
|
||||
}
|
||||
while (_table[i].right != npos) {
|
||||
i = _table[i].right;
|
||||
while (_table[i].right[false] != npos) {
|
||||
i = _table[i].right[false];
|
||||
}
|
||||
return i;
|
||||
}
|
||||
@@ -375,71 +382,19 @@ public:
|
||||
return this->_insert_right(p, fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Perform a Left Tree Rotation at `i`
|
||||
/// \param i The root node for the rotation
|
||||
constexpr void rotate_left(size_t i) {
|
||||
if (i >=_table.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t l = i;
|
||||
size_t p = parent(l);
|
||||
size_t r = right(l);
|
||||
|
||||
if (p == npos) {
|
||||
_root = r;
|
||||
} else if (l == _table[p].left) {
|
||||
_table[p].left = r;
|
||||
} else {
|
||||
_table[p].right = r;
|
||||
}
|
||||
|
||||
_table[l].parent = r;
|
||||
_table[l].right = _table[r].left;
|
||||
|
||||
_table[r].parent = p;
|
||||
_table[r].left = l;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Perform a Right Tree Rotation at `i`
|
||||
/// \param i The root node for the rotation
|
||||
constexpr void rotate_right(size_t i) {
|
||||
if (i >=_table.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t r = i;
|
||||
size_t p = parent(r);
|
||||
size_t l = left(r);
|
||||
|
||||
if (p == npos) {
|
||||
_root = l;
|
||||
} else if (r == _table[p].left) {
|
||||
_table[p].left = l;
|
||||
} else {
|
||||
_table[p].right = l;
|
||||
}
|
||||
|
||||
_table[r].parent = l;
|
||||
_table[r].left = _table[l].right;
|
||||
|
||||
_table[l].parent = p;
|
||||
_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()) {
|
||||
if (sub == npos) {
|
||||
return npos;
|
||||
}
|
||||
size_t sub_parent = parent(sub);
|
||||
size_t new_root = child(sub, not dir);
|
||||
size_t new_child = child(new_root, dir);
|
||||
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;
|
||||
if (new_child != npos) {
|
||||
@@ -457,6 +412,40 @@ public:
|
||||
return new_root;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Move Insertion, bool d, constructs a new node as the child of `p`
|
||||
/// \details If the child of `p` already exists, the move assignment operator is used instead
|
||||
/// \param p The parent node
|
||||
/// \param d The direction to insert
|
||||
/// \param val The object to move into the new node
|
||||
/// \returns The id of the new node
|
||||
constexpr size_t insert(size_t p, bool d, value_t&& val) {
|
||||
return this->_insert(p, d, fennec::forward<value_t>(val));
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Copy Insertion, bool d, constructs a new node as the child of `p`
|
||||
/// \details If the child of `p` already exists, the copy assignment operator is used instead
|
||||
/// \param p The parent node
|
||||
/// \param d The direction to insert
|
||||
/// \param val The object to copy to the new node
|
||||
/// \returns The id of the new node
|
||||
constexpr size_t insert(size_t p, bool d, const value_t& val) {
|
||||
return this->_insert(p, d, val);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Emplace Insertion, constructs a new node as the child of `p`
|
||||
/// \details If the child of `p` already exists, the move assignment operator is used instead
|
||||
/// \param p The parent node
|
||||
/// \param d The direction to insert
|
||||
/// \param args The arguments to construct the new node with
|
||||
/// \returns The id of the new node
|
||||
template<typename...ArgsT>
|
||||
constexpr size_t emplace(size_t p, bool d, ArgsT&&...args) {
|
||||
return this->_insert(p, d, fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Clears the tree, destroying all elements
|
||||
constexpr void clear() {
|
||||
@@ -470,11 +459,11 @@ public:
|
||||
size_t i = queue.front();
|
||||
queue.pop_front();
|
||||
|
||||
if (_table[i].left != npos) {
|
||||
queue.push_front(_table[i].left);
|
||||
if (_right(i) != npos) {
|
||||
queue.push_front(_right(i));
|
||||
}
|
||||
if (_table[i].right != npos) {
|
||||
queue.push_front(_table[i].right);
|
||||
if (_left(i) != npos) {
|
||||
queue.push_front(_left(i));
|
||||
}
|
||||
|
||||
fennec::destruct(&_table[i]);
|
||||
@@ -761,16 +750,14 @@ protected:
|
||||
if (i != npos) {
|
||||
_table[i].value = value_t(fennec::forward<ArgsT>(args)...);
|
||||
} else {
|
||||
size_t d = 1;
|
||||
i = _next_free();
|
||||
if (p != npos) {
|
||||
d = depth(p) + 1;
|
||||
_table[p].left = i;
|
||||
_left(p) = i;
|
||||
}
|
||||
if (_root == npos) {
|
||||
_root = i;
|
||||
}
|
||||
fennec::construct(&_table[i], p, npos, npos, d, fennec::forward<ArgsT>(args)...);
|
||||
fennec::construct(&_table[i], p, npos, npos, fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
@@ -780,24 +767,38 @@ protected:
|
||||
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) {
|
||||
_root = i;
|
||||
}
|
||||
} else {
|
||||
size_t d = 1;
|
||||
i = _next_free();
|
||||
if (p != npos) {
|
||||
d = depth(p) + 1;
|
||||
_table[p].right = i;
|
||||
_right(p) = i;
|
||||
}
|
||||
if (_root == npos) {
|
||||
_root = i;
|
||||
}
|
||||
fennec::construct(&_table[i], p, npos, npos, d, fennec::forward<ArgsT>(args)...);
|
||||
fennec::construct(&_table[i], p, npos, npos, fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
template<typename...ArgsT>
|
||||
constexpr size_t _insert(size_t p, bool d, ArgsT&&...args) {
|
||||
size_t i = p == npos ? _root : _child(p, d);
|
||||
if (i != npos) {
|
||||
_table[i].value = value_t(fennec::forward<ArgsT>(args)...);
|
||||
return i;
|
||||
}
|
||||
|
||||
i = _next_free();
|
||||
if (p != npos) {
|
||||
_child(p, d) = i;
|
||||
}
|
||||
if (_root == npos) {
|
||||
_root = i;
|
||||
}
|
||||
fennec::construct(&_table[i], p, npos, npos, fennec::forward<ArgsT>(args)...);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
constexpr size_t& _parent(size_t i) {
|
||||
return _table[i].parent;
|
||||
@@ -808,19 +809,19 @@ protected:
|
||||
}
|
||||
|
||||
constexpr size_t& _left(size_t i) {
|
||||
return _table[i].left;
|
||||
return _table[i].child[false];
|
||||
}
|
||||
|
||||
constexpr size_t& _right(size_t i) {
|
||||
return _table[i].right;
|
||||
return _table[i].child[true];
|
||||
}
|
||||
|
||||
constexpr size_t& _child(size_t i, bool dir) {
|
||||
return dir ? _right(i) : _left(i);
|
||||
return _table[i].child[dir];
|
||||
}
|
||||
|
||||
constexpr size_t& _sibling(size_t i) {
|
||||
size_t p = parent(i);
|
||||
size_t p = _parent(i);
|
||||
size_t& l = _left(p);
|
||||
size_t& r = _right(p);
|
||||
return i == l ? l : r;
|
||||
|
||||
Reference in New Issue
Block a user