释放为树分配的内存 - C

发布于 2024-09-14 07:47:56 字数 830 浏览 2 评论 0原文

我有一个定义如下的树,

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

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

I have a tree defined like,

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

Now I need to free the memory allocated by this tree. I wrote the following code.

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;
}

This method returns the number of items it freed so that I can verify it against the number of allocations made. This code works. But I am not sure this is the correct way of doing things.

This is a suffix tree implementation. For items s,stack,over, overflow, stackoverflow the tree will look like

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

Any suggestions to improve the code are welcome.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

命硬 2024-09-21 07:47:56

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

另外,您可以删除 child 变量,因为您只在真正需要时使用它一次。每次递归将为您节省 sizeof(pointer) 堆栈空间;-)

If you need to free a tree you need to walk it, so I think the code is correct. I would have done it the same way (recursively walk the tree, freeing the objects along the way). The only thing I would do differently is to run the xfree after the recursion (i.e. swap xfree(current); and freecnt += tree_free(child) + 1;). Because now you delete a node before you delete its child, but I feel that it would be better to delete the child before deleting the parent.

Also, you could get rid of the child variable as you use it only once, with a real need. Would save you sizeof(pointer) of stack space per recursion ;-)

允世 2024-09-21 07:47:56

这是一个相当好的解决方案。您对子级使用递归(不会太深),但对兄弟级使用迭代(如果使用递归,深入)。作为纯递归解决方案,您的代码当然可以更优雅(为 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;
}

它未经测试,因此我没有做出任何保证或适用性声明,特别是因为它对于大量同级链接的特定情况可能是危险的。我将其更多地包含在内是为了表明递归的可能性。我的建议是使用第一个。

That's a fairly good solution. You're using recursion for the children (which won't go too deep) but iteration for the siblings (which would go deep if you used recursion). Your code could certainly be more elegant as a recursion-only solution (calling tree_free for both child and next) but the risk of stack overflow would be greatly increased so I think you made the right choice there.

Having said that, there's no need for child at all if you re-arrange the order of your operations:

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;
}

If you think the length of your sibling list won't be that large, you could try the elegant solution:

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;
}

It's untested so I make no statement of warranty or fitness for purpose, especially since it's probably dangerous for your specific case of a large number of sibling links. I include it more as an indication of what's possible with recursion. My advice is to use the first one.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文