释放内存二叉树

时间:2014-02-17 16:07:41

标签: c++ binary-tree huffman-code

我有一个创建二叉树(* build_tree)*(Huffman)的函数。

我还需要一个释放构建树的内存的函数。

这是我第一次使用二叉树,所以我有点困惑。 我应该创建一个遍历树中每个节点并删除它的循环吗? 我应该考虑节点是叶子还是父节点?

void free_memory(NodePtr root)
{
    delete root;
}

struct HuffmanNode
{
   //some stuff
    HuffmanNode *left;
    HuffmanNode *right;
};

如果有人可以帮助我开始,我将不胜感激:)

2 个答案:

答案 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,我的建议是第一个解决方案。