mirror of
https://github.com/PrimeDecomp/prime.git
synced 2025-09-01 08:48:38 +00:00
269 lines
6.4 KiB
C++
269 lines
6.4 KiB
C++
#include "rstl/red_black_tree.hpp"
|
|
|
|
namespace rstl {
|
|
|
|
struct _node {
|
|
_node* mLeft;
|
|
_node* mRight;
|
|
_node* mParent;
|
|
node_color mColor;
|
|
};
|
|
|
|
struct _header {
|
|
_node* mLeftmost;
|
|
_node* mRightmost;
|
|
_node* mRootNode;
|
|
};
|
|
|
|
void rbtree_rotate_left(void* header_void, void* node_void) {
|
|
_header* header = static_cast< _header* >(header_void);
|
|
_node* node = static_cast< _node* >(node_void);
|
|
|
|
_node* parent = node->mParent;
|
|
_node* right = node->mRight;
|
|
_node* l = right->mLeft;
|
|
|
|
if (parent == nullptr) {
|
|
header->mRootNode = right;
|
|
right->mParent = nullptr;
|
|
} else {
|
|
if (parent->mLeft == node) {
|
|
parent->mLeft = right;
|
|
} else {
|
|
parent->mRight = right;
|
|
}
|
|
right->mParent = node->mParent;
|
|
}
|
|
node->mParent = right;
|
|
right->mLeft = node;
|
|
if (l) {
|
|
l->mParent = node;
|
|
}
|
|
node->mRight = l;
|
|
}
|
|
|
|
void rbtree_rotate_right(void* header_void, void* node_void) {
|
|
_header* header = static_cast< _header* >(header_void);
|
|
_node* node = static_cast< _node* >(node_void);
|
|
|
|
_node* parent = node->mParent;
|
|
_node* left = node->mLeft;
|
|
_node* r = left->mRight;
|
|
|
|
if (parent == nullptr) {
|
|
header->mRootNode = left;
|
|
left->mParent = nullptr;
|
|
} else {
|
|
if (node == parent->mLeft) {
|
|
parent->mLeft = left;
|
|
} else {
|
|
parent->mRight = left;
|
|
}
|
|
left->mParent = node->mParent;
|
|
}
|
|
node->mParent = left;
|
|
left->mRight = node;
|
|
if (r) {
|
|
r->mParent = node;
|
|
}
|
|
node->mLeft = r;
|
|
}
|
|
|
|
void rbtree_rebalance(void* header_void, void* node_void) {
|
|
_node* node = static_cast< _node* >(node_void);
|
|
_header* header = static_cast< _header* >(header_void);
|
|
|
|
while (node->mParent != nullptr && node->mParent->mColor == kNC_Black) {
|
|
_node* p = node->mParent->mParent->mLeft;
|
|
if (node->mParent == p) {
|
|
p = node->mParent->mParent->mRight;
|
|
if ((p != nullptr && p->mColor == kNC_Black)) {
|
|
node->mParent->mColor = kNC_Red;
|
|
p->mColor = kNC_Red;
|
|
node->mParent->mParent->mColor = kNC_Black;
|
|
node = node->mParent->mParent;
|
|
|
|
} else {
|
|
if (node == node->mParent->mRight) {
|
|
node = node->mParent;
|
|
rbtree_rotate_left(header, node);
|
|
}
|
|
node->mParent->mColor = kNC_Red;
|
|
node->mParent->mParent->mColor = kNC_Black;
|
|
rbtree_rotate_right(header, node->mParent->mParent);
|
|
}
|
|
} else if (p != nullptr && p->mColor == kNC_Black) {
|
|
node->mParent->mColor = kNC_Red;
|
|
p->mColor = kNC_Red;
|
|
node->mParent->mParent->mColor = kNC_Black;
|
|
node = node->mParent->mParent;
|
|
|
|
} else {
|
|
if (node == node->mParent->mLeft) {
|
|
node = node->mParent;
|
|
rbtree_rotate_right(header, node);
|
|
}
|
|
node->mParent->mColor = kNC_Red;
|
|
node->mParent->mParent->mColor = kNC_Black;
|
|
rbtree_rotate_left(header, node->mParent->mParent);
|
|
}
|
|
}
|
|
header->mRootNode->mColor = kNC_Red;
|
|
}
|
|
|
|
void* rbtree_rebalance_for_erase(void* header_void, void* node_void) {
|
|
_header* header = static_cast< _header* >(header_void);
|
|
_node* node = static_cast< _node* >(node_void);
|
|
|
|
_node* next;
|
|
_node* result = node;
|
|
|
|
if (node->mLeft == nullptr) {
|
|
next = node->mRight;
|
|
} else {
|
|
_node* tmp = node->mRight;
|
|
if (tmp == nullptr) {
|
|
next = tmp;
|
|
} else {
|
|
do {
|
|
result = tmp;
|
|
tmp = result->mLeft;
|
|
} while (result->mLeft != nullptr);
|
|
next = result->mRight;
|
|
}
|
|
}
|
|
|
|
if (result != node) {
|
|
node->mLeft->mParent = result;
|
|
result->mLeft = node->mLeft;
|
|
|
|
_node* tmp = result;
|
|
if (result != node->mRight) {
|
|
tmp = result->mParent;
|
|
if (next != nullptr) {
|
|
next->mParent = result->mParent;
|
|
}
|
|
result->mParent->mLeft = next;
|
|
result->mRight = node->mRight;
|
|
node->mRight->mParent = result;
|
|
}
|
|
|
|
if (header->mRootNode == node) {
|
|
header->mRootNode = result;
|
|
} else {
|
|
if (node->mParent->mLeft == node) {
|
|
node->mParent->mLeft = result;
|
|
} else {
|
|
node->mParent->mRight = result;
|
|
}
|
|
}
|
|
|
|
result->mParent = node->mParent;
|
|
node_color c = result->mColor;
|
|
result->mColor = node->mColor;
|
|
node->mColor = c;
|
|
result = node;
|
|
|
|
} else {
|
|
_node* a1 = result->mParent;
|
|
if (next != nullptr) {
|
|
next->mParent = a1;
|
|
}
|
|
if (header->mRootNode == node) {
|
|
header->mRootNode = next;
|
|
} else {
|
|
if (node->mParent->mLeft == node) {
|
|
node->mParent->mLeft = next;
|
|
} else {
|
|
node->mParent->mRight = next;
|
|
}
|
|
}
|
|
|
|
if (header->mLeftmost == node) {
|
|
if (node->mRight == nullptr) {
|
|
header->mLeftmost = node->mParent;
|
|
} else {
|
|
// prVar1 = next;
|
|
_node* prVar1 = next;
|
|
if (next == nullptr) {
|
|
header->mLeftmost = nullptr;
|
|
} else {
|
|
_node* newLeftmost;
|
|
do {
|
|
newLeftmost = prVar1;
|
|
prVar1 = newLeftmost->mLeft;
|
|
} while (newLeftmost->mLeft != nullptr);
|
|
header->mLeftmost = newLeftmost;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (header->mRightmost == node) {
|
|
if (node->mLeft == nullptr) {
|
|
header->mRightmost = node->mParent;
|
|
} else {
|
|
// prVar1 = next;
|
|
_node* prVar1 = next;
|
|
if (next == nullptr) {
|
|
header->mRightmost = nullptr;
|
|
} else {
|
|
_node* newRightmost;
|
|
do {
|
|
newRightmost = prVar1;
|
|
prVar1 = newRightmost->mRight;
|
|
} while (newRightmost->mRight != nullptr);
|
|
header->mRightmost = newRightmost;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (result->mColor != kNC_Black) {
|
|
while (true) {
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void* rbtree_traverse_forward(const void* header_void, void* node_void) {
|
|
const _header* header = static_cast< const _header* >(header_void);
|
|
_node* node = static_cast< _node* >(node_void);
|
|
|
|
if (node == nullptr) {
|
|
return header->mLeftmost;
|
|
}
|
|
_node* right = node->mRight;
|
|
if ((right == nullptr) && (node->mParent == nullptr)) {
|
|
return nullptr;
|
|
}
|
|
if ((right == nullptr) && (node->mParent->mLeft == node)) {
|
|
return node->mParent;
|
|
}
|
|
|
|
if (right != nullptr) {
|
|
_node* result = right;
|
|
goto enter_middle;
|
|
do {
|
|
result = right;
|
|
enter_middle:
|
|
right = result->mLeft;
|
|
} while (right != nullptr);
|
|
return result;
|
|
}
|
|
|
|
_node* parent = nullptr;
|
|
goto enter_final;
|
|
do {
|
|
node = parent;
|
|
enter_final:
|
|
parent = node->mParent;
|
|
if (!parent)
|
|
break;
|
|
} while (parent->mRight == node);
|
|
|
|
return parent != nullptr ? parent : nullptr;
|
|
}
|
|
|
|
} // namespace rstl
|