線性時間構造最大堆

QianFa01發表於2024-04-17

堆:是一個陣列,近似的完全二叉樹,除了最底層外,該樹是完全充滿的.

最小堆: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)

相關文章