建堆复杂度O(n)证明

Posted xcw0754

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了建堆复杂度O(n)证明相关的知识,希望对你有一定的参考价值。

堆排序中首先需要做的就是建堆,广为人知的是建堆复杂度才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)证明的主要内容,如果未能解决你的问题,请参考以下文章

自下而上建堆(heap)的时间复杂度证明

c++ 手写堆 (包括建堆排序添加元素删除元素)

堆排序和TOP-K问题

堆排序和TOP-K问题

以下代码片段的算法复杂度

植物大战 堆排序——纯C