惯用遍历二叉树(可能是任何树)

时间:2014-11-13 15:50:58

标签: algorithm binary-tree tree-traversal

双向链接列表可以实现链接列表的惯用遍历,我想为什么不能使用二叉树?传统上,二进制树或树一般是单向的,这意味着,给定一个具有足够数量节点的大树,找到叶节点的运行时间可能是昂贵的。

如果找到这样一个节点后,找到下一个我可以将树遍历回根,那么与通过树的每个节点的另一个深度优先搜索相比,这是不是有利的吗?我之前从未考虑过这一点,直到认识到双重链表和二叉树的结合可能会增加利益。

例如,如果我使用内部类

class Tree<T> {

      private class TwoWayNode {

           var data     : T
           var left     : TwoWayNode
           var right    : TwoWayNode
           var previous : TwoWayNode
      }
}

左和右的使用与从每个节点遍历各个子树一样正常,并且之前将保持指向父节点启用惯用遍历的指针。像这样的人会很好地工作,有什么潜在的问题或陷阱吗?

2 个答案:

答案 0 :(得分:1)

鉴于您存储了previous引用,您可以先走最左边。到达叶子节点后​​,再次向上移动,向右移动。

您始终可以将当前节点,您的&#34; walker&#34;与子节点进行比较,以便检查您是否 left 或< em>对最后一次。这使你的遍历无状态,你甚至不需要递归;适用于非常大的数据集。

现在,每次你离开右边的叶子,你都会再次向后退一个。

此算法是Depth-First-Search。 *

加快速度: 鉴于您可以为遍历顺序定义一些确定性条件,这可以变得非常灵活,甚至可以用于光线跟踪等应用程序。


* http://en.wikipedia.org/wiki/Depth-first_search

Bonus:本文介绍了光线跟踪中Kd树的遍历算法:评论:光线跟踪的Kd树遍历算法http://dcgi.felk.cvut.cz/home/havran/ARTICLES)/cgf2011.pdf

答案 1 :(得分:0)

实际上,二叉树的节点通常使用指向 left right 子节点以及 parent 的指针来实现(请参阅{{3}红黑树)。

但你并不总是需要一个父指针:

  • 对于inorder-traversal,您可以使用递归算法,以便调用堆栈为您处理。
  • 如果您想访问 min max 节点,您只需维护一个指向它们的额外指针。
  • 有时您可以使用this implementation
  • 或者更聪明地组织你的指针(参见finger tree第666页):
    • 节点的左指针指向第一个(左)孩子
    • 节点的右指针指向同级(如果是左子)或返回父级(如果是右子)

超酷: Self adjusting binary search trees二进制搜索树,以便在没有堆栈的情况下遍历,从而更轻松地进行顺序(和反向顺序) - 所以O(1)空间! < / p>