【问题标题】:Total number of nodes in a tree data structure?树数据结构中的节点总数?
【发布时间】:2010-10-05 15:19:59
【问题描述】:

我有一个深度为 L 级的树数据结构,每个节点有 大约 N 个节点。我想计算出树中节点的总数。要做到这一点(我认为),我需要知道有多少百分比的节点会有孩子。

N 中叶节点与非叶节点的比例的正确术语是什么?

三个节点总数的计算公式是什么?

更新有人在其中一个答案中提到了Branching factor,但随后就消失了。我想这是我一直在寻找的术语。那么公式不应该考虑分支因素吗?

更新我应该说的是对假设数据结构的估计,而不是确切的数字!

【问题讨论】:

  • 我取出了分支因子,因为那是您所说的 N 的术语。然后我意识到您正在寻找叶节点与内部节点的比率。

标签: data-structures tree


【解决方案1】:

好的,每个节点大约有 N 个子节点,树的深度为 L 级。

With 1 level, the tree has 1 node.
With 2 levels, the tree has 1 + N nodes.
With 3 levels, the tree has 1 + N + N^2 nodes.
With L levels, the tree has 1 + N + N^2 + ... + N^(L-1) nodes.

节点总数为 (N^L-1) / (N-1)。

好的,只是一个小例子,为什么它是指数的:

                    [NODE]
                      |
                     /|\
                    / | \
                   /  |  \
                  /   |   \
            [NODE]  [NODE] [NODE]
              |
             /|\
            / | \

【讨论】:

  • 需要更正:[..] 并且树的深度为 L(为 N)级。无论如何+1 :)
  • +1,但是拼出代数来说明为什么 1+N+N^2+...+N^L = (N^L-1)/(N -1)。
  • 编辑:我做了 Andrea Ambu 的建议更改,还修正了一个错字。
  • 事实上你对方程的解有点偏离——它应该是简单的 (N^L)-1 (想象一下如果 N 是 2 并且 L 是 3——总和是 1+2+4 =7=(2^3)-1)。这可以通过归纳很容易地证明。
  • @HenryR:我独立推导出了 Gamecat 的公式。如果 N=2,那么您提出的答案也是正确的,因为在这种情况下除以 (N-1) 不会改变任何内容。当 N>2 时,您需要执行除法以获得正确答案。
【解决方案2】:

只是为了纠正第一个答案中的错字:深度为 L 的树的节点总数为 (N^(L+1)-1) / (N-1)...(即幂 L+1 而不仅仅是 L)。

这可以如下所示。首先,采用我们的定理:

1 + N^1 + N^2 + ... + N^L = (N^(L+1)-1)/(N-1)

两边乘以(N-1):

(N-1)(1 + N^1 + N^2 + ... + N^L) = N^(L+1)-1。

展开左侧:

N^1 + N^2 + N^3 + ... + N^(L+1) - 1 - N^1 - N^2 - ... - N^L。

所有项 N^1 到 N^L 都被取消,剩下 N^(L+1) - 1。这是我们的右手边,所以初始相等是正确的。

【讨论】:

  • 这对于非二叉树是不正确的。例如,如果每个节点有 8 个孩子。 8^2-1 = 63. 深度为 1
  • @aDev 您忘记除以 (N-1) 或在这种情况下为 7,这将导致最终答案为 9,这对于 N=8、L=1 是正确的。
【解决方案3】:

如果你的树大约满,也就是说,除了最后两个之外,每个级别都有完整的子级,那么你有 N^(L-2) 和 N^(L- 1)叶子节点和N^(L-1)和N^L节点之间的总数。

如果你的树没有满,那么知道叶子节点的数量并没有帮助,因为一棵完全不平衡的树将有一个叶子节点但任意多个父节点。

我想知道你的陈述“每个节点大约有 N 个节点”有多精确 - 如果你知道平均分支因子,也许你可以计算出树的预期大小。

如果您能够找到叶子与内部节点的比率,并且您知道平均子节点数,则可以将其近似为 (n*ratio)^N = n。这不会给你答案,但我想知道是否有比我数学更好的人想办法将 L 插入这个方程并给你一些可解的东西。

