有效地找到树节点的深刻标记的子节点

时间:2012-02-27 00:38:01

标签: performance algorithm tree computer-science children

给定(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*

4 个答案:

答案 0 :(得分:2)

原则上,您需要在步行树和存储标记值列表之间进行权衡。你提到了两个极端,我将在下面给你一个例子,它位于它们之间的中间位置。

想到的一个想法是在每个标记的节点上存储标记子节点的下一个“层”,这应该在存储和时间之间提供非常均衡的混合,因此在您的示例中它不会节省太多,但是例如如果你有

        A
       / \
      B*  C
     / \   \
    D*  E   F
   / \   \   \
  G   H*  I*  J*
 /   / \
K   L   M

您可以将D,I BH中的D以及H,I,J中的“空”标记存储起来。

要获取节点的列表,您只需要走到每个分支到达标记节点,例如,要获取A的列表,您必须从A->B步行A->C->F->J,然后B会给你I,DD会给你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)

你必须至少走一次树。没有比这更快的方法了。你不想存储它们,所以你每次都要重新走它们。