Some cleanup. Make red-black node color an enum as promised.

Not converting to template class just yet, because we lose the ability to meaningfully compare the code using the reccmp tool. My plan is to get the functions as close as possible to a match, then change over at the final step.
This commit is contained in:
disinvite 2023-08-01 23:21:02 -04:00
parent 8afddd3bdb
commit c80744dfde
2 changed files with 45 additions and 38 deletions

View File

@ -65,12 +65,12 @@ inline void MxBinaryTree::LeftRotate(TreeNode *x)
}
}
inline TreeNode *minimum(TreeNode *p_node)
inline TreeNode *MxBinaryTree::minimum(TreeNode *p_node)
{
// horrible. but it has to be this way to
// force a non-branching JMP to repeat the loop.
while (1) {
if (p_node->m_child1 == MxBinaryTree::g_Node_Nil)
if (p_node->m_child1 == g_Node_Nil)
break;
p_node = p_node->m_child1;
}
@ -80,7 +80,7 @@ inline TreeNode *minimum(TreeNode *p_node)
// OFFSET: LEGO1 0x100ad480
void Successor(TreeNode* &p_node)
void MxBinaryTree::Successor(TreeNode* &p_node)
{
// I think this is checking whether this is the tree "root" node
// i.e. MxBinaryTree->m_root
@ -88,13 +88,13 @@ void Successor(TreeNode* &p_node)
// If it is the "root" node, return the minimum value of the tree.
// We have a reference to it at m_root->m_child1.
if (p_node->m_color == NODE_COLOR_RED
if (p_node->m_color == RBNodeColor_Red
&& p_node->m_parent->m_parent == p_node) {
p_node = p_node->m_child1;
return;
}
if (p_node->m_child0 != MxBinaryTree::g_Node_Nil) {
if (p_node->m_child0 != g_Node_Nil) {
p_node = minimum(p_node->m_child0);
return;
}
@ -111,7 +111,7 @@ void Successor(TreeNode* &p_node)
// OFFSET: LEGO1 0x100ad4d0
void MxBinaryTree::Insert(TreeNode **p_output, TreeNode *p_leaf, TreeNode *p_parent, TreeValue *&p_value)
{
TreeNode *node = newTreeNode(p_parent, NODE_COLOR_RED);
TreeNode *node = newTreeNode(p_parent, RBNodeColor_Red);
node->m_child0 = g_Node_Nil;
node->m_child1 = g_Node_Nil;
@ -125,7 +125,7 @@ void MxBinaryTree::Insert(TreeNode **p_output, TreeNode *p_leaf, TreeNode *p_par
// if param_2 is tree_nil (always true I think?)
//
if (m_root != p_parent
&& p_leaf == MxBinaryTree::g_Node_Nil
&& p_leaf == g_Node_Nil
&& TreeValueCompare(p_value, p_parent->m_value)) {
p_parent->m_child1 = node;
@ -152,7 +152,7 @@ void MxBinaryTree::Insert(TreeNode **p_output, TreeNode *p_leaf, TreeNode *p_par
while (m_root->m_parent != cur) {
TreeNode *parent = cur->m_parent;
if (parent->m_color != NODE_COLOR_RED)
if (parent->m_color != RBNodeColor_Red)
break;
TreeNode *uncle = parent->m_parent->m_child0;
@ -160,7 +160,7 @@ void MxBinaryTree::Insert(TreeNode **p_output, TreeNode *p_leaf, TreeNode *p_par
// wrong uncle
uncle = parent->m_parent->m_child1;
if (uncle->m_color != NODE_COLOR_RED) {
if (uncle->m_color != RBNodeColor_Red) {
// 100ad5d3
if (parent->m_child1 == cur) {
@ -169,36 +169,36 @@ void MxBinaryTree::Insert(TreeNode **p_output, TreeNode *p_leaf, TreeNode *p_par
}
// LAB_100ad60f
cur->m_parent->m_color = NODE_COLOR_BLACK;
cur->m_parent->m_parent->m_color = NODE_COLOR_RED;
cur->m_parent->m_color = RBNodeColor_Black;
cur->m_parent->m_parent->m_color = RBNodeColor_Red;
LeftRotate(cur->m_parent->m_parent);
continue;
}
} else {
// LAB_100ad67f
if (uncle->m_color != NODE_COLOR_RED) {
if (uncle->m_color != RBNodeColor_Red) {
if (parent->m_child0 == cur) {
cur = parent;
LeftRotate(cur);
}
// LAB_100ad60f
cur->m_parent->m_color = NODE_COLOR_BLACK;
cur->m_parent->m_parent->m_color = NODE_COLOR_RED;
cur->m_parent->m_color = RBNodeColor_Black;
cur->m_parent->m_parent->m_color = RBNodeColor_Red;
RightRotate(cur->m_parent->m_parent);
continue;
}
}
// LAB_100ad72c
parent->m_color = NODE_COLOR_BLACK;
uncle->m_color = NODE_COLOR_BLACK;
parent->m_parent->m_color = NODE_COLOR_RED;
parent->m_color = RBNodeColor_Black;
uncle->m_color = RBNodeColor_Black;
parent->m_parent->m_color = RBNodeColor_Red;
cur = parent->m_parent;
}
m_root->m_parent->m_color = NODE_COLOR_BLACK;
m_root->m_parent->m_color = RBNodeColor_Black;
*p_output = node;
}
@ -241,10 +241,10 @@ MxBinaryTree::~MxBinaryTree()
}
// OFFSET: LEGO1 0x100af7a0
void somethingWithNode(TreeNode*& p_node)
void MxBinaryTree::Predecessor(TreeNode*& p_node)
{
// TODO
if (p_node->m_child1 != MxBinaryTree::g_Node_Nil) {
if (p_node->m_child1 != g_Node_Nil) {
p_node = minimum(p_node->m_child1);
return;
}

View File

@ -3,9 +3,11 @@
#include "mxstring.h"
// TODO: enum instead?
#define NODE_COLOR_RED 0
#define NODE_COLOR_BLACK 1
enum RBNodeColor
{
RBNodeColor_Red = 0,
RBNodeColor_Black = 1,
};
// SIZE 0x14
class TreeValue {
@ -31,11 +33,11 @@ class TreeNode {
TreeNode *m_parent; // +4 // parent node
TreeNode *m_child1; // +8 // string sorts before
TreeValue *m_value; // +c
int m_color; // +10 // BLACK or RED.
RBNodeColor m_color; // +10 // BLACK or RED.
};
// TODO: helper to avoid using a non-default constructor
inline TreeNode *newTreeNode(TreeNode *p_parent, int p_color)
inline TreeNode *newTreeNode(TreeNode *p_parent, RBNodeColor p_color)
{
TreeNode *t = new TreeNode();
t->m_parent = p_parent;
@ -43,17 +45,6 @@ inline TreeNode *newTreeNode(TreeNode *p_parent, int p_color)
return t;
}
// OFFSET: LEGO1 0x100ad120
inline int TreeValueCompare(TreeValue *&p_val0, TreeValue *&p_val1)
{
// For strcmp, a result greater than 0 means that b > a.
// So: for this function, return TRUE if:
// * string values are non-equal
// * string values are in order: p_val0 < p_val1
return strcmp(p_val0->m_str.GetData(), p_val1->m_str.GetData()) > 0;
}
// SIZE 0x10
class MxBinaryTree
{
@ -63,18 +54,23 @@ class MxBinaryTree
MxBinaryTree()
{
if (!g_Node_Nil) {
g_Node_Nil = newTreeNode(NULL, NODE_COLOR_BLACK);
g_Node_Nil = newTreeNode(NULL, RBNodeColor_Black);
g_Node_Nil->m_child0 = NULL;
g_Node_Nil->m_child1 = NULL;
}
m_root = newTreeNode(g_Node_Nil, NODE_COLOR_RED);
m_root = newTreeNode(g_Node_Nil, RBNodeColor_Red);
}
~MxBinaryTree();
void LeftRotate(TreeNode *);
void RightRotate(TreeNode *);
void Insert(TreeNode **, TreeNode *, TreeNode *, TreeValue *&);
void Successor(TreeNode* &p_node);
void Predecessor(TreeNode *&p_node);
int TreeValueCompare(TreeValue *&p_val0, TreeValue *&p_val1);
TreeNode *minimum(TreeNode *p_node);
TreeNode *maximum(TreeNode *p_node);
TreeNode *Search(TreeValue *&);
TreeNode *Find(TreeValue *&);
@ -84,6 +80,17 @@ class MxBinaryTree
int m_nodeCount; // +c
};
// OFFSET: LEGO1 0x100ad120
inline int MxBinaryTree::TreeValueCompare(TreeValue *&p_val0, TreeValue *&p_val1)
{
// For strcmp, a result greater than 0 means that b > a.
// So: for this function, return TRUE if:
// * string values are non-equal
// * string values are in order: p_val0 < p_val1
return strcmp(p_val0->m_str.GetData(), p_val1->m_str.GetData()) > 0;
}
inline TreeNode *MxBinaryTree::Find(TreeValue *&p_value)
{
TreeNode *node = Search(p_value);