From c80744dfdea8a06733cdcca021e6abab9e0e7efb Mon Sep 17 00:00:00 2001 From: disinvite Date: Tue, 1 Aug 2023 23:21:02 -0400 Subject: [PATCH] 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. --- LEGO1/mxbinarytree.cpp | 40 +++++++++++++++++++-------------------- LEGO1/mxbinarytree.h | 43 ++++++++++++++++++++++++------------------ 2 files changed, 45 insertions(+), 38 deletions(-) diff --git a/LEGO1/mxbinarytree.cpp b/LEGO1/mxbinarytree.cpp index abfb5a36..7baa0b93 100644 --- a/LEGO1/mxbinarytree.cpp +++ b/LEGO1/mxbinarytree.cpp @@ -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; } diff --git a/LEGO1/mxbinarytree.h b/LEGO1/mxbinarytree.h index 37d6851e..525fd7d5 100644 --- a/LEGO1/mxbinarytree.h +++ b/LEGO1/mxbinarytree.h @@ -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);