Still working on "tree add" function

* I think the left/right rotates are correct now. Eventually I will rename the members from m_child0/m_child1 to right/left but that ought to be its own commit.
* MxAtomId operator= match
* Added some more comments as I try to work all this stuff out.
This commit is contained in:
disinvite 2023-07-28 17:48:42 -04:00
parent fcfc475eb1
commit d80b387490
3 changed files with 78 additions and 49 deletions

View File

@ -54,13 +54,15 @@ void MxAtomId::Destroy()
// OFFSET: LEGO1 0x100ad1c0 // OFFSET: LEGO1 0x100ad1c0
MxAtomId &MxAtomId::operator=(const MxAtomId &atomId) MxAtomId &MxAtomId::operator=(const MxAtomId &atomId)
{ {
// TODO
const char *temp = m_internal;
if (m_internal) if (m_internal)
Destroy(); Destroy();
if (atomId.m_internal && MxOmni::GetInstance() && AtomIdTree()) if (atomId.m_internal && MxOmni::GetInstance() && AtomIdTree()) {
try_to_open(temp, LookupMode_Exact); TreeValue *value = try_to_open(atomId.m_internal, LookupMode_Exact);
value->RefCountInc();
}
m_internal = atomId.m_internal;
return *this; return *this;
} }
@ -87,24 +89,34 @@ TreeValue *MxAtomId::try_to_open(const char *p_str, LookupMode p_mode)
// should NOT inline // should NOT inline
node = tree->Search(value); node = tree->Search(value);
// pointer reuse??? TreeNode *t;
TreeNode *ptr_reuse = node;
// is the node an exact match? // is the node an exact match?
if (tree->m_root == node || TreeValueCompare(value, node->m_value)) { if (tree->m_root == node || TreeValueCompare(value, node->m_value)) {
ptr_reuse = tree->m_root; t = tree->m_root;
}
ptr_reuse = ptr_reuse->m_child0;
if (ptr_reuse == AtomIdTree()->m_root) {
delete value;
value = ptr_reuse->m_value;
} else { } else {
t = node;
} }
// LAB_100ad42b if (t->m_child0 != AtomIdTree()->m_root) {
delete value;
value = node->m_value;
} else {
// repeat?
node = tree->Search(value);
TreeNode *pOutput;
// TODO: this is all wrong, but I wanted to see if
// just slapping an approximation of the code down would reveal
// the answer.
if (AtomIdTree()->m_p2) {
tree->Insert(&pOutput, pOutput, node, value);
} else {
tree->Insert(&pOutput, pOutput, AtomIdTree()->m_root, value);
}
// LAB_100ad42b
}
return value; return value;
} }

View File

@ -9,7 +9,7 @@ TreeValue::~TreeValue()
// nothing. // nothing.
} }
inline void MxBinaryTree::LeftRotate(TreeNode *x) inline void MxBinaryTree::RightRotate(TreeNode *x)
{ {
TreeNode *y = x->m_child1; TreeNode *y = x->m_child1;
x->m_child1 = y->m_child0; x->m_child1 = y->m_child0;
@ -36,7 +36,7 @@ inline void MxBinaryTree::LeftRotate(TreeNode *x)
} }
} }
inline void MxBinaryTree::RightRotate(TreeNode *x) inline void MxBinaryTree::LeftRotate(TreeNode *x)
{ {
TreeNode *y = x->m_child0; TreeNode *y = x->m_child0;
x->m_child0 = y->m_child1; x->m_child0 = y->m_child1;
@ -63,38 +63,47 @@ inline void MxBinaryTree::RightRotate(TreeNode *x)
} }
} }
inline TreeNode *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)
break;
p_node = p_node->m_child1;
}
return p_node;
}
// OFFSET: LEGO1 0x100ad480 // OFFSET: LEGO1 0x100ad480
void mini_walk(TreeNode* &p_node) void mini_walk(TreeNode* &p_node)
{ {
// I think this is checking whether this is the tree "root" node
// i.e. MxBinaryTree->m_root
// The actual root is m_root->parent. There is an intentional loop here.
// 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 == NODE_COLOR_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;
} }
TreeNode *t = p_node->m_child0; // successor?
if (t != MxBinaryTree::g_Node_Nil) { if (p_node->m_child0 != MxBinaryTree::g_Node_Nil) {
p_node = minimum(p_node->m_child0);
// wonky
while (1) {
if (t->m_child1 == MxBinaryTree::g_Node_Nil)
break;
t = t->m_child1;
}
p_node = t;
return; return;
} }
TreeNode *u = p_node->m_parent; // p_node->m_child0 *is* NIL, so go up a level and try it
TreeNode *v = p_node; TreeNode *y = p_node->m_parent;
while (u != v) { while (p_node == y->m_child0) {
p_node = u; p_node = y;
v = u; y = y->m_parent;
u = u->m_parent;
} }
p_node = u;
} }
// OFFSET: LEGO1 0x100ad4d0 // OFFSET: LEGO1 0x100ad4d0
@ -119,14 +128,17 @@ void MxBinaryTree::Insert(TreeNode **p_output, TreeNode *p_leaf, TreeNode *p_par
p_parent->m_child1 = node; p_parent->m_child1 = node;
if (m_root->m_child1 == p_parent) if (m_root->m_child1 == p_parent)
// Set the tree minimum.
m_root->m_child1 = node; m_root->m_child1 = node;
} else { } else {
p_parent->m_child0 = node; p_parent->m_child0 = node;
if (m_root != p_parent) { if (m_root != p_parent) {
if (m_root->m_child0 == p_parent) if (m_root->m_child0 == p_parent)
// Set the tree maximum.
m_root->m_child0 = node; m_root->m_child0 = node;
} else { } else {
// Set the tree minimum and top node.
m_root->m_parent = node; m_root->m_parent = node;
m_root->m_child1 = node; m_root->m_child1 = node;
} }
@ -150,20 +162,6 @@ void MxBinaryTree::Insert(TreeNode **p_output, TreeNode *p_leaf, TreeNode *p_par
// 100ad5d3 // 100ad5d3
if (parent->m_child1 == cur) { if (parent->m_child1 == 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;
RightRotate(cur->m_parent->m_parent);
continue;
}
} else {
// LAB_100ad67f
if (uncle->m_color != NODE_COLOR_RED) {
if (parent->m_child0 == cur) {
cur = parent; cur = parent;
RightRotate(cur); RightRotate(cur);
} }
@ -174,6 +172,20 @@ void MxBinaryTree::Insert(TreeNode **p_output, TreeNode *p_leaf, TreeNode *p_par
LeftRotate(cur->m_parent->m_parent); LeftRotate(cur->m_parent->m_parent);
continue; continue;
} }
} else {
// LAB_100ad67f
if (uncle->m_color != NODE_COLOR_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;
RightRotate(cur->m_parent->m_parent);
continue;
}
} }
// LAB_100ad72c // LAB_100ad72c

View File

@ -47,6 +47,11 @@ inline TreeNode *newTreeNode(TreeNode *p_parent, int p_color)
// OFFSET: LEGO1 0x100ad120 // OFFSET: LEGO1 0x100ad120
inline int TreeValueCompare(TreeValue *&p_val0, TreeValue *&p_val1) 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; return strcmp(p_val0->m_str.GetData(), p_val1->m_str.GetData()) > 0;
} }