def heapify(A):
    for root in xrange(len(A)//2-1, -1, -1):
        rootVal = A[root]
        child = 2*root+1
        while child < len(A):
            if child+1 < len(A) and A[child] > A[child+1]:
                child += 1
            if rootVal <= A[child]:
                break
            A[child], A[(child-1)//2] = A[(child-1)//2], A[child]
            child = child *2 + 1

这是python heapq的类似实现.heapify().文档中说这个函数在O(n)中运行.但对于n/2个元素,它会记录(n)个操作.为什么是O(n)?

推荐答案

这需要更仔细的分析,比如你会发现.基本观点是,只有堆的根实际上具有深度log2(len(a)).在叶子上方的一个 node 上——有一半的 node 位于该 node 上——在第一次内部循环迭代中,一片叶子被击中.

"精确"推导

挥舞双手,当算法在一个包含N个元素的子树的根 node 上查看 node 时,每个子树中大约有N/2个元素,然后需要与log(N)成比例的功才能将根和这些子堆合并到一个堆中.所以总共需要T(N)个小时

T(N) = 2*T(N/2) + O(log(N))

这是一种罕见的复发.不过,Akra–Bazzi method可以用来推断它是O(N).

我认为,从零开始推导出一个精确的解决方案更能提供信息,当然也更令人满意.为此,我将只讨论完整的二叉树:在每个级别上尽可能完整.然后总共有2**N - 1个元素,所有子树也是完整的二叉树.这回避了一大堆毫无意义的细节,比如当事情不完全平衡时如何处理.

当我们看一个包含2**k - 1个元素的子树时,它的两个子树每个元素正好有2**(k-1) - 1个元素,有k个级别.例如,对于包含7个元素的树,根上有1个元素,第二层有2个元素,第三层有4个元素.子树重设后,根必须移动到位,将其向下移动0、1或2级.这需要在0级和1级之间进行比较,也可能在1级和2级之间进行比较(如果根需要向下移动),但仅此而已:所需的功与k-1成正比.总之,

T(2**k - 1) = 2 * T(2**(k-1) - 1) + (k - 1)*C

对于某些常数C,边界是比较两个相邻级别上的元素的最坏情况.

T(1)美元怎么样?那是免费的!一棵只有一个元素的树已经是一个堆了——没什么可做的.

T(1) = 0

在这些叶子之上一层,树木有三种元素.将最小的(对于最小堆;对于最大堆)移动到顶部需要(不超过)C美元.

T(3) = C

一级以上的树有7个元素.对每个子树进行重分类需要花费T(3)美元,然后将根移动到位不超过2*C美元:

T(7) = 2*C + 2*C = 4*C

继续以同样的方式:

T(15) = 2* 4*C + 3*C = 11*C
T(31) = 2*11*C + 4*C = 26*C
T(63) = 2*26*C + 5*C = 57*C
...
T(2**k - 1) = (2**k - k - 1)*C

最后一行是对一般形式的猜测.你可以验证"它适用于"之前的所有特定行,然后用归纳法证明它很简单.

那么,N = 2**k - 1

T(N) = (N - log2(N+1)) * C

这表明T(N)C*N为界,当然O(N)也是.

Python-3.x相关问答推荐

CONNEXION.EXCEPTIONS.ResolverError:运行pyz文件时未命名模块

这是重命名极地df列的最好方式吗?

如何使用PySide6创建切换框架?

pandas查找另一列中是否存在ID

While循环不停止地等待,直到时间.睡眠结束

msg-seviri l1.5本机文件

Python中根据分组/ID对两个数据框进行映射,以更接近值的升序排列

三重奏:为什么频道被记录为使用async with,而不是with?

如果集合大于 len(x),则 pandas 在重复的行中拆分集合列

在不改变 python 中原始数组顺序的情况下,对多维字符串数组进行降序排序?

attrs 将 list[str] 转换为 list[float]

Python Regex 查找给定字符串是否遵循交替元音、辅音或辅音、元音的连续模式

当我判断另一个 checkButton 时,如何判断两个 python tkinter checkButtons?

如何在python 3.10中将列表项(字符串类型)转换为模块函数

为什么 Multiprocessing 的 Lock 不会阻止其他进程使用对象?

从 yahoo Finance python 一次下载多只股票

活动屏幕上的 PyQt4 中心窗口

如何从字典中打印特定键值?

Python 3.5:async with导致 SyntaxError.为什么?

如何为 Python 3.x 安装 psycopg2?