为什么建堆的时间复杂度是O(n)?

原文:https://blog.youkuaiyun.com/LeoSha/article/details/46116959 

 

先看下堆排序与快速排序的实现代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=111;
int a[maxn];
 
void quicksort(int a[],int l,int r)
{
    if(l>=r) return;
    int i,j,tmp;
    i=l;
    j=r;
    tmp=a[l];
    while(i!=j)
    {
        while(j>i&&a[j]>=tmp) j--;
        while(i<j&&a[i]<=tmp) i++;
        swap(a[i],a[j]);
    }
    a[l]=a[i];
    a[i]=tmp;
    quicksort(a,l,i-1);
    quicksort(a,i+1,r);
}
 
void adjustheap(int num[],int s,int len)
{
    int tmp=num[s];
    int child=s*2+1;
    while(child<len)
    {
        if(child+1<len&&num[child]<num[child+1])
            child++;
        if(num[child]>num[s])
        {
            num[s]=num[child];
            num[child]=tmp;
            s=child;
            child=s*2+1;
        }
        else
            break;
    }
}
 
void buildheap(int num[],int len)
{
    for(int i=(len-1)/2;i>=0;i--)
    {
        adjustheap(num,i,len);
    }
}
 
void heapsort(int num[],int len)
{
    buildheap(num,len);
    for(int i=len-1;i>0;i--)
    {
        swap(num[i],num[0]);
        adjustheap(num,0,i);
    }
}
 
int main()
{
    int n,i;
    scanf("%d",&n);
    //for(i=1;i<=n;i++)
        //scanf("%d",&a[i]);
    //quicksort(a,1,n);
    for(i=0;i<n;i++)
        scanf("%d",&a[i]);
    heapsort(a,n);
    for(i=0;i<n;i++)
        printf("%d ",a[i]);
    puts("");
    return 0;
}

牛客网测试排序代码链接:https://www.nowcoder.com/questionTerminal/508f66c6c93d4191ab25151066cb50ef

 

如果仅从代码上直观观察,会得出构造二叉堆的时间复杂度为O(n㏒n)的结果,这个结果是错的,虽然该算法外层套一个n次循环,而内层套一个分治策略下的㏒n复杂度的循环,该思考方法犯了一个原则性错误,那就是构建二叉堆是自下而上的构建,每一层的最大纵深总是小于等于树的深度的,因此,该问题是叠加问题,而非递归问题。那么换个方式,假如我们自上而下建立二叉堆,那么插入每个节点都和树的深度有关,并且都是不断的把树折半来实现插入,因此是典型的递归,而非叠加。

在做证明之前,我们的前提是,建立堆的顺序是bottom-top的。 
正确的证明方法应当如下:

具有n个元素的平衡二叉树,树高为㏒n,我们设这个变量为h。
最下层非叶节点的元素,只需做一次线性运算便可以确定大根,而这一层具有2^(h-1)个元素,我们假定O(1)=1,那么这一层元素所需时间为2^(h-1) × 1。
由于是bottom-top建立堆,因此在调整上层元素的时候,并不需要同下层所有元素做比较,只需要同其中之一分支作比较,而作比较次数则是树的高度减去当前节点的高度。因此,第x层元素的计算量为2^(x) × (h-x)。
又以上通项公式可得知,构造树高为h的二叉堆的精确时间复杂度为: 
S = 2^(h-1) × 1 + 2^(h-2) × 2 + …… +1 × (h-1) ①
通过观察第四步得出的公式可知,该求和公式为等差数列和等比数列的乘积,因此用错位想减发求解,给公式左右两侧同时乘以2,可知: 
2S = 2^h × 1 + 2^(h-1) × 2+ …… +2 × (h-1) ②

用②减去①可知: S =2^h × 1 - h +1 ③

将h = ㏒n 带入③,得出如下结论:

S = n - ㏒n +1 = O(n)

结论:构造二叉堆的时间复杂度为线性得证。

原文:https://blog.youkuaiyun.com/LeoSha/article/details/46116959 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值