因为您需要在删除期间遍历树,所以想法是在返回时删除
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
}
递归的一个非常重要的方面是何时停止。我假设结构中的 NULL 指针表示没有子树。
if (t->left) del_tree(t->left);
现在的策略是当我们在左右两边都达到 NULL 指针时尽可能深入,我们被困在一片叶子中。我们现在清理叶子(删除值)并返回。执行返回时delete t->left;
,该节点在左子树上没有任何内容,并在其右子树上继续。
在这里我找到了一个很好的遍历图像
删除一棵树的问题分为3个部分。删除左子树,删除右子树,清理self。删除子树(左或右)与删除树本身的过程非常相似。所以你使用相同的函数,这称为递归。
考虑删除文件系统结构。您决定首先删除“左”文件夹结构的策略,然后删除子树“右”,最后删除文件“值”。当您在执行此策略期间更改为文件夹(无论是左还是右)时,您会注意到问题看起来相同。因此,您再次将此策略应用于树中的任何文件夹。
发生的情况是,除非当前目录中没有更多目录,否则您会反复切换到左侧目录。您删除文件“值”。然后您返回一个文件夹并删除名为“left”的文件夹。现在你寻找一个名为'right'的文件夹,进入它,找不到文件夹,删除文件'value'并返回到上一个文件夹。您删除了现在为空的“正确”,最后也删除了文件“值”。接下来是做进一步的返回(回溯)。等等。
在更深入的过程中,您无法删除非空文件夹。撤退时必须删除。