1. 程式人生 > >建堆復雜度O(n)證明

建堆復雜度O(n)證明

nlogn 需要 它的 小根堆 () 簡單的 這不 調用 inline

堆排序中首先需要做的就是建堆,廣為人知的是建堆復雜度才O(n),不過很少有人去了解過這個復雜度的證明過程,因為不是那麽直觀地可以一眼就看出來。本文不講堆排序,只單純講建堆過程

建堆代碼

欲了解復雜度的計算過程,必先看懂建堆代碼。先看這個建堆過程

// 將arr[n]向上調整至合適位置
void AdjustHeap(vector<int> &arr, int n)
{
    if(n<=0) return ;
    if(arr[(n-1)/2] > arr[n]) {  //與父結點比較
        swap(arr[(n-1)/2], arr[n]);
        AdjustHeap(arr, (n-1)/2);   //遞歸調整
    }
}
// 小根堆
void BuildHeap(vector<int> &arr)
{
    for(int i=1; i<arr.size(); i++) {
        AdjustHeap(arr, i);
    }
}

因為不講堆排序,所以這裏用的是向上調整即可,更加直觀易懂。相信這麽簡單的代碼你應該能看懂它的原理。

復雜度計算

從直觀上看,AdjustHeap()的調用深度最多為logn層,故復雜度上限為O(logn)。而BuildHead()中的循環為n-1次,故它的復雜度為O(nlogn),但這不是它的實際平均復雜度,而是一個估算的上界,它很可能永遠達不到這個上界。下面來分析一下。

AdjustHeap(arr, 1) 比較次數最多為1次,最少為1次。
AdjustHeap(arr, 2) 比較次數最多為1次,最少為1次。
AdjustHeap(arr, 3) 比較次數最多為2次,最少為1次。
AdjustHeap(arr, 4)

比較次數最多為2次,最少為1次。
AdjustHeap(arr, 5) 比較次數最多為2次,最少為1次。
AdjustHeap(arr, 6) 比較次數最多為2次,最少為1次。
AdjustHeap(arr, 7) 比較次數最多為3次,最少為1次。
...
AdjustHeap(arr, n-1) 比較次數最多為logn次,最少為1次。

按最壞情況來算,將這些比較次數累加起來就是建堆的時間復雜度,顯然最佳情況是O(n)。而最壞情況的比較次數復雜一些,為了方便計算,假設n是2的k次冪,則k = logn
\({1 + 1 + 2 + 2 + 2 + 2 + 3 + 3 + ... + k}\)


= \({1*2^1+2*2^2+3*2^3}+\cdots + {k*2^k}\)
=

建堆復雜度O(n)證明