【问题标题】:traversing binary search tree C++遍历二叉搜索树 C++
【发布时间】:2012-10-04 21:57:48
【问题描述】:

我正在做一个编程作业并编写一堆函数来实现二叉搜索树,并给出了一些函数。我以为我理解递归,但如果你愿意的话,我一直对切换方向感到困惑。

这是一个赋值函数:

static void deleteAll(BSTNode<Data>* n) {
  if (0 == n) return;
  deleteAll(n->left);
  deleteAll(n->right);
  delete n;
}

要删除一棵非常短的树,

 根
   / \
左右手

我打电话给deleteAll(root)n != 0 所以现在我打电话给deleteAll(lefty)n != 0 所以我打电话给deleteAll(lefty-&gt;left)。当然没有左节点。当我添加左节点时,我的构造函数将左、右和父指针初始化为 0,所以现在 n == 0。所以我退出了函数并且永远不会删除 righty。我怎样才能到达deleteAll(n-&gt;right)

正如我所说,提供了此功能,因此我不应该更改它。我想也许我必须调用deleteAll(b.begin())b.end() 以从最左边或最右边的节点开始,但每次我在脑海中经历它时,我都会点击n == 0

请帮助我理解。

【问题讨论】:

  • 也许让它在每个函数的不同点打印,这样你就可以了解发生了什么:) 看起来它应该在当前代码中正常工作!
  • 告诉你的老师字母 n 是为大小保留的。转念一想,不要。只要记住它。那个“if(0==n)”让我愣了一秒。

标签: c++ recursion binary-search-tree


【解决方案1】:

想象一个箭头指向正在执行的当前行。当我们调用deleteAll(root)时,首先我们检查root是否为0:

--> if (0 == root) return;
    deleteAll(root->left);
    deleteAll(root->right);
    delete root;

因为root != 0,所以我们调用deleteAll(root-&gt;left)

    if (0 == root) return;
--> deleteAll(root->left); /*
    |-1-> if (0 == lefty) return;
    |-2-> deleteAll(lefty->left);
    |-3-> deleteAll(lefty->right);
    |-4-> delete lefty; */
    deleteAll(root->right);
    delete root;
  }

现在箭头将移回函数顶部并开始对lefty 执行相同的操作,贯穿我评论中的第 1-4 行(在第 2 行,相同的扩展将再次发生,直到找到空节点)。但这里重要的是它记住它在函数调用之前的位置,以便以后可以恢复。所以deleteAll(root-&gt;left) 会去做它所做的事情并最终返回。然后原来的调用继续:

    if (0 == root) return;
    deleteAll(root->left);
--> deleteAll(root->right);
    delete root;

现在右节点也被删除了。这发生在递归的每一步。请记住,return 只返回当前函数,而不是整个递归链。

【讨论】:

    【解决方案2】:

    return 只返回到调用它的函数。在deleteAll(lefty) 的情况下(如果我理解正确,或者deleteAll(root))。 deleteAll(n-&gt;right) 将在 deleteAll(n-&gt;left) 返回后被调用。 deleteAll 的 post 条件是 n 和它的所有子节点都将被删除。

    假设我们有以下树:

        a
       / \
       b c
      /   \
     d     e
    

    调用图如下:

    deleteAll(a)
        deleteAll(a->left)
            deleteAll(a->left->left)
                deleteAll(a->left->left->left)
                deleteAll(a->left->left->right)
            deleteAll(a->left->right)
        deleteAll(a->right)
            deleteAll(a->right->left)
            deleteAll(a->right->right)
                deleteAll(a->right->right->left)
                deleteAll(a->right->right->right)
    

    或者就节点名称而言:

    deleteAll(a)
        deleteAll(b)
            deleteAll(d)
                deleteAll(NULL)
                deleteAll(NULL)
            deleteAll(NULL)
        deleteAll(c)
            deleteAll(NULL)
            deleteAll(e)
                deleteAll(NULL)
                deleteAll(NULL)
    

    【讨论】:

    • @MooingDuck 哇,谢谢你的收获。哇,我第一次搞砸了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-09
    • 2011-09-08
    • 1970-01-01
    • 2018-02-25
    相关资源
    最近更新 更多