【问题标题】:Is it possible to iterate through a binary tree using iteration instead of recursion?是否可以使用迭代而不是递归来遍历二叉树?
【发布时间】:2014-04-30 23:23:39
【问题描述】:

在学校,当我们需要遍历一棵树(例如二叉搜索树)时,我们总是被教导递归地遍历这棵树。

既然每个recusion都可以写成迭代,那么是否可以单独使用迭代来访问树的元素?

我在 C++ 的上下文中问这个

【问题讨论】:

  • 你总是可以用循环和堆栈替换递归。
  • 酷,谢谢。我总是难以理解递归的程序流程。
  • 我认为你必须理解它一次,之后所有的递归都会有意义。不要因为不懂就换成更复杂的东西。

标签: c++ recursion tree iteration


【解决方案1】:

是的。

对于您处理的每个节点,将子节点存储到队列中。这对同一级别中的其余节点继续进行。处理完该级别的所有节点后,您将处理排队的子节点。反过来,您将孩子的孩子存储到队列中。这种情况一直持续到你触底为止。

例如:

      D
  B       F 
A   C   E   G

// 1
Current: D
Queue: B, F

// 2
Current: B, F
Queue: A, C, E, G

// 3
Current: A, C, E, G
Queue: no more!

迭代比递归复杂得多,因为您需要实现一个队列(如果没有提供)以及一些用于不平衡树的额外逻辑。但是,迭代更加“内存友好”,因为您的队列只是一堆指向节点的指针,而递归每次调用都会占用堆栈。

【讨论】:

  • 我很高兴你说是的,因为我一直认为递归是访问树中节点的唯一方法,这种误解使我远离使用树结构(IMO 树实际上是一个强大的结构使用),因为我对如何使用递归并不了解。
  • @user3437460 取决于开发者,以及使用。对我来说,递归比迭代更容易实现,因为递归非常简单。但是,迭代是“内存友好的”,因为它不会占用堆栈。
  • 感谢您的回复。我可以知道,具有超过 2 个子节点的非二叉树怎么办?是否仍然可以迭代地进行?
  • @user3437460 同样适用。只需将子节点排队即可。树的迭代背后的概念是你是在“按级别”(breadth first)而不是在递归中按分支(depth first)。
  • @JosephtheDreamer:我会注意到使用队列是一个实现细节;您可以使用适当的树表示在 O(1) 空间中进行迭代。
【解决方案2】:

是的。存在一种称为树的threading 的方法,它基本上以特定的遍历顺序连接节点。因此,您可以像任何其他递归遍历一样迭代遍历整个树。

【讨论】:

    【解决方案3】:

    答案是肯定的。

    这取决于您要执行哪种遍历(Preorder、Inorder、Postorder)。如果要复制递归行为,则需要模拟堆栈递归。 它可能在一些场景中有用,但递归更简单。

    【讨论】:

      【解决方案4】:

      std::setstd::map 最常见的实现是红黑树;两者都可以只用两个迭代器进行迭代(通过调用beginend 获得);因此,不仅可以在没有递归的情况下进行迭代,甚至可以在 O(1) 空间中进行迭代,前提是树的结构正确。

      一棵树有多种表示形式:

      • 父母对孩子的访问:父母可能有一个指向第一个孩子的指针、一个指向第一个和最后一个孩子的指针或一个指向每个孩子的指针数组
      • 子级访问父级:子级可能有也可能没有指向其父级的指针
      • 兄弟访问:孩子可能有也可能没有指向其前任和继任者的指针

      一般来说,如果:

      • 孩子有一个指向其父母的指针
      • 可以访问父母的第一个孩子并知道您何时到达最后一个孩子

      然后您可以在 O(1) 空间中实现迭代;您甚至可以选择在其子代之前、中间或之后“访问”父代。

      【讨论】:

        猜你喜欢
        • 2011-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多