【问题标题】:Freeing memory allocated for a Tree - C释放分配给树的内存 - C
【发布时间】:2011-03-29 20:39:56
【问题描述】:

我定义了一棵树,

struct tree {
    char label[MAX_LENGTH];
    char value[MAX_LENGTH];
    struct tree *child;
    struct tree *next;
};

现在我需要释放这棵树分配的内存。我写了以下代码。

unsigned int tree_free(struct tree *root)
{
    struct tree *current = NULL, *next = NULL, *child = NULL;
    unsigned int freecnt = 0;

    current = root;
    while(current != NULL)
    {
        next = current->next;
        child = current->child;      
        xfree(current);
        freecnt += tree_free(child) + 1;
        current = next;
    }
    return freecnt;
}

此方法返回它释放的项目数,以便我可以根据分配的数量来验证它。此代码有效。但我不确定这是正确的做事方式。

这是一个后缀树实现。对于项目 s,stack,over,overflow,stackoverflow,树看起来像

root
-s
--stack
---stackoverflow
-over
--overflow

欢迎提出任何改进代码的建议。

【问题讨论】:

  • 您遗漏了一些细节:(1)树的结构是什么?从代码中可以看出它不是“香草”二叉树。 (2)xfree是什么?
  • 它不是二叉树。这是一种后缀树的实现。 xfree 只是 free() 的一个包装器。一棵树将有多个子元素,而不仅仅是像二叉树那样的两个。
  • 编辑了我的帖子以使其清楚。

标签: c algorithm memory-management tree


【解决方案1】:

如果你需要释放一棵树,你需要走它,所以我认为代码是正确的。我会以同样的方式来做(递归地走树,沿途释放对象)。我唯一不同的是在递归之后运行 xfree(即交换 xfree(current);freecnt += tree_free(child) + 1;)。因为现在你在删除它的子节点之前先删除一个节点,但我觉得在删除父节点之前删除子节点会更好。

此外,您可以删除 child 变量,因为您只使用一次,确实需要。每次递归将为您节省sizeof(pointer) 的堆栈空间;-)

【讨论】:

    【解决方案2】:

    这是一个相当好的解决方案。您正在对孩子使用递归(不会太深),但对兄弟姐妹使用迭代(如果您使用递归,深入)。作为仅递归的解决方案,您的代码当然可以更优雅(为childnext 调用tree_free),但堆栈溢出的风险会大大增加,所以我认为你在那里做出了正确的选择。

    话虽如此,如果您重新安排操作顺序,则根本不需要child

    unsigned int tree_free (struct tree *root) {
        struct tree *current = NULL, *next = NULL;
        unsigned int freecnt = 0;
    
        current = root;
        while(current != NULL)
        {
            freecnt += tree_free (current->child) + 1;
            next = current->next;
            xfree (current);
            current = next;
        }
        return freecnt;
    }
    

    如果您认为兄弟列表的长度不会那么大,您可以尝试优雅的解决方案:

    unsigned int tree_free (struct tree *root) {
        unsigned int freecnt;
    
        if (root == NULL) return 0;
        freecnt = tree_free (root->child) + tree_free (root->next);
        xfree (root);
        return freecnt + 1;
    }
    

    它未经测试,因此我不作任何保证或适用性声明,特别是因为它可能对您的大量同级链接的特定情况很危险。我将它更多地包括在内,以表明递归的可能性。我的建议是使用第一个。

    【讨论】:

    • 非常感谢。很高兴听到实施还可以。再次感谢。
    猜你喜欢
    • 2013-04-14
    • 2013-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-16
    • 2013-11-22
    • 1970-01-01
    相关资源
    最近更新 更多