堆的建立

对堆的常见操作一般有两种,一种是新增一个值并将其置于堆顶,然后对堆进行调整,另一种是仅仅新增一个值,将元素放入堆的顶部,这样就带来两种不同的堆的建立。

第一种方式是通过每次将元素置于堆的底部,然后调整,采用类似插入排序的方法,保证每次调整后,都是最小堆。

时间复杂度O(NlogN)

#include <stdio.h>//建立一个堆第一种方法
int h[101];
void up(int i)//这个函数的目的是向一个已经符合最小堆的末尾插入元素,同时整理堆,使得它仍然符合最小堆的规律
{             //这里其实有一种递归的思想,假设第n层一下都符合最小堆的规律,那么如果第n-1层的某个节点也符合,那么就包含了第n-1层
    int temp;
    while (i!=1)
    {

        if (h[i]<h[i/2])//应该是父节点小,子节点大,如果父节点大,则不符合
        {

            temp=h[i];
            h[i]=h[i/2];
            h[i/2]=temp;
            i=i/2;//不要忘记检查父节点
        }
        else break;
    }
}
int main()
{

    int n,i;
    scanf("%d",&n);
    for (i=1;i<=n;i++)
    {

        scanf("%d",&h[i]);//有点类似插入排序,读入一个数,就把他塞进堆内正确的位置,这样每个数读入之前都是符合最小堆的规律的,只需要将新加进来的数放在它正确的位置即可
        up(i);
    }
    for (i=1;i<=n;i++)
        printf("%d ",h[i]);
    printf("\n");
    return 0;
}


第二种方式是将所有数据读入,从最后一个非叶节点(n/2)开始,考察每棵树是否符合,之所以从非叶节点开始,是因为叶节点没有子节点,必然符合~~

时间复杂度O(N)

#include <stdio.h>
 int a[101];
 int n;
 void down(int i)
 {
     int t,temp;
     while(i*2<=n)
     {

         if (a[i]>a[i*2])
         t=i*2;
         else
            t=i;
         if ((i*2+1<=n)&&(a[t]>a[i*2+1]))
            t=i*2+1;
         if (t!=i)
         {

             temp=a[t];
             a[t]=a[i];
             a[i]=temp;
             i=t;
         }
         else break;

     }
 }
 int main()
 {

     int i;
     scanf("%d",&n);
     for (i=1;i<=n;i++)
        scanf("%d",&a[i]);
        for (i=n/2;i>=1;i--)
            down(i);
        for (i=1;i<=n;i++)
            printf("%d ",a[i]);
        return 0;
 }




由此看来,一般第二种方式更加常见~~


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值