有人可以直观地解释树遍历是如何工作的吗?

时间:2012-12-08 23:55:07

标签: c++ tree

我正在尝试通过遍历树并根据需要删除内存来恢复树中分配的内存。例如,假设我有以下树结构:

struct tree
{
   int *value;
   tree *left;
   tree *right;
}

tree *root; //always points to the root of this tree

我知道我们必须在每次递归调用后访问每个value,删除它,然后移动到下一个节点(可以是leftright),但是递归过程似乎非常直观(特别是我们向左移动或向右移动的部分)。

我正在尝试遵循“用root做一些事情,递归调用左边,然后递归调用右边”的规则,但代码函数的方式让我感到困惑。如何保留root的不变量?如果有人能够以图形方式解释这个概念,那就太棒了。

2 个答案:

答案 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)

因此,当您按照原文中的分支进行操作时,您最终会再次进入根目录。