我正在尝试通过遍历树并根据需要删除内存来恢复树中分配的内存。例如,假设我有以下树结构:
struct tree
{
int *value;
tree *left;
tree *right;
}
tree *root; //always points to the root of this tree
我知道我们必须在每次递归调用后访问每个value
,删除它,然后移动到下一个节点(可以是left
或right
),但是递归过程似乎非常直观(特别是我们向左移动或向右移动的部分)。
我正在尝试遵循“用root做一些事情,递归调用左边,然后递归调用右边”的规则,但代码函数的方式让我感到困惑。如何保留root
的不变量?如果有人能够以图形方式解释这个概念,那就太棒了。
答案 0 :(得分:0)
因为在删除期间需要树进行遍历,所以想法是在返回时删除
void del_tree(tree *t) {
if (t->left) {
// there is a left subtree existing. delete it
del_tree(t->left); // first go deeper on left side
// left branch now completely empty
delete t->left; // nothing left behind t->left
t->left=0; // just in case
} else {
// there is no left subtree existing
// we are in a leaf or in an unbalanced node
}
if (t->right) {
// there is a right subtree existing. delete it
del_tree(t->right); // now go deeper on right side
// right branch now completely empty
delete t->right; // nothing left behind t->right
t->right=0; // just in case
} else {
// there is no rigt subtree existing
// we are in a leaf or this was an unbalanced node
// (before we deleted the left subtree)
}
// both branches are now completely empty
// either they were from the beginning (leaf)
// or we have successfully reduced this node to a leaf
// now do the node visit
if (t->value) {
delete t->value; // tidy up
t->value=0; // just in case
}
// now we are completely clean and empty
// after return t will be deleted
}
void main() {
tree *my_tree;
// stuff
del_tree(my_tree); // delete the whole tree
delete my_tree; // delete the remaining root node
}
递归的一个非常重要的方面是何时停止。我假设你的struct中的NULL指针表明没有子树。
现在的策略尽可能深入if (t->left) del_tree(t->left);
当我们在左侧和右侧都达到NULL指针时,我们被搁浅在一片叶子中。我们现在清理叶子(删除值)并返回。在执行返回delete t->left;
时,此节点在左子树上没有任何内容,并继续在其右子树上。
在这里,我找到了traversal
的精美图片删除树的问题分为3部分。删除左子树,删除右子树并清理自己。删除子树(左或右)与删除树本身的过程非常相同。所以你使用相同的函数,这称为递归。
想到删除文件系统结构。您决定首先删除'left'文件夹结构的策略,然后删除子树'right',最后删除文件'value'。在执行此策略期间,您将更改为文件夹(无论是向左还是向右),您会发现问题看起来相同。所以你再次将这个策略应用到树中的任何文件夹。
发生的情况是,您将重复更改为目录,除非当前目录中没有更多目录。你删除文件'值'。然后你返回一个文件夹并删除名为'left'的文件夹。现在你找一个名为'right'的文件夹,改成它,找不到文件夹,删除文件'value'并返回上一个文件夹。你删除现在为空的'right',最后删除文件'的值。接下来是做进一步的回归(回溯)。等等。
在深入期间,您无法删除非空文件夹。撤退时你必须删除。
答案 1 :(得分:0)
您可以将树视为具有根和两个叶子的树,并且每个叶子指向另一个树的根。
实际上,这就是你保留“root的不变量”的方法,因为只要你按照一个叶子的指针,就会到达另一棵树的根。
root -> branch -> leaf
|
V
branch -> leaf
也可以视为
root -> tree1
|
V
tree2
反过来
root -> (root -> leaf)
|
V
(root -> leaf)
因此,当您按照原文中的分支进行操作时,您最终会再次进入根目录。