给定(m-way)树T:
A
/ \
B C
/ \ \
D* E* F
/ \ \ \
G H* I J*
使用标记的节点D *,E * H *和J *,可以快速检索给定节点下所有标记的子节点,除了遍历所有子树或存储所有标记的子节点对于每个节点?即:
B -> D*, E*, H*
C -> J*
A -> D*, E*, H*, J*
答案 0 :(得分:2)
原则上,您需要在步行树和存储标记值列表之间进行权衡。你提到了两个极端,我将在下面给你一个例子,它位于它们之间的中间位置。
想到的一个想法是在每个标记的节点上存储标记子节点的下一个“层”,这应该在存储和时间之间提供非常均衡的混合,因此在您的示例中它不会节省太多,但是例如如果你有
A
/ \
B* C
/ \ \
D* E F
/ \ \ \
G H* I* J*
/ / \
K L M
您可以将D,I
B
和H
中的D
以及H,I,J
中的“空”标记存储起来。
要获取节点的列表,您只需要走到每个分支到达标记节点,例如,要获取A
的列表,您必须从A->B
步行A->C->F->J
,然后B
会给你I,D
,D
会给你H
。
您还可以将其视为仅在原始树旁边存储标记节点的树,在本例中为两棵树
B J
/ \
D I
|
H
根据标记节点的分布情况,您可以为应用程序优化此想法。
答案 1 :(得分:1)
如果你自下而上,你可以访问树的很小一部分。
此算法可以在最小空间中表示树:即只是结构的向量,除了“父节点”索引和“标记标志”(根用于-1)之外的完整有效负载
for each node
if marked && given parent in parents'chain
ok, save (for instance) the index
endif
next
IMO,根据数据分布统计,我觉得这可能很有效。
答案 2 :(得分:1)
当且仅当根节点中的标记节点存在于当前节点中时,才能在每个节点(boolean
)中存储一位(或true
)。更新树时,此标签易于维护,并允许您在递归和迭代算法中轻松跳过不感兴趣的子树。但是,您必须遍历标记节点的路径上的所有节点。
确保访问零开销但又难以维护的另一个想法是:让每个标记的节点都有第二对子指针。通过这些,您可以存储标记节点的树,而只需很少的存储空间。您甚至可以通过这种方式对标记进行编码;当且仅当这些指针中的至少一个不是null
时,才标记节点。必须以特殊的方式对待根。
答案 3 :(得分:0)
你必须至少走一次树。没有比这更快的方法了。你不想存储它们,所以你每次都要重新走它们。