📜  构建堆的时间复杂度

📅  最后修改于: 2021-10-28 02:11:20             🧑  作者: 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)到 root(1) 的索引(高度 = lg(n))。因此, Heapify为每个节点花费不同的时间,即O(h) .

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

现在为了推导出时间复杂度,我们将构建堆的总成本表示为-

(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

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程