【问题标题】:How to get all parents for all leaves in a tree quickly?如何快速获得树上所有叶子的所有父母?
【发布时间】:2012-08-29 21:25:06
【问题描述】:

我有一个可能很大的根树结构,我想将其转换为X * Y 矩阵,其中X 是树中的叶子数量,Y 是树中节点的数量,度数更大大于1,即根节点和内部节点。矩阵应该这样填充:

Mi,j = { 0 如果叶 i 有祖先 j,否则为 1

例如,这棵树:

      --A 
     /
    1   B
   / \ /
  /   3  
 /     \
0       C
 \ 
  \   --D
   \ /
    2
     \--E

将转化为这个矩阵:

  0 1 2 3
A T T F F
B T T F T
C T T F T
D T F T F
E T F T F

由于树可能会变得非常大(可能约为 100,000 片叶子),我想知道是否有比遍历每个叶子节点的树更智能/更快的方法。感觉好像某种算法存在于这个问题的某个地方,但我还没有弄清楚。也许有人可以帮忙?

在我的应用程序中,树代表大phylogenetic hierarchies,所以它不平衡,可能有两个以上的子节点。

【问题讨论】:

  • 我认为这里最大的问题是矩阵本身 - 一个微不足道的改进是只存储每个叶子的祖先列表 - 但即使那样你仍然不能更快(至少在big-O 术语)而不是遍历所有祖先,因为无论如何您都必须将它们添加到列表中。您或许应该考虑一下您将如何使用这些数据,以及是否真的需要明确存储所有这些数据,然后可能会出现更好的结果。
  • 不幸的是,我必须使用矩阵数据结构,因为在我看不到如何合并祖先列表的进一步步骤中,我需要它作为输入。不过,感谢您指出这一点!

标签: algorithm data-structures tree graph-algorithm


【解决方案1】:

我会选择后序遍历。

在遍历树时维护叶子列表,并且在每个级别中 - 该列表将包含直到该级别的所有叶子。

我们将使用的函数的声明:

list merge(list1,list2) //merges two lists and creates a new list
list create() // creates a new empty list
void add(list,e) // appends e to the list
void setParent(leaf,node) //sets (in your matrix) node as a parent of leaf

伪代码:

list Traverse(root):
  if (root == nil):
      l <- create()
      return l
  else if (root is leaf):
      l <- create()
      add(l,root)
      return l
  else: 
      l1 <- Traverse(root.left)
      l2 <- Traverse(root.right)
      l <- merge(l1,l2)
      for each leaf in l:
          setParent(leaf,root)
      return l

时间是O(n*m) - 用于设置矩阵(尽管算法本身是O(nlogn) 时间用于平衡树)。

如果你想阻止O(n*m)初始化你可以initialize the matrix in O(1),然后在O(nlogn)运行上面的算法。虽然它会提供更好的渐近复杂性,但我怀疑它实际上会更快。

【讨论】:

  • 谢谢!我在午休期间想出了类似的东西(对输出矩阵的列使用布尔运算,基本上使用相同的遍历策略),但你的可能是更快、更通用的解决方案。
猜你喜欢
  • 1970-01-01
  • 2019-10-14
  • 1970-01-01
  • 2012-10-09
  • 2015-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多