【问题标题】:Is there any non-recursive/stack-consuming, bottom-up binary tree traversal algorithm? [duplicate]是否有任何非递归/消耗堆栈的自下而上的二叉树遍历算法? [复制]
【发布时间】:2013-12-25 19:27:57
【问题描述】:

假设您想编写一个简单的数学归约器,例如,它将进行转换:

((add ((add 2) 3)) ((add 4) 2)) -> 11

一个简单的算法可以是(JavaScript 中的示例):

function r(a){
    if (typeof(a)!=="object") return a;
    var a = [r(a[0]), r(a[1])];
    return a[0][0]==="add" ? a[0][1] + a[1] : a;
}
console.assert(r([["add",[["add",2],3]],[["add",4],2]]) === 11);

常量栈可以解决同样的问题吗?

【问题讨论】:

  • 非递归...递归?
  • 措辞不好,我仍然不确定如何命名。
  • 是的,您可以通过在堆上使用堆栈(数据结构)使 any 递归程序迭代。
  • 我猜 OP 询问是否可以仅使用 O(1) 空间自下而上遍历树。我想,如果你有直接指向树叶的指针并且节点有指向它们父母的指针,这是可能的。我不确定是否可以使用带 O(1) 空间的算法构建这样的树。
  • @Viclib 你只需将一个工作指针指向根,循环while(not done){ ... } 并移动一个工作指针,检测减少条件,尽可能用值替换节点,直到done .

标签: algorithm recursion language-agnostic


【解决方案1】:

可以使用堆上的堆栈和循环来模拟任何递归算法。所以,是的,可以在单个函数调用中做到这一点。

如果您正在谈论在恒定空间(堆栈和堆)中遍历单个链接的树,那么不,你不能这样做(你必须记住你的方式备份)。

【讨论】:

  • 我支持你,但我认为最后一个陈述是错误的 - 请参阅 Morris Inorder Tree Transversal。我只是不确定如何使这个算法适应我的问题。
  • @Viclib:“Morris Inorder Tree Transversal”添加了 additional 链接结构,该结构被“single-linked tree”明确排除。
【解决方案2】:

如果您将树结构转换为zipper,则可以使用状态机对其进行遍历。它不再是简单的树,而是允许您将其设为非递归或尾递归。

【讨论】:

    【解决方案3】:

    是的,可以在不使用递归、显式维护堆栈或修改树节点的情况下对二叉树进行深度优先遍历。

    生成的算法需要 O(1) 额外空间和 O(n^2) 时间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-08
      • 2019-08-23
      • 1970-01-01
      • 1970-01-01
      • 2012-09-23
      相关资源
      最近更新 更多