我有一个定义的树,
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,堆栈,覆盖,溢出,堆栈溢出,树将看起来像
root
-s
--stack
---stackoverflow
-over
--overflow
欢迎任何改进代码的建议。
答案 0 :(得分:2)
如果你需要释放一棵树,你需要走它,所以我认为代码是正确的。我会以同样的方式完成它(递归地走树,沿途释放物体)。我唯一要做的就是在递归后运行xfree(即交换xfree(current);
和freecnt += tree_free(child) + 1;
)。因为现在您在删除子节点之前删除了节点,但我觉得在删除父节点之前删除子节点会更好。
此外,您可以删除child
变量,因为您只需要使用一次,但确实需要。每次递归会为你保存sizeof(pointer)
堆栈空间; - )
答案 1 :(得分:1)
这是一个相当不错的解决方案。你正在为孩子们使用递归(这不会太深)但是为兄弟姐妹进行迭代(如果使用递归,会深入)。作为一个仅递归的解决方案(对tree_free
和child
都调用next
),你的代码肯定会更优雅,但是堆栈溢出的风险会大大增加,所以我认为你做了正确的选择。
话虽如此,如果您重新安排运营顺序,则根本不需要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;
}
这是未经测试的,因此我没有声明保修或适用性,特别是因为它可能对您的大量兄弟链接的特定情况有危险。我更多地将其包含在内,表明递归的可能性。我的建议是使用第一个。