【问题标题】:O(n) algorithm of heapifyheapify 的 O(n) 算法
【发布时间】:2014-05-30 14:48:00
【问题描述】:

我正在编写一个 O(n) 算法,用于在 Python 中“堆积”一个列表。我不明白为什么它不起作用。

def func(l):
    size=len(l)
    for root in range((size//2)-1,-1,-1):
        child = 2*root+1 #parent of child is target
        while(child<size):
            #l[child] should be smaller sibling
            if child<size-1 and l[child]>l[child+1]:
                child+=1
            #can we put l[root] in l[child//2]?
            if l[root]<=l[child]:
                break #yes
            #no
            l[child//2]=l[child]#move child up
            child=2*child+1#move down a level
        l[child//2]=l[root]
    return l

【问题讨论】:

  • root 的子节点是否应该在 pos. 2*root 和 2*root+1?
  • @MicahSmith:如果索引是从零开始的,则不会,就像在 Python 中一样。 root 的孩子是 2*root+12*root+2
  • @Blckknght 听起来不错。在我的 DS 课程中,我们学会了将 root 放入索引 1 并将索引 0 留空。 (在 heapify 期间既允许上面的模式并用作占位符。)

标签: python algorithm heap bottom-up


【解决方案1】:

你的函数有两个问题。

第一个很容易掌握。您使用错误的计算来查找您的 child 索引的父级。而不是child // 2,您应该使用(child - 1) // 2。这导致您将一些值转移到错误的位置。

第二个问题有点微妙。如果l[root] 大于它的一个孩子,则您当前正在用该孩子覆盖它,因此当您尝试将其插入列表中稍后的另一个位置时,原始值不再可用。可能您应该将l[root] 保存在for 循环的顶部,然后在您当前在代码后面检查l[root] 的任何时候使用保存的值(ifwhile 循环和最后结束后的分配。

这是一个固定版本的代码,用 cmets 指出我所做的更改:

def func(l):
    size=len(l)
    for root in range((size//2)-1,-1,-1):
        root_val = l[root]             # save root value
        child = 2*root+1
        while(child<size):
            if child<size-1 and l[child]>l[child+1]:
                child+=1
            if root_val<=l[child]:     # compare against saved root value
                break
            l[(child-1)//2]=l[child]   # find child's parent's index correctly
            child=2*child+1
        l[(child-1)//2]=root_val       # here too, and assign saved root value
    return l

【讨论】:

    【解决方案2】:

    上面的解释很好,这里稍微修改一下:

     # heapify in place
     def heapify(A):
        # write your code here
        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
    

    【讨论】:

      猜你喜欢
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 2022-10-13
      • 1970-01-01
      • 2019-12-23
      • 1970-01-01
      • 2020-05-13
      • 1970-01-01
      相关资源
      最近更新 更多