【问题标题】:Tree Traversal and Recursion Conceptual Question树遍历和递归概念问题
【发布时间】:2021-11-03 02:31:55
【问题描述】:

对于大小为 N 的问题的许多递归解决方案都遵循这种模式:

第 1 步:求解最小输入的问题(例如,n = 1)

第 2 步:给定大小为 n = k-1 (k

我们可以看到它的归纳性质,这就是为什么我们通常使用归纳来证明递归算法。对于某些问题,例如递归斐波那契,这种模式以一种明显的方式出现。我的问题是,比如说,二叉树遍历是否也可以被视为遵循这种模式?

以深度优先搜索为例:

def DFS(root):

  if root == None:
    return
  print(root.value)
  DFS(root.left)
  DFS(root.right)

我了解代码和调用堆栈,但我很难准确地阐明 DFS 的第 1 步和第 2 步是什么(保持上述递归解决方案的结构)。不可能只有当当前节点为None时才是base case,因为遍历单个节点也应该是base case。

如果我说第 4 行,即包含 print 语句的那一行,是一个基本情况,它没有多大意义,因为它针对每个子树运行。

【问题讨论】:

  • 如果我没记错的话,这看起来更像是预购遍历而不是 DFS……?无论如何,单个节点如何成为基本案例?只有root == None 是所示算法中的基本情况。这里有一个(叶)节点,您仍然可以递归并访问它的子节点,即使它们是None。试图对此应用归纳似乎有点想多了。我不确定它到底能带来什么好处。
  • @ggorlen 没错,这只是没有搜索的预购遍历。对我来说,这样做的好处是将两个概念联系在一起并获得更深入的理解。此外,有时在思考“这个问题的最简单版本是什么?”和“我将如何从一个小问题的解决方案到一个更大的问题”有助于设计算法......我觉得我不能将这些步骤应用于树遍历问题,所以我倾向于与他们斗争。
  • 对,但在这种情况下,本身并没有真正需要解决的问题——所发生的只是打印,因此没有结果或数据在树中移动。如果它们存在,您只需访问节点,打印,这就是它的全部内容。像这样的基本树遍历中唯一的“技巧”/“洞察力”是打印(或通用访问代码)去哪里产生不同的排序?

标签: recursion tree binary-search-tree tree-traversal induction


【解决方案1】:

它遵循相同的模式。

要解决的“问题”是以正确的顺序打印树。您的代码实现了预购。

第 1 步:求解最小输入的问题(例如,n = 1)

这里最小的问题是打印一棵空树(root is None)。在这种情况下,解决方案是什么都不打印(只打印return)。

第 2 步:给定大小为 n = k-1 (k

我们可以认为k 表示当前树中的节点数,n 表示这棵树的直接子树中的节点数。打印左子树或右子树是一个较小的问题,其中n <= k-1(注意<=)。

打印树(预先排序),包括打印根节点,然后解决左右子树的“问题”。


一个区别是树的输出是这个函数的“副作用”——它不返回结果,而是输出它。这意味着进行递归调用的人不需要取回结果即可使用。更纯粹的函数会返回树的字符串表示形式,调用者将使用它与正在构建的字符串串联,并将其返回给自己的调用者。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-12
    • 2014-03-11
    • 1970-01-01
    • 2020-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多