mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-30 03:15:38 -05:00
347 lines
No EOL
12 KiB
C++
347 lines
No EOL
12 KiB
C++
#pragma once
|
|
|
|
namespace geode::stl {
|
|
struct _rb_tree_base {
|
|
bool m_isblack;
|
|
_rb_tree_base* m_parent;
|
|
_rb_tree_base* m_left;
|
|
_rb_tree_base* m_right;
|
|
};
|
|
|
|
template <typename T>
|
|
struct _rb_tree_node : public _rb_tree_base {
|
|
T m_value;
|
|
};
|
|
|
|
inline void _rb_tree_rotate_left(_rb_tree_base* const x, _rb_tree_base*& root);
|
|
inline void _rb_tree_rotate_right(_rb_tree_base* const x, _rb_tree_base*& root);
|
|
inline void _rb_insert_rebalance(
|
|
bool const insert_left, _rb_tree_base* x, _rb_tree_base* p, _rb_tree_base& header
|
|
);
|
|
inline _rb_tree_base* _rb_increment(_rb_tree_base* __x) noexcept;
|
|
inline _rb_tree_base* _rb_decrement(_rb_tree_base* __x) noexcept;
|
|
inline _rb_tree_base* _rb_rebalance_for_erase(_rb_tree_base* const __z, _rb_tree_base& __header) noexcept;
|
|
|
|
template <typename T>
|
|
struct _rb_tree_iterator {
|
|
typedef T value_type;
|
|
typedef T& reference;
|
|
typedef T* pointer;
|
|
|
|
typedef _rb_tree_iterator<T> _Self;
|
|
typedef _rb_tree_base* _Base_ptr;
|
|
typedef _rb_tree_node<T>* _Link_type;
|
|
|
|
_rb_tree_iterator() : m_node() {}
|
|
|
|
explicit _rb_tree_iterator(_Base_ptr __x) noexcept : m_node(__x) {}
|
|
|
|
reference operator*() const noexcept {
|
|
return static_cast<_Link_type>(m_node)->m_value;
|
|
}
|
|
|
|
pointer operator->() const noexcept {
|
|
return &static_cast<_Link_type>(m_node)->m_value;
|
|
}
|
|
|
|
_Self& operator++() noexcept {
|
|
m_node = _rb_increment(m_node);
|
|
return *this;
|
|
}
|
|
|
|
_Self operator++(int) noexcept {
|
|
_Self __tmp = *this;
|
|
m_node = _rb_increment(m_node);
|
|
return __tmp;
|
|
}
|
|
|
|
_Self& operator--() noexcept {
|
|
m_node = _rb_decrement(m_node);
|
|
return *this;
|
|
}
|
|
|
|
_Self operator--(int) noexcept {
|
|
_Self __tmp = *this;
|
|
m_node = _rb_decrement(m_node);
|
|
return __tmp;
|
|
}
|
|
|
|
bool operator==(_Self const& __x) const noexcept {
|
|
return m_node == __x.m_node;
|
|
}
|
|
|
|
bool operator!=(_Self const& __x) const noexcept {
|
|
return m_node != __x.m_node;
|
|
}
|
|
|
|
_Base_ptr m_node;
|
|
};
|
|
|
|
inline void _rb_tree_rotate_left(_rb_tree_base* const x, _rb_tree_base*& root) {
|
|
_rb_tree_base* const y = x->m_right;
|
|
|
|
x->m_right = y->m_left;
|
|
if (y->m_left != 0) y->m_left->m_parent = x;
|
|
y->m_parent = x->m_parent;
|
|
|
|
if (x == root) root = y;
|
|
else if (x == x->m_parent->m_left) x->m_parent->m_left = y;
|
|
else x->m_parent->m_right = y;
|
|
y->m_left = x;
|
|
x->m_parent = y;
|
|
}
|
|
|
|
inline void _rb_tree_rotate_right(_rb_tree_base* const x, _rb_tree_base*& root) {
|
|
_rb_tree_base* const y = x->m_left;
|
|
|
|
x->m_left = y->m_right;
|
|
if (y->m_right != 0) y->m_right->m_parent = x;
|
|
y->m_parent = x->m_parent;
|
|
|
|
if (x == root) root = y;
|
|
else if (x == x->m_parent->m_right) x->m_parent->m_right = y;
|
|
else x->m_parent->m_left = y;
|
|
y->m_right = x;
|
|
x->m_parent = y;
|
|
}
|
|
|
|
inline void _rb_insert_rebalance(
|
|
bool const insert_left, _rb_tree_base* x, _rb_tree_base* p, _rb_tree_base& header
|
|
) {
|
|
_rb_tree_base*& root = header.m_parent;
|
|
|
|
x->m_parent = p;
|
|
x->m_left = 0;
|
|
x->m_right = 0;
|
|
x->m_isblack = false;
|
|
|
|
if (insert_left) {
|
|
p->m_left = x;
|
|
|
|
if (p == &header) {
|
|
header.m_parent = x;
|
|
header.m_right = x;
|
|
}
|
|
else if (p == header.m_left) {
|
|
header.m_left = x;
|
|
}
|
|
}
|
|
else {
|
|
p->m_right = x;
|
|
|
|
if (p == header.m_right) {
|
|
header.m_right = x;
|
|
}
|
|
}
|
|
|
|
while (x != root && x->m_parent->m_isblack == false) {
|
|
_rb_tree_base* const xpp = x->m_parent->m_parent;
|
|
|
|
if (x->m_parent == xpp->m_left) {
|
|
_rb_tree_base* const y = xpp->m_right;
|
|
if (y && y->m_isblack == false) {
|
|
x->m_parent->m_isblack = true;
|
|
y->m_isblack = true;
|
|
xpp->m_isblack = false;
|
|
x = xpp;
|
|
}
|
|
else {
|
|
if (x == x->m_parent->m_right) {
|
|
x = x->m_parent;
|
|
_rb_tree_rotate_left(x, root);
|
|
}
|
|
x->m_parent->m_isblack = true;
|
|
xpp->m_isblack = false;
|
|
_rb_tree_rotate_right(xpp, root);
|
|
}
|
|
}
|
|
else {
|
|
_rb_tree_base* const y = xpp->m_left;
|
|
if (y && y->m_isblack == false) {
|
|
x->m_parent->m_isblack = true;
|
|
y->m_isblack = true;
|
|
xpp->m_isblack = false;
|
|
x = xpp;
|
|
}
|
|
else {
|
|
if (x == x->m_parent->m_left) {
|
|
x = x->m_parent;
|
|
_rb_tree_rotate_right(x, root);
|
|
}
|
|
x->m_parent->m_isblack = true;
|
|
xpp->m_isblack = false;
|
|
_rb_tree_rotate_left(xpp, root);
|
|
}
|
|
}
|
|
}
|
|
root->m_isblack = true;
|
|
}
|
|
|
|
inline _rb_tree_base* _rb_increment(_rb_tree_base* __x) noexcept {
|
|
if (__x->m_right != 0) {
|
|
__x = __x->m_right;
|
|
while (__x->m_left != 0)
|
|
__x = __x->m_left;
|
|
}
|
|
else {
|
|
_rb_tree_base* __y = __x->m_parent;
|
|
while (__x == __y->m_right) {
|
|
__x = __y;
|
|
__y = __y->m_parent;
|
|
}
|
|
if (__x->m_right != __y) __x = __y;
|
|
}
|
|
return __x;
|
|
}
|
|
|
|
inline _rb_tree_base* _rb_decrement(_rb_tree_base* __x) noexcept {
|
|
if (!__x->m_isblack && __x->m_parent->m_parent == __x) __x = __x->m_right;
|
|
else if (__x->m_left != 0) {
|
|
_rb_tree_base* __y = __x->m_left;
|
|
while (__y->m_right != 0)
|
|
__y = __y->m_right;
|
|
__x = __y;
|
|
}
|
|
else {
|
|
_rb_tree_base* __y = __x->m_parent;
|
|
while (__x == __y->m_left) {
|
|
__x = __y;
|
|
__y = __y->m_parent;
|
|
}
|
|
__x = __y;
|
|
}
|
|
return __x;
|
|
}
|
|
|
|
inline _rb_tree_base* _rb_rebalance_for_erase(
|
|
_rb_tree_base* const __z, _rb_tree_base& __header
|
|
) noexcept {
|
|
_rb_tree_base*& __root = __header.m_parent;
|
|
_rb_tree_base*& __leftmost = __header.m_left;
|
|
_rb_tree_base*& __rightmost = __header.m_right;
|
|
_rb_tree_base* __y = __z;
|
|
_rb_tree_base* __x = 0;
|
|
_rb_tree_base* __x_parent = 0;
|
|
|
|
if (__y->m_left == 0) // __z has at most one non-null child. y == z.
|
|
__x = __y->m_right; // __x might be null.
|
|
else if (__y->m_right == 0) // __z has exactly one non-null child. y == z.
|
|
__x = __y->m_left; // __x is not null.
|
|
else {
|
|
// __z has two non-null children. Set __y to
|
|
__y = __y->m_right; // __z's successor. __x might be null.
|
|
while (__y->m_left != 0)
|
|
__y = __y->m_left;
|
|
__x = __y->m_right;
|
|
}
|
|
if (__y != __z) {
|
|
// relink y in place of z. y is z's successor
|
|
__z->m_left->m_parent = __y;
|
|
__y->m_left = __z->m_left;
|
|
if (__y != __z->m_right) {
|
|
__x_parent = __y->m_parent;
|
|
if (__x) __x->m_parent = __y->m_parent;
|
|
__y->m_parent->m_left = __x; // __y must be a child of m_left
|
|
__y->m_right = __z->m_right;
|
|
__z->m_right->m_parent = __y;
|
|
}
|
|
else __x_parent = __y;
|
|
if (__root == __z) __root = __y;
|
|
else if (__z->m_parent->m_left == __z) __z->m_parent->m_left = __y;
|
|
else __z->m_parent->m_right = __y;
|
|
__y->m_parent = __z->m_parent;
|
|
std::swap(__y->m_isblack, __z->m_isblack);
|
|
__y = __z;
|
|
// __y now points to node to be actually deleted
|
|
}
|
|
else { // __y == __z
|
|
__x_parent = __y->m_parent;
|
|
if (__x) __x->m_parent = __y->m_parent;
|
|
if (__root == __z) __root = __x;
|
|
else if (__z->m_parent->m_left == __z) __z->m_parent->m_left = __x;
|
|
else __z->m_parent->m_right = __x;
|
|
if (__leftmost == __z) {
|
|
if (__z->m_right == 0) // __z->m_left must be null also
|
|
__leftmost = __z->m_parent;
|
|
// makes __leftmost == _M_header if __z == __root
|
|
else {
|
|
__leftmost = __x;
|
|
while (__leftmost->m_left != 0)
|
|
__leftmost = __leftmost->m_left;
|
|
}
|
|
}
|
|
if (__rightmost == __z) {
|
|
if (__z->m_left == 0) // __z->m_right must be null also
|
|
__rightmost = __z->m_parent;
|
|
// makes __rightmost == _M_header if __z == __root
|
|
else { // __x == __z->m_left
|
|
__rightmost = __x;
|
|
while (__rightmost->m_right != 0)
|
|
__rightmost = __rightmost->m_right;
|
|
}
|
|
}
|
|
}
|
|
if (__y->m_isblack != false) {
|
|
while (__x != __root && (__x == 0 || __x->m_isblack))
|
|
if (__x == __x_parent->m_left) {
|
|
_rb_tree_base* __w = __x_parent->m_right;
|
|
if (__w->m_isblack == false) {
|
|
__w->m_isblack = true;
|
|
__x_parent->m_isblack = false;
|
|
_rb_tree_rotate_left(__x_parent, __root);
|
|
__w = __x_parent->m_right;
|
|
}
|
|
if ((__w->m_left == 0 || __w->m_left->m_isblack == true) &&
|
|
(__w->m_right == 0 || __w->m_right->m_isblack == true)) {
|
|
__w->m_isblack = false;
|
|
__x = __x_parent;
|
|
__x_parent = __x_parent->m_parent;
|
|
}
|
|
else {
|
|
if (__w->m_right == 0 || __w->m_right->m_isblack == true) {
|
|
__w->m_left->m_isblack = true;
|
|
__w->m_isblack = false;
|
|
_rb_tree_rotate_right(__w, __root);
|
|
__w = __x_parent->m_right;
|
|
}
|
|
__w->m_isblack = __x_parent->m_isblack;
|
|
__x_parent->m_isblack = true;
|
|
if (__w->m_right) __w->m_right->m_isblack = true;
|
|
_rb_tree_rotate_left(__x_parent, __root);
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
// same as above, with m_right <-> m_left.
|
|
_rb_tree_base* __w = __x_parent->m_left;
|
|
if (__w->m_isblack == false) {
|
|
__w->m_isblack = true;
|
|
__x_parent->m_isblack = false;
|
|
_rb_tree_rotate_right(__x_parent, __root);
|
|
__w = __x_parent->m_left;
|
|
}
|
|
if ((__w->m_right == 0 || __w->m_right->m_isblack == true) &&
|
|
(__w->m_left == 0 || __w->m_left->m_isblack == true)) {
|
|
__w->m_isblack = false;
|
|
__x = __x_parent;
|
|
__x_parent = __x_parent->m_parent;
|
|
}
|
|
else {
|
|
if (__w->m_left == 0 || __w->m_left->m_isblack == true) {
|
|
__w->m_right->m_isblack = true;
|
|
__w->m_isblack = false;
|
|
_rb_tree_rotate_left(__w, __root);
|
|
__w = __x_parent->m_left;
|
|
}
|
|
__w->m_isblack = __x_parent->m_isblack;
|
|
__x_parent->m_isblack = true;
|
|
if (__w->m_left) __w->m_left->m_isblack = true;
|
|
_rb_tree_rotate_right(__x_parent, __root);
|
|
break;
|
|
}
|
|
}
|
|
if (__x) __x->m_isblack = true;
|
|
}
|
|
return __y;
|
|
}
|
|
} |