线性时间构造最大堆

堆:是一个数组,近似的完全二叉树,除了最底层外,该树是完全充满的.

最小堆:A[i] <= A[2i] && A[i] <= A[2i+1]

最大堆:A[i] >= A[2i] && A[i] >= A[2i+1]

下标从1开始算起

维护堆

max_heapify(A, i):维护最大堆的性质,让A[i]的值逐级下降

    if 2*i <= len(A) and A[2*i] > A[i]:
        largest = 2*i
    else:
        largest = i
    if 2*i+1 <= len(A) and A[2*i+1] > A[i]:
        largest = 2*i+1
    else:
        largest = i
    if largest != i:
        A[i],A[largest] = A[largest],A[i]
        max_heapify(A,largest)

时间复杂度:(见算法导论第三版6.2节)

对于一个以i为根节点、大小为n的子树,交换值的代价为O(1),加上,以i的一个孩子为根节点的子树运行max_heapify的时间,每个孩子的子树的大小至多为2n/3(最坏情况发生在树的最底层恰好半满的时候)

这儿的2n/3的推导:

1、假设有一个包含n个元素的堆, 计算高度为 h=k 的节点数的上限
2、假设有一个完全二叉树,其中底层正好半满,即有x个节点。我们可以通过添加x个节点来构造一个满二叉树
3、满二叉树的大小为 n + x = 2x * 2 - 1 = 4x - 1 。因此,我们有 n = 3x - 1,进而 x = (n + 1) / 3。
4、在满二叉树中,第i层的节点数目为 (满树大小 - 1) / 2。代入上述结果,我们得到 2x - 1 = 2n/3 - 1/3 < 2n / 3。
因此,在一个最大堆中,节点i的子树大小至多为2n/3

由此,

T(n) ≤ T(2n/3) + O(1) ---->  T(n)=O(lg n)

即对于一个树高为h的节点,该操作的时间复杂度是O(h)。

建堆

最大堆:自底向上
build-max-heap(A):从最后一个非叶子节点开始,逐级向上维护最大堆的性质

A.heap-size = len(A)
for i in range(len(A)//2,0,-1):
    max_heapify(A,i)

时间复杂度

初看是O(n lgn),精确是:O(n)

1、高为h的 至多节点个数

6.3-3

2、线性时间构造最大堆

时间
这儿推导不是很明白!!!再看!!!

堆排序

heapsort(A):

build-max-heap(A)
for i in range(len(A),1,-1):
    A[1],A[i] = A[i],A[1]
    A.heap-size = A.heap-size - 1
    max_heapify(A,1)
posted @ 2024-04-17 20:51  QianFa01  阅读(13)  评论(0编辑  收藏  举报