使用常量空间和O(n)运行时编写二进制搜索树的非递归遍历

use*_*037 48 java binary-tree traversal tree-traversal

这不是作业,这是一个面试问题.

这里的问题是算法应该是恒定的空间.我对如何在没有堆栈的情况下做到这一点非常无能为力,我会发布我使用堆栈编写的内容,但无论如何它都不相关.

这是我尝试过的:我试图进行预订遍历,然后我到了最左边的节点,但我被困在那里.我不知道如何在没有堆栈/父指针的情况下"recurse"备份.

任何帮助,将不胜感激.

(我将它标记为Java,因为这是我很习惯使用的,但它显然是语言无关的.)

ilu*_*uxa 30

我并没有完全认为它,但我认为只要你愿意在这个过程中弄乱你的树,这是可能的.

每个节点都有2个指针,因此它可以用来表示双向链表.假设你从Root前进到Root.Left = Current.现在Root.Left指针是无用的,所以将它指定为Current.Right并继续到Current.Left.当你到达最左边的孩子时,你会有一个链表,树上挂着一些节点.现在迭代一遍,重复你遇到的每一棵树的过程

编辑:想通了.这是按顺序打印的算法:

void traverse (Node root) {
  traverse (root.left, root);
}

void traverse (Node current, Node parent) {
  while (current != null) {
    if (parent != null) {
      parent.left = current.right;
      current.right = parent;
    }

    if (current.left != null) {
      parent = current;
      current = current.left;
    } else {
      print(current);
      current = current.right;
      parent = null;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 哦,是的,这是一个好主意.它被称为指针反转,有时被垃圾收集器使用.它与Huet的拉链有关.但正如你所说,它弄乱你的树,往往违反静态类型的安全. (2认同)
  • 如果根只有一个右子树会发生什么..它永远不会进入 while 循环并且不会遍历树!... while(current != null|| parent!= null) 应该修复它imo .. (2认同)

bra*_*ter 29

Morris Inorder树遍历怎么样?它基于线程树的概念,它修改了树,但在完成后还原它.

Linkie:http://geeksforgeeks.org/?p = 6358

不使用任何额外的空间.

  • 如果有什么帮助,我在这里问了有关如何还原树的问题:http://stackoverflow.com/questions/5502916/please-explain-morris-inorder-tree-traversal-without-using-stacks-or -递归 (2认同)
  • @brainydexter良好的链接,但Morris遍历解释在O(nlogn)时间复杂度而不是O(n)时间问题. (2认同)

jmg*_*jmg 5

如果您使用基于向下指针的树并且没有父指针或其他内存,则不可能在常量空间中遍历。

如果您的二叉树位于数组中而不是基于指针的对象结构中,则这是可能的。但是这样你就可以直接访问任何节点。这是一种作弊;-)