我有一个创建二叉树(* build_tree)*(Huffman)的函数。
我还需要一个释放构建树的内存的函数。
这是我第一次使用二叉树,所以我有点困惑。 我应该创建一个遍历树中每个节点并删除它的循环吗? 我应该考虑节点是叶子还是父节点?
void free_memory(NodePtr root)
{
delete root;
}
struct HuffmanNode
{
//some stuff
HuffmanNode *left;
HuffmanNode *right;
};
如果有人可以帮助我开始,我将不胜感激:)
答案 0 :(得分:2)
如果您在流程步骤中实施了一个后序树遍历并删除了节点和数据,那么您将确保访问树的每个节点并删除数据。
您可以看到递归和迭代示例here,其中包含相关代码。
递归解决方案:
void postOrderTraversal(BinaryTree *p) {
if (!p) return;
postOrderTraversal(p->left);
postOrderTraversal(p->right);
// this is where we delete
delete p->data;
delete p;
}
一种可能的迭代解决方案:
void postOrderTraversalIterative(BinaryTree *root) {
if (!root) return;
stack<BinaryTree*> s;
s.push(root);
BinaryTree *prev = NULL;
while (!s.empty()) {
BinaryTree *curr = s.top();
if (!prev || prev->left == curr || prev->right == curr) {
if (curr->left)
s.push(curr->left);
else if (curr->right)
s.push(curr->right);
} else if (curr->left == prev) {
if (curr->right)
s.push(curr->right);
} else {
// this is where we delete
delete curr->data;
delete curr;
s.pop();
}
prev = curr;
}
}
答案 1 :(得分:1)
如果您使用智能指针,问题将自行解决。如果每个节点包含一个私人SP给它的孩子,并且你删除了一个节点,那么它的孩子也将被释放。显然,你的类析构函数,当它清理时将被SP调用,需要释放任何其他非RIIA分配的资源(如果存在的话)。
class Node
{
private:
std:unique_ptr<Node> left;
std:unique_ptr<Node> right;
}
我在这里使用std::unique_ptr<>
是因为我假设这些是私有的,而不会暴露给程序的其他部分。如果您希望其他东西使用这些指针引用节点,那么您应该使用std::shared_ptr<>
。
如果您不使用SP,则类析构函数需要自己完成工作,并且您必须更加小心内存泄漏。每个类析构函数都会删除它的子节点,而子节点又会调用每个子节点中的析构函数。
class Node
{
private:
NodePtr left;
NodePtr right;
~Node()
{
delete left;
delete right;
// Delete any other resources allocated by the node.
}
}
你也可以像@OldProgrammer建议的那样去做,并在你自己的时候遍历树底删除节点。记住你必须自下而上。如果你自上而下,那么你将失去对(尚未)未删除的子节点和泄漏内存的引用。正如您所看到的,递归删除代码(as referenced in @unluddite's answer)要复杂得多。
以递归方式执行(任何操作)会产生内存开销。见:Is a recursive destructor for linked list, tree, etc. bad?。如果您的树非常大,那么您应该考虑这一点并进行相应的测试。
如果您使用SP,我的建议是第一个解决方案。