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

View File

@ -3,9 +3,11 @@
#include "mxstring.h" #include "mxstring.h"
// TODO: enum instead? enum RBNodeColor
#define NODE_COLOR_RED 0 {
#define NODE_COLOR_BLACK 1 RBNodeColor_Red = 0,
RBNodeColor_Black = 1,
};
// SIZE 0x14 // SIZE 0x14
class TreeValue { class TreeValue {
@ -31,11 +33,11 @@ class TreeNode {
TreeNode *m_parent; // +4 // parent node TreeNode *m_parent; // +4 // parent node
TreeNode *m_child1; // +8 // string sorts before TreeNode *m_child1; // +8 // string sorts before
TreeValue *m_value; // +c 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 // 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(); TreeNode *t = new TreeNode();
t->m_parent = p_parent; t->m_parent = p_parent;
@ -43,17 +45,6 @@ inline TreeNode *newTreeNode(TreeNode *p_parent, int p_color)
return t; 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 // SIZE 0x10
class MxBinaryTree class MxBinaryTree
{ {
@ -63,18 +54,23 @@ class MxBinaryTree
MxBinaryTree() MxBinaryTree()
{ {
if (!g_Node_Nil) { 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_child0 = NULL;
g_Node_Nil->m_child1 = 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(); ~MxBinaryTree();
void LeftRotate(TreeNode *); void LeftRotate(TreeNode *);
void RightRotate(TreeNode *); void RightRotate(TreeNode *);
void Insert(TreeNode **, TreeNode *, TreeNode *, TreeValue *&); 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 *Search(TreeValue *&);
TreeNode *Find(TreeValue *&); TreeNode *Find(TreeValue *&);
@ -84,6 +80,17 @@ class MxBinaryTree
int m_nodeCount; // +c 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) inline TreeNode *MxBinaryTree::Find(TreeValue *&p_value)
{ {
TreeNode *node = Search(p_value); TreeNode *node = Search(p_value);