3.2.8

3.2.8 #

解答 #

假设输入的完全二叉树结点数目为 $n$。

完全二叉树总是可以分成两部分,一个满二叉树,以及多余的结点。

于是完全二叉树中满二叉树的部分层数为 $l = \lfloor \log_2 (n+1) \rfloor$。(根结点位于第一层)

满二叉树占的结点数量为 $n_1 = 2^l -1$,多余结点数量为 $n_2=n-n_1$。

又因为深度等于层数 - 1,多余结点正好在满二叉树的下一层,因此多余结点的深度即为 $l$。

于是多余结点的深度和 $d_2 = l \times n_2$。

接下来计算满二叉树的深度和。

一个层数为 $l$ 的满二叉树,最后一层正好有 $2^{l-1}$ 个结点。

于是深度和为 $d_1 = 0 \times 1 + 1 \times 2+2 \times 4+\cdots+(l-1)2^{l-1} =\sum_{i=1}^{l-1} i2^i$。

用错位相减法,有:

$$ \begin{eqnarray*} d_1&=&1\times 2^1 + &2 \times 2^2 + \cdots + (l-1)2^{l-1} \newline 2d_1&=& &1\times 2^2 + \cdots+(l-2)2^{l-1} +(l-1)2^{l} \newline d_1-2d_1&=& 1 \times2^1+ &1 \times2^2+\cdots+1\times2^{l-1}-(l-1)2^l \newline d_1 &=&(l-1)2^l &-2^l+2 \newline &=&(l-2)2^l &+2 \end{eqnarray*} $$

于是可得总深度和: $d=d_1+d_2=l\times n_2+ (l-2)2^l+2$。

平均查找次数即为:$avgCompare=d / n + 1$ 。

代码 #

int OptCompares(int n)
{
    // 完全二叉树 = 满二叉树 + 多余结点
    // 满二叉树的层数。
    var l = (int)Math.Log(n + 1, 2);
    // 多余结点的个数。
    var extraNodes = n + 1 - (int)Math.Pow(2, l);

    var depthSum =
        extraNodes * l + (l - 2) * (int)Math.Pow(2, l) + 2;
    return depthSum / n + 1;
}