使用恒定空间和 O(n) 运行时间编写二叉搜索树的非递归遍历
这不是作业,这是一道面试题。
这里的要点是算法应该是常数空间。 我对如何在没有堆栈的情况下做到这一点一无所知,我会发布我使用堆栈编写的内容,但无论如何它都不相关。
这是我尝试过的:我尝试进行预序遍历,并且到达了最左边的节点,但我被困在那里。我不知道如何在没有堆栈/父指针的情况下“递归”备份。
任何帮助将不胜感激。
(我将其标记为 Java,因为这是我使用起来很舒服的方式,但很明显,它与语言无关。)
This is not homework, this is an interview question.
The catch here is that the algorithm should be constant space.
I'm pretty clueless on how to do this without a stack, I'd post what I've written using a stack, but it's not relevant anyway.
Here's what I've tried: I attempted to do a pre-order traversal and I got to the left-most node, but I'm stuck there. I don't know how to "recurse" back up without a stack/parent pointer.
Any help would be appreciated.
(I'm tagging it as Java since that's what I'm comfortable using, but it's pretty language agnostic as is apparent.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
Morris中序树遍历怎么样?它基于线程树的概念,它修改树,但在完成后将其恢复回来。
链接:http://geeksforgeeks.org/?p=6358
不使用任何额外空间。
How about Morris Inorder tree traversal? Its based on the notion of threaded trees and it modifies the tree, but reverts it back when its done.
Linkie: http://geeksforgeeks.org/?p=6358
Doesn't use any extra space.
我没有完全考虑清楚,但我认为只要你愿意在这个过程中弄乱你的树,这是可能的。
每个 Node 有 2 个指针,因此可以用来表示双向链表。假设您从 Root 前进到 Root.Left=Current。现在Root.Left指针没有用处,因此将其分配给Current.Right并继续到Current.Left。当您到达最左边的子节点时,您将拥有一个链表,其中的树悬挂在某些节点上。现在迭代它,对你在编辑时遇到的每棵树重复这个过程
:仔细考虑一下。这是按顺序打印的算法:
I didn't think it through entirely, but i think it's possible as long as you're willing to mess up your tree in the process.
Every Node has 2 pointers, so it could be used to represent a doubly-linked list. Suppose you advance from Root to Root.Left=Current. Now Root.Left pointer is useless, so assign it to be Current.Right and proceed to Current.Left. By the time you reach leftmost child, you'll have a linked list with trees hanging off of some nodes. Now iterate over that, repeating the process for every tree you encounter as you go
EDIT: thought it through. Here's the algorithm that prints in-order:
如果您使用基于向下指针的树并且没有父指针或其他内存,则不可能在常量空间中遍历。
如果您的二叉树位于数组中而不是基于指针的对象结构中,则这是可能的。但是这样你就可以直接访问任何节点。这是一种作弊;-)
If you are using a downwards pointer based tree and don't have a parent pointer or some other memory it is impossible to traverse in constant space.
It is possible if your binary tree is in an array instead of a pointer-based object structure. But then you can access any node directly. Which is a kind of cheating ;-)
这是 iluxa 的简短版本原始答案。
它以完全相同的顺序运行完全相同的节点操作和打印步骤 - 但以简化的方式 [1]:
[1]
另外,当树根节点没有左子节点时它甚至可以工作。
Here's a shorter version iluxa's original answer.
It runs exactly the same node manipulation and printing steps, in exactly the same order — but in a simplified manner [1]:
[1]
Plus, it even works when the tree root node has no left child.
它是一个搜索树,所以你总是可以得到下一个键/条目
你需要类似的东西(我没有测试代码,但它很简单)
为了清楚起见,这是
higherEntry
,所以它不是递归的。给你了:)It's a a search tree, so you can always get the next key/entry
You need smth like (I didn't test the code, but it's as simple as it gets)
for clarity this is
higherEntry
, so it's not recursive. There you have it :)问题的标题没有提到节点中缺少“父”指针。虽然 BST 不一定需要它,但许多二叉树实现确实有一个父指针。
类节点{
节点*左;
节点*右;
节点*父节点;
数据数据;
};
在这种情况下,在纸上画出树的图,然后用铅笔在树周围从边缘的两侧向上和向下绘制(向下时,您将在边缘的左侧,并且上升时,您将位于右侧)。基本上有4种状态:
The title of the question doesn't mention the lack of a "parent" pointer in the node. Although it isn't necessarily required for BST, many binary tree implementations do have a parent pointer.
class Node {
Node* left;
Node* right;
Node* parent;
DATA data;
};
It this is the case, imaging a diagram of the tree on paper, and draw with a pencil around the tree, going up and down, from both sides of the edges (when going down, you'll be left of the edge, and when going up, you'll be on the right side). Basically, there are 4 states:
我们可以遍历二叉树而不修改树本身(前提是节点有父指针)。并且可以在恒定的空间内完成。我发现这个有用的链接相同
http:// tech.technoflirt.com/2011/03/04/non-recursive-tree-traversal-in-on-using-constant-space/
We can traverse the binary tree without modifying the tree itself (provided nodes have parent pointer). And it can be done in constant space. I found this useful link for the same
http://tech.technoflirt.com/2011/03/04/non-recursive-tree-traversal-in-on-using-constant-space/
接受的答案需要进行以下更改,否则它将不会打印 BST 只有一个节点的树
Accepted answer needs the following change otherwise it will not print the tree where the BST only has one node
上面 iluxa 的答案的小特例
minor special case for iluxa's answer above
它是一个二叉搜索树,因此每个节点都可以通过一系列右/左决策来到达。将该系列描述为 0/1,从最低有效位到最高有效位。所以函数f(0)的意思是“取右手边的分支,直到找到叶子为止所找到的节点;f(1)的意思是向左取一个,向右取一个;f(2)——即二进制010—— - 表示向右,然后向左,然后向右,直到找到一个叶子,从 n=0 开始迭代 f(n),直到找到每个叶子。效率不高(因为您必须从树的顶部开始)。时间)但恒定的记忆和线性时间。
It's a binary search tree, so every node can be reached by a series of right/left decision. Describe that series as 0/1, least-significant bit to most-significant. So the function f(0) means "the node found by taking the right-hand branch until you find a leaf; f(1) means take one left and the rest right; f(2) -- that is, binary 010 -- means take a right, then a left, then rights until you find a leaf. Iterate f(n) starting at n=0 until you have hit every leaf. Not efficient (since you have to start at the top of the tree each time) but constant memory and linear time.