有限的空间迭代器
我已经实现了一棵树(不是二进制树,每个节点都有几个子节点)。对于每个节点,我们都可以在树,孩子和父节点中访问其水平。
下一阶段是为这棵树实现2个迭代器,但捕获是我不能节省超过恒定数量的信息来帮助完成这些迭代器(即恒定的空间复杂性)。
我的问题是我目前处于的一个节点n:
- 在BFS顺序中找到下一个遍历的节点是什么算法?
- 在 *反向BFS顺序中找到下一个遍历的节点是什么算法?
*注意:
反向BFS正在以相反顺序横穿水平,例如以下树的反向BF
1
/ | \
2 3 4
/ / \ \
5 6 7 8
为5 6 7 8,然后2 3 4,然后是1。
I've implemented a tree (not a binary tree, every node can have several child nodes). For every node, we can access its level in the tree, its children and its parent node.
The next phase is to implement 2 iterators for this tree but the catch is I can not save more than a constant amount of information to help complete these iterators (i.e constant space complexity).
My questions are, given a node n that I'm currently at:
- What would be the algorithm to find the next node to traverse in a BFS order?
- What would be the algorithm to find the next node to traverse in a *Reverse BFS order?
*Note:
Reverse BFS is traversing the levels in reverse order e.g Reverse BFS of the following tree
1
/ | \
2 3 4
/ / \ \
5 6 7 8
would be 5 6 7 8 then 2 3 4 and then 1.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是算法的草图。效率低下,但满足您仅使用O(1)额外空间的要求。
node* goright(node* c)
如果
c
是root(没有父母),请返回null
令
p
为c
的父母。立即在c
的右边找到其子女r
(可能需要对p
的子女链接进行线性搜索)。如果找到,返回r
如果找不到(
c
是最正确的孩子),setc = p
,从一开始就重复。因此,发现的节点可能比我们开始的节点更高。
节点* godowntolevel(node* p,int k)
如果
p
是null
,返回null
如果
p
在级别k
,返回p
。从
p
开始,请按照左侧的儿童链接向下链接,直到达到级别k
或无需链接。令c
为因此找到的节点。如果c
在级别k
,返回c
。否则,
c
是k
上方的级别节点。 SETP = Goright(C)
,从开始时重复。node* nextAtlevel(node* c,int k)
返回
godowntolevel(goright(c),k)
node* nextinbfsorder(node* c)
令
k
为c
的级别。令r = nextAtlevel(c,k)
。如果r
不是null
,返回r
。否则,将父链一直穿过根,返回
godowntolevel(root,k+1)
。另外,root
可以存储在迭代器中。另外,迭代器可以跟踪它在遍历级别k
时遇到的第一个非叶节点的最左边的孩子,然后跳到该孩子,一旦NextAtlevel
失败;这个孩子在级别开始迭代k+1
。反向BF会类似地工作。困难的部分是找到启动遍历的节点。基本上,执行
godowntolevel(root,infinity)
,同时跟踪遇到的最深层次,并在该级别遇到的第一个节点。当然,dogodowntolevel(root,k-1)
而不是godownTolevel(root,k+1)
nextAtlevel
失败。如果您在建造树时跟踪
h
,则可以使用godowntolevel(root,h)
启动遍历Here's a sketch of the algorithm. Very inefficient, but satisfies your requirement of only using O(1) additional space.
Node* GoRight(Node* c)
If
c
is root (there's no parent), returnNULL
Let
p
be the parent ofc
. Find its childr
immediately to the right ofc
(may need to do a linear search ofp
's child links). If found, returnr
If not found (
c
is the right-most child), setc=p
, repeat from the start.The node thus found may be at a higher level than the node we started with.
Node* GoDownToLevel(Node* p, int k)
If
p
isNULL
, returnNULL
If
p
is at levelk
, returnp
.Starting from
p
, follow the left-most child links down until levelk
is reached or there are no links to follow. Letc
be the node thus found. Ifc
is at levelk
, returnc
.Otherwise,
c
is a leaf node at a level abovek
. Setp = GoRight(c)
, repeat from the start.Node* NextAtLevel(Node* c, int k)
Return
GoDownToLevel(GoRight(c), k)
Node* NextInBFSOrder(Node* c)
Let
k
be the level ofc
. Letr = NextAtLevel(c, k)
. Ifr
is notNULL
, returnr
.Otherwise, traverse the parent chain all the way to the root, return
GoDownToLevel(root, k+1)
. Alternatively,root
could be stored in the iterator. Alternatively, the iterator could keep track of the leftmost child of the first non-leaf node it encountered while traversing levelk
, and jump to that child onceNextAtLevel
fails; this child starts the iteration at levelk+1
.Reverse BFS would work similarly. The hard part is finding the node to start the traversal from. Basically, perform
GoDownToLevel(root, infinity)
while keeping track of the deepest level encountered and the first node encountered at that level. And of course, doGoDownToLevel(root, k-1)
instead ofGoDownToLevel(root, k+1)
whenNextAtLevel
fails.If you keep track of the height
h
of the tree while its being built, then you can start the traversal withGoDownToLevel(root, h)
我假设您可以弄清楚如何进行树的预订遍历:先扎根,然后再去第一个孩子,直到您没有孩子碰到节点。然后去找父母,然后在您来自一个孩子之后找到下一个孩子。如果这是最后一个孩子与新父母重复。
一次这样做以找出树的最深节点,或者使树存储的最大深度。然后,再做一个深度的第一个孩子。您的迭代器是那个深度和孩子的地址。
要增加迭代器,请继续对孩子进行预订遍历,然后跳过所有节点,其中
node-> depth!= depth
。每次遍历饰面都会减小深度。当深度变为负返回end()
时。注意:在预订遍历中,您可以在
node-> depth == depth
时跳到孩子身上,直接回到父母身上。I assume you can figure out how to do an pre-order traversal of the tree: Take the root first, then go to the first child till you hit a node with no children. Then go to the parent and find the next child after the one you came from. If it was the last child repeat with the new parent.
Do this once to find out the deepest node of the tree, or have the tree store its max depth. Then do it again stopping at the first child with that depth. Your iterator is that depth and the address of the child.
To increment the iterator keep doing pre-order traversal on the child and skip all the nodes where
node->depth != depth
. Each time the traversal finishes decrement depth. When depth becomes negative returnend()
.Note: in the pre-order traversal you can skip going down to children when
node->depth == depth
, go straight back to parent.