📜  建立堆的时间复杂度

📅  最后修改于: 2021-05-08 19:01:53             🧑  作者: Mango

考虑以下用于构建输入数组A的堆的算法。

BUILD-HEAP(A) 
    heapsize := size(A); 
    for i := floor(heapsize/2) downto 1 
        do HEAPIFY(A, i); 
    end for 
END

快速浏览以上算法,表明运行时间为O(nlg(n)) ,因为每次致电Heapify都会产生费用O(lg(n)) Build-Heap使O(n)这样的电话。
这个上限虽然正确,但不是渐近严格的。

通过观察Heapify的运行时间取决于树的高度“ h”(等于lg(n),其中n是节点数),而大多数子树的高度为小的。
当我们沿着树向上移动时,高度“ h”增加。 Build-Heap的第3行从最后一个内部节点的索引(heapsize / 2)(高度= 1)到根(1)的索引(高度= lg(n))运行一个循环。因此, Heapify为每个节点花费不同的时间,这是O(h)

为了找到构建堆的时间复杂度,我们必须知道高度为h的节点数。
为此,我们使用一个事实,即大小为n的堆最多具有\left \lceil \frac{n}{2^{h+1}} \right \rceil 高度为h的节点。

现在,为了得出时间复杂度,我们将Build-Heap的总成本表示为-

(1)    \begin{flalign*} T(n) &= \sum_{h = 0}^{lg(n)}\left \lceil \frac{n}{2^{h+1}} \right \rceil * O(h)\\ &= O(n * \sum_{h = 0}^{lg(n)}\frac{h}{2^{h}})\\ &= O(n * \sum_{h = 0}^{\infty}\frac{h}{2^{h}})\\ \end{flalign*}

第2步使用Big-Oh表示法的属性来忽略上限函数和常数2( 2^{h+1} = 2.2^h )。类似地,在第三步中,由于我们使用的是Big-Oh表示法,因此可以将求和的上限增加到无穷大。

无限GP的总和(x <1)

(2)    \begin{align*} \sum_{n = 0}^{\infty}{x}^{n} = \frac{1}{1-x} \end{align*}

在微分两边并乘以x时,我们得到

(3)    \begin{align*} \sum_{n = 0}^{\infty}n{x}^{n} = \frac{x}{(1-x)^{2}} \end{align*}

将在(3)中获得的结果放回到我们的推导(1)中,我们得到

(4)    \begin{flalign*} &= O(n * \frac{\frac{1}{2}}{(1 - \frac{1}{2})^2})\\ &= O(n * 2)\\ &= O(n)\\ \end{flalign*}

因此证明了构建二进制堆的时间复杂度是O(n)

参考 :
http://www.cs.sfu.ca/CourseCentral/307/petra/2009/SLN_2.pdf