- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
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 个元素,它执行 log(n) 操作。为什么是 O(n)?
最佳答案
它需要更仔细的分析,比如你会 find here .基本见解是只有堆的根实际上具有深度 log2(len(a))
。在叶子上方的节点向下 - 一半的节点存在 - 叶子在第一次内循环迭代中被击中。
挥挥手,当算法正在查看具有 N
个元素的子树的根节点时,每个子树中大约有 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)
呢?那是免费的!只有 1 个元素的树已经是堆 - 无事可做。
T(1) = 0
在树叶之上一层,树有 3 个元素。将最小的(对于最小堆;最大的对于最大堆)移动到顶部的成本(不超过)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 heapify() 时间复杂度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51735692/
我正在尝试构建一个最小堆,但未能获得正确的结果。我不确定可能出了什么问题。 输入 = 209 97 298 54 110 27 250 455 139 181 446 206 478 90 88 输出
我从以下位置找到了堆排序的代码:http://rosettacode.org/wiki/Sorting_algorithms/Heapsort#C 我的理解方式(这在某些地方是错误的)是 heapso
下面是堆类。我正在尝试对堆进行排序,但我的 max_heapify 函数有问题。我插入了值 [10, 9, 7, 6, 5, 4, 3] 并且我的堆排序打印给定的输出。给定的输出和期望的输出在类下面给
我正在学习一门关于数据结构和算法的类(class),我应该在其中实现堆排序算法以在指定的时间范围内运行。下面是两个实现: def generateSwaps(): size=self._n f
def heapify(A): for root in xrange(len(A)//2-1, -1, -1): rootVal = A[root] child
我想插入一些节点,看来这个功能有问题。可以插入但不能执行heapify。我想知道添加新元素后索引是否困惑。欢迎任何评论。谢谢。 def heapify(arr, n, i): smallest
这是我最近遇到的面试问题之一。 给定完整或几乎完整二叉树的根地址,我们必须编写一个函数将树转换为最大堆。 这里不涉及数组。树已经构建完毕。 例如, 1
我有一个关于堆排序的问题。我不知道我的代码有什么问题。该程序仅更改了表中的第二个和最后一个位置。这是我的代码(没有主要功能): #include #define DUZO 100000000 i
我正在尝试制作一种适用于我的自定义容器的自定义(而不是使用 STL 方法)堆排序方法。我有迭代器,但是我找不到 make_heap 算法的描述。据我所知,它的作用类似于排列元素,使它们看起来像一个二叉
问题是我正在尝试修复最大堆,但它不起作用,因为错误不断发生。我一直在遵循几本书中的伪代码,但仍然显示错误。我尝试使用 = 进行交换,将 A[i] 交换为 A[largest],但出现错误 class
一旦调用了remove min函数,我如何在java中“堆化”基于数组的最小堆(这只是获取索引1处的元素并将其删除,然后用数组中的最后一项替换它)。我很困惑在删除最小值发生后如何将数组再次放入最小堆中
每次 heapq.heapify 函数更改我的堆列表中的元素时,我都希望得到回调通知(顺便说一句,这是跟踪列表中的对象以及它们的索引如何获取所需要的改变了)。 我的计划是从 list 继承并重写 __
Tarjan 的“数据结构和网络算法”在 leftiest heaps 中陈述了 heapify 函数如下: heap function heapify (list q); do |q| ≥ 2
我试着看http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-alg
我正在用 Ruby 实现 Heapify 算法(即将二叉树转换为堆),并认为下面的算法有效。我担心的是我进行了过多的递归调用。 第一次和第二次递归调用是从左右子树中选择最高节点,第三次递归调用是在我交
我一直在研究算法入门教科书中的一些算法,特别是我正在尝试让二叉堆 100% 正确地工作。我有一种奇怪的感觉,我正在使用的示例不正确,我想知道是否有人可以帮助我指明正确的方向。 给定数组 int[ ]
我对最大堆排序伪代码的一部分感到困惑。下降到 2 是什么意思? HeapSort(A) Build-Max-Heap(A) for i down to 2 do exchange A[1] A[i]
在CLRS书中,自上而下的heapify构建堆的复杂度为O(n)。也可以通过反复调用插入来建立堆,其最坏情况下的复杂度为nlg(n)。 我的问题是:对于后一种方法性能较差的原因,是否有任何见解? 我问
我有 b = heapify([5,4,9,1]) 如果我做一个 type(b) 它说它是 NoneType 而不是列表类型,有人知道我做错了什么吗?? 最佳答案 heapify() 方法就地转换列表
我正在为计算机科学类(class)创建一个堆实现,我想知道下面的递归函数是否会从一个还不是堆的数组对象中创建一个堆。代码如下: void Heap::Heapify(int i) { int
我是一名优秀的程序员,十分优秀!