cleanups and a few more utility methods

This commit is contained in:
AzaezelX 2026-01-27 17:47:19 -06:00
parent 0175c109ac
commit 09f0fa2861

View file

@ -32,13 +32,20 @@ class TreeNode : public Vector<TreeNode<T>*> {
public:
T data;
TreeNode<T>* parent;
TreeNode(const T& val = T(), TreeNode<T>* p = NULL) : data(val), parent(p){}
TreeNode(const T& val = T(), TreeNode<T>* p = NULL) : data(val), parent(p) {}
virtual ~TreeNode()
{
deleteChildren();
if (parent)
{
parent->remove(this);
for (U32 i = 0; i < parent->size(); i++)
{
if ((*parent)[i] == this)
{
parent->erase(i);
break;
}
}
parent = NULL;
}
}
@ -46,12 +53,14 @@ public:
//description logic
inline bool isRoot() const { return parent == NULL; }
inline bool isLeaf() const { return size() == 0; }
//parent logic
// Parent logic
inline TreeNode<T>* getParent() const { return parent; }
inline void setParent(TreeNode<T>* p)
{
if (parent) parent->remove(this);
if (parent == p) return;
if (parent) parent->removeChild(this);
parent = p;
if (parent) parent->push_back(this);
}
@ -65,10 +74,21 @@ public:
}
inline void addChild(TreeNode<T>* child)
{
if (child) {
child->parent = this;
push_back(child);
if (!child) return;
// Check if already a child to prevent duplicates
for (U32 i = 0; i < size(); i++)
{
if ((*this)[i] == child)
return; // Already a child
}
// Remove from old parent if needed
if (child->parent && child->parent != this)
child->parent->removeChild(child);
child->parent = this;
push_back(child);
}
inline void setChild(U32 i, TreeNode<T>* child)
{
@ -80,12 +100,41 @@ public:
(*this)[j] = NULL;
}
TreeNode<T>* oldChild = (*this)[i];
if (oldChild == child) return;
// Unlink old child
if (oldChild)
{
oldChild->parent = NULL;
}
if (child == NULL)
{
removeChild(i);
(*this)[i] = NULL;
}
else
{
// Handle moving from different parent vs same parent
if (child->parent && child->parent != this)
{
child->parent->removeChild(child);
}
else if (child->parent == this)
{
// Moving within same parent - find and remove from old slot
for (U32 j = 0; j < size(); j++)
{
if (j != i && (*this)[j] == child)
{
erase(j);
if (j < i)
i--;
break;
}
}
}
(*this)[i] = child;
child->parent = this;
}
@ -93,8 +142,6 @@ public:
inline TreeNode<T>* getChild(U32 i) const
{
if (!this)
return NULL;
if (i < size())
return (*this)[i];
return NULL;
@ -103,12 +150,28 @@ public:
inline void addChildren(const Vector<T>* children)
{
if (!children) return;
for (U32 i = 0; i < children->size(); i++) {
for (U32 i = 0; i < children->size(); i++)
{
TreeNode<T>* child = new TreeNode<T>((*children)[i], this);
push_back(child);
}
}
inline void removeChild(TreeNode<T>* child)
{
if (!child) return;
for (U32 i = 0; i < size(); i++)
{
if ((*this)[i] == child)
{
child->parent = NULL;
erase(i);
return;
}
}
}
inline void removeChild(U32 i)
{
if (i < size())
@ -119,6 +182,62 @@ public:
erase(i);
}
}
inline void replaceChild(TreeNode<T>* oldChild, TreeNode<T>* newChild)
{
if (!oldChild) return;
for (U32 i = 0; i < size(); i++)
{
if ((*this)[i] == oldChild)
{
oldChild->parent = NULL;
if (newChild)
{
// Handle moving from different parent vs same parent
if (newChild->parent && newChild->parent != this)
{
newChild->parent->removeChild(newChild);
}
else if (newChild->parent == this)
{
// Moving within same parent - find and remove from old slot
for (U32 j = 0; j < size(); j++)
{
if (j != i && (*this)[j] == newChild)
{
erase(j);
if (j < i)
i--;
break;
}
}
}
(*this)[i] = newChild;
newChild->parent = this;
}
else
{
(*this)[i] = NULL;
}
return;
}
}
}
inline void compact()
{
// Remove NULL entries from children array
for (U32 i = 0; i < size(); )
{
if ((*this)[i] == NULL)
erase(i);
else
i++;
}
}
void operator =(Vector<T>* other) { clear(); addChildren(other); }
inline U32 getNumChildren() const { return size(); }
@ -128,13 +247,18 @@ public:
Vector<TreeNode<T>*> children;
children.reserve(size());
for (U32 i = 0; i < size(); i++)
children.push_back((*this)[i]);
{
if ((*this)[i]) // Skip NULLs
children.push_back((*this)[i]);
}
return children;
}
inline void deleteChildren()
{
Vector<TreeNode<T>*> children;
for (U32 i = 0; i < size(); i++) {
for (U32 i = 0; i < size(); i++)
{
children.push_back((*this)[i]);
}
clear();
@ -156,9 +280,10 @@ public:
if (!parent) return siblings;
siblings.reserve(parent->size() - 1);
for (U32 i = 0; i < parent->size(); i++) {
for (U32 i = 0; i < parent->size(); i++)
{
TreeNode<T>* sibling = (*parent)[i];
if (sibling != this)
if (sibling && sibling != this) // Skip NULLs
siblings.push_back(sibling);
}
return siblings;
@ -169,6 +294,35 @@ public:
inline void setData(const T& val) { data = val; }
inline void operator =(const T& val) { data = val; }
inline T* getDataPtr() { return &data; }
// Traversal helpers
inline U32 getDepth() const
{
U32 depth = 0;
TreeNode<T>* current = parent;
while (current)
{
depth++;
current = current->parent;
}
return depth;
}
inline TreeNode<T>* getRoot()
{
TreeNode<T>* current = this;
while (current->parent)
current = current->parent;
return current;
}
inline const TreeNode<T>* getRoot() const
{
const TreeNode<T>* current = this;
while (current->parent)
current = current->parent;
return current;
}
};
class TreeObject : public SimObject {
@ -213,7 +367,7 @@ public:
bool toParent(S32 key, S32 newParentKey);
Vector<S32> getChildren(S32 key);
S32 getNumChildren(S32 key) {return getChildren(key).size();};
S32 getNumChildren(S32 key) { return getChildren(key).size(); };
Vector<S32> getSiblings(S32 key);
S32 getNumSiblings(S32 key) { return getSiblings(key).size(); };