不过,如果您想准确地知道,您必须遍历树的结构并随时计算节点数。

【讨论】:

    【解决方案4】:

    深度L的节点数计算公式为:(假设有N个根节点)

    NL

    要计算所有节点的数量,需要对每一层执行此操作:

    for depth in (1..L)
        nodeCount += N ** depth
    

    如果只有 1 个根节点,则从 L 中减去 1,并将总节点数加 1。

    请注意,如果在一个节点中的叶子数量与平均情况不同,这可能会对您的数量产生很大影响。树的位置越靠前,影响越大。

    * * * N ** 1 *** *** *** N ** 2 *** *** *** *** *** *** *** *** *** N ** 3

    这是社区 wiki,因此请随意更改我令人震惊的代数。

    【讨论】:

    • “从N个节点开始”是什么意思?
    • @gs:树的第一层有N个节点,而不是1个。相应更新。
    • 你是对的,虽然实际上你在那个循环中计算的总和结果可以用一个简单的公式来表达,在 GameCat 的回答中给出。
    【解决方案5】:

    Knuth 的估计器 [1],[2] 是一个point estimate,它以任意有限树中的节点数为目标,无需遍历所有节点,即使树不平衡。 Knuth 的估计器是无偏估计器的一个例子; Knuth 估计器的期望值将是树中的节点数。话虽如此,如果所讨论的树不平衡,Knuth 的估计量可能会有很大的差异,但在你的情况下,由于每个节点都会有大约 N 个子节点,我认为 Knuth 的估计量的方差应该不会太大。当您尝试测量执行蛮力搜索所需的时间时,此估算器特别有用。

    对于以下函数,我们将假设所有树都表示为列表的列表。 例如,[] 表示具有单个节点的树,[[],[[],[]]] 将表示具有 5 个节点和 3 个叶子的树(树中的节点与左括号一一对应)。以下函数是用 GAP 语言编写的。

    函数simpleestimate 给出一个输出,估计树tree 中的节点数。 simpleestimate 背后的想法是我们随机选择从树的根 x_0 到叶子 x_n 的路径 x_0,x_1,...,x_n。假设 x_i 有 a_i 个后继者。然后simpleestimate 将返回 1+a_1+a_1*a_2+...+a_1*a_2*...*a_n。

    point:=tree; prod:=1; count:=1; list:=[]; 
    while Length(point)>0 do prod:=prod*Length(point); count:=count+prod; point:=Random(point); od;
    return count; end;
    

    函数estimate 将简单地给出通过多次应用函数simpleestimate(tree) samplesize 给出的估计值的算术平均值。

    estimate:=function(samplesize,tree) local count,i; 
    count:=0; 
    for i in [1..samplesize] do count:=count+simpleestimate(tree); od; 
    return Float(count/samplesize); end;
    

    示例: simpleestimate([[[],[[],[]]],[[[],[]],[]]]); 返回 15 而 estimate(10000,[[[],[[],[]]],[[[],[]],[]]]); 返回 10.9608 (树实际上有 11 个节点)。

    1. 估计搜索树大小。 http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.129.5569&rep=rep1&type=pdf

    2. 估计回溯程序的效率。唐纳德·E·克努斯 http://www.ams.org/journals/mcom/1975-29-129/S0025-5718-1975-0373371-6/S0025-5718-1975-0373371-6.pdf

    【讨论】:

      【解决方案6】:

      如果您只知道树的深度,那么计算总大小的唯一选择就是遍历并计算它们。

      【讨论】:

      • 实际上他也知道每个节点的平均或预期子节点数。这加上树的高度足以计算出树中节点的平均数或预期数。
      • 是的,那是我的错误——我读到这个问题是因为需要知道树的确切大小。
      猜你喜欢
      • 1970-01-01
      • 2011-05-15
      • 1970-01-01
      • 2015-05-15
      • 2012-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-02
      相关资源
      最近更新 更多