我一直在努力解决这个问题。我有一个BST,用于在插入时遇到重复时递增计数器。这完全按照设计工作。
树丢弃此元素,树保持不变。但是我想删除树中的原始元素,以便第三次插入重复元素不会增加计数器。我运行程序时遇到段错误。请参阅下面的代码。 GDB说segfault发生在InsertInto()方法中,而ValGrind抱怨我找不到一堆内存泄漏。
非常感谢任何帮助。
struct BSTreeNode
{
int mData;
BSTreeNode *mLeft, *mRight;
BSTreeNode(int i)
{
mData = i;
mLeft = NULL;
mRight = NULL;
}
~BSTreeNode()
{
delete mLeft;
delete mRight;
}
};
class BSTree {
private:
BSTreeNode * mRoot;
bool mWithDeletion;
public:
int mDupCounter;
BSTree():mRoot(NULL),mDupCounter(0),mWithDeletion(false){}
BSTree(bool _withDelete):mRoot(NULL),mDupCounter(0),mWithDeletion(_withDelete){}
~BSTree()
{
delete mRoot;
}
BSTreeNode * FindSmallest(BSTreeNode *& _node)
{
if (!_node->mLeft)
return _node;
else
return FindSmallest(_node->mLeft);
}
void DeleteNode(BSTreeNode *& _node)
{
if (!_node->mLeft && !_node->mRight) // no subtrees
{
delete _node;
_node = NULL;
}
else if (_node->mLeft && !(_node->mRight)) // only left subtree
{
_node = _node->mLeft;
}
else if (_node->mRight && !(_node->mLeft)) // only right subtree
{
_node = _node->mRight;
}
else // both subtrees exist.
{
BSTreeNode * temp = FindSmallest(_node->mRight);
_node->mData = temp->mData;
DeleteNode(temp);
}
}
void InsertInto(BSTreeNode *& _node, int _valueToInsert)
{
if (!_node)
{
_node = new BSTreeNode(_valueToInsert);
}
else if (_valueToInsert < _node->mData)
{
InsertInto(_node->mLeft, _valueToInsert);
}
else if (_valueToInsert > _node->mData)
{
InsertInto(_node->mRight, _valueToInsert);
}
else
{
cout << "DUPLICATE FOUND!" << endl;
mDupCounter++;
// delete the node already in the tree if we must
if (mWithDeletion)
DeleteNode(_node);
}
cout << endl;
}
void InsertIntoRoot(int _valueToInsert)
{
InsertInto(mRoot, _valueToInsert);
}
};
答案 0 :(得分:0)
您确定要通过删除节点来避免计算第三个副本吗?!即使你的删除代码正确,你仍然可以计算第4,第6等复制品。 你在模糊地隐藏了在没有节点的情况下发生重复这一事实。
如果您在每个BSTreeNode中明确存储计数器,那么您自己会帮忙。我确信与树中重复的非平凡删除/插入相比,开销可以忽略不计。
else
{
cout << "DUPLICATE FOUND!" << endl;
_node.DupCounter++;
}
如果它不是性能我甚至会忽略全局mDupCounter并遍历树来分析结果。如果要求发生变化,您可以有更多选择来计算不同的数字,例如:频率或其他的直方图。