Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 构建堆的时间复杂度如何?_Algorithm_Big O_Heap_Complexity Theory_Construction - Fatal编程技术网

Algorithm 构建堆的时间复杂度如何?

Algorithm 构建堆的时间复杂度如何?,algorithm,big-o,heap,complexity-theory,construction,Algorithm,Big O,Heap,Complexity Theory,Construction,有人能解释一下堆的构建是多么复杂吗 向堆中插入一个项是O(logn),插入会重复n/2次(剩余的是叶子,不能违反heap属性)。我认为,这意味着复杂性应该是O(n logn) 换句话说,对于我们“heapify”的每个项目,到目前为止,它有可能必须对堆的每个级别(即logn级别)进行一次筛选(即筛选) 我缺少什么?如果您通过重复插入元素来构建堆,那么它将是O(n log n)。但是,通过按任意顺序插入元素,然后应用算法将它们“heapify”到正确的顺序(当然取决于堆的类型),可以更有效地创建新

有人能解释一下堆的构建是多么复杂吗

向堆中插入一个项是O(logn),插入会重复n/2次(剩余的是叶子,不能违反heap属性)。我认为,这意味着复杂性应该是O(n logn)

换句话说,对于我们“heapify”的每个项目,到目前为止,它有可能必须对堆的每个级别(即logn级别)进行一次筛选(即筛选)

我缺少什么?

如果您通过重复插入元素来构建堆,那么它将是O(n log n)。但是,通过按任意顺序插入元素,然后应用算法将它们“heapify”到正确的顺序(当然取决于堆的类型),可以更有效地创建新堆


有关示例,请参见“构建堆”。在这种情况下,您基本上从树的底部开始工作,交换父节点和子节点,直到满足堆条件

你的分析是正确的。然而,它并不紧

解释为什么构建堆是一个线性操作并不容易,您应该更好地阅读它

可以看到对该算法的大量分析


主要思想是,在
build\u heap
算法中,所有元素的实际
heapify
成本不是
O(logn)

调用
heapify
时,运行时间取决于进程终止前元素在树中向下移动的距离。换句话说,它取决于堆中元素的高度。在最坏的情况下,元素可能会一直下降到叶级别

让我们逐级统计所做的工作

在最底层,有
2^(h)
节点,但我们不在其中任何节点上调用
heapify
,因此工作为0。在下一级,有
2^(h− 1) 
节点,每个节点可能向下移动1级。在从底部开始的第三层,有
2^(h− 2) 
节点,每个节点可能向下移动2级


正如您所看到的,并不是所有的heapify操作都是
O(logn)
,这就是为什么您在构建堆时得到
O(n)

的原因,假设您采用的是自底向上的方法

  • 获取每个元素并将其与其子元素进行比较,以检查该对是否符合堆规则。因此,叶被免费包含在堆中。那是因为他们没有孩子
  • 向上移动,叶正上方节点的最坏情况是1次比较(最多只与一代子代进行比较)
  • 再往上看,他们的直系父母最多可以和两代孩子相比
  • 按照相同的方向继续,您将在最坏情况下对根进行日志(n)比较。log(n)-1表示其直系子代,log(n)-2表示其直系子代,依此类推
  • 总结一下,你得到了类似于log(n)+{log(n)-1}*2+{log(n)-2}*4+…+1*2^{(logn)-1},它只不过是O(n) 直觉上: “复杂性应该是O(nLog n)…对于我们“heapify”的每个项目,到目前为止,它可能必须为堆的每个级别(即log n级别)过滤一次。”

    不完全是。您的逻辑不会产生严格的界限——它高估了每个heapify的复杂性。如果自下而上构建,插入(heapify)可以比
    O(log(n))
    小得多。程序如下:

    (步骤1)第一个
    n/2
    元素位于堆的底行
    h=0
    ,因此不需要heapify

    (第2步)下一个
    n/22
    元素位于从底部向上的第1行<代码>h=1,heapify过滤器向下1级

    (步骤一) 下一个
    n/2i
    元素从底部向上排成一行
    i
    h=i
    ,heapify过滤器
    i
    级别降低

    (步骤日志(n))最后一个
    n/2log2(n)=1
    元素从底部向上排列
    log(n)
    h=log(n)
    ,heapify过滤器
    log(n)
    级别降低

    注意:在第一步之后,
    1/2
    元素
    (n/2)
    已经在堆中,我们甚至不需要调用heapify一次。另外,请注意,只有一个元素,即根元素,实际上会产生完整的
    log(n)
    复杂性


    理论上: 构建大小为
    N
    的堆的总步骤
    N
    ,可以用数学方法写出

    在height
    i
    中,我们已经(在上面)展示了需要调用heapify的
    n/2i+1
    元素,我们知道heapify At height
    i
    O(i)
    。这使得:

    最后求和的解可通过取已知几何级数方程两边的导数来求出:

    最后,将
    x=1/2
    插入上述等式,得到
    2
    。将其插入第一个方程式,得出:


    因此,步骤总数的大小为O(n)

    我认为本主题中隐藏了几个问题:

    • 如何实现
      buildHeap
      ,使其在O(n)时间内运行
    • 当正确实现时,如何显示
      buildHeap
      在O(n)时间内运行
    • 为什么相同的逻辑不能使堆排序在O(n)时间而不是O(n log n)时间内运行
    如何实现
    buildHeap
    ,使其在O(n)时间内运行? 通常,这些问题的答案集中在
    siftUp
    siftDown
    之间的差异上。在
    siftUp
    siftDown
    之间做出正确的选择对于
    buildHeap
    获得O(n)性能至关重要,但却无能为力
    (0 * n/2) + (1 * n/4) + (2 * n/8) + ... + (h * 1).
    
    (h * n/2) + ((h-1) * n/4) + ((h-2)*n/8) + ... + (0 * 1).
    
    for (i = n - 1; i > 0; i--) {
        arr[i] = deleteMax();
    }
    
    h*n/2 + (h-1)*n/4 + ... + 0 * 1.
    
    T = O(log(1) + log(2) + .. + log(n)) = O(log(n!))
    
        So total number of traversal would be:-
        T(n) = sigma((2^(logn-h))*h) where h varies from 1 to logn
        T(n) = n((1/2)+(2/4)+(3/8)+.....+(logn/(2^logn)))
        T(n) = n*(sigma(x/(2^x))) where x varies from 1 to logn
         and according to the [sources][1]
        function in the bracket approaches to 2 at infinity.
        Hence T(n) ~ O(n)
    
    Green  = n/2^1 * 0 (no iterations since no children)  
    red    = n/2^2 * 1 (heapify will perform atmost one swap for each red node)  
    blue   = n/2^3 * 2 (heapify will perform atmost two swaps for each blue node)  
    purple = n/2^4 * 3 (heapify will perform atmost three swaps for each purple node)   
    
    ->(n/2^1 * 0) + (n/2^2 * 1)+ (n/2^3 * 2) + (n/2^4 * 3) +...+ (n/2^(h+1) * h)  
    -> n * ( 0 + 1/4 + 2/8 + 3/16 +...+ h/2^(h+1) ) 
    
    -> ( 0 + 1/4 + 2/8 + 3/16 +...+ h/2^(h+1) )