排序算法——堆排序

有一点需要注意,那就是,左孩子的下标是2×s+1,右孩子下标是2×s,注意是下标,例如数组1到10,那么下标为13579的全部是左孩子(构造树的时候1第一个数是根,第二个数是左孩子,第三个是右孩子,然后第四个数则是第一个左孩子的左孩子,以此类推)。最大堆:每个父节点都比子节点大;最小堆:每个父节点都比子节点小

 [22:42:20] vi t.c
[22:42:27] gcc t.c
[22:42:28] ./a.out
父节点已经排好: 10 8 9 7 3 4 5 6 1 2 
1 2 3 4 5 6 7 8 9 10 
[22:42:30] cat t.c
#include<stdio.h>
void head(int a[],int i,int len)
{
    int p=a[i];
    int child=2*i+1;//child 左节点,child+1右节点
    while(child<len)
    {
        if(child+1<len&&a[child]<a[child+1])
            ++child;//如果左节点比右节点小,令child变成右节点下标
        if(a[i]<a[child])//父节点与子节点比较,小于就移动
        {
            a[i]=a[child];//父节点赋上子节点的值
            i=child;//那么原来的父节点下标就变成子节点的下标
            child=2*i+1;//令子节点的下标等于它的左孩子,因为不能只比较一次,需要循环比较,确保每一个子节点都比父节点小
        }
        else
            break;//父节点比子节点大,直接退出了
        a[i]=p;//完成交换
    }
}
void sort(int a[],int len)
{   
    int i,t;
    for(i=(len-1)/2;i>=0;i--)//这里把每个父节点排好,这个循环结束后,每个父节点都比子节点大
        head(a,i,len);
    //下面这个是用来查看父节点是否排好的
    printf("父节点已经排好: ");
    for(i=0;i<len;i++)
        printf("%d ",a[i]);
    printf("\n");
    for(i=len-1;i>0;--i)//这个循环是用来把堆顶最大那个节点放到相应的字节点位置的,因为用了t变量进行了交换操作,所以这个循环每执行一次,在堆顶的都是最大的值
    {
        t=a[i];
        a[i]=a[0];
        a[0]=t;//交换
        head(a,0,i);//重新调整堆,让它再次成为最大堆
    }
}
int main()
{   
    int i;
    int a[]={3,1,5,7,2,4,9,6,10,8};
    int length=sizeof(a)/sizeof(a[0]);
    sort(a,length);
    for(i=0;i<length;i++)
        printf("%d ",a[i]);
    printf("\n");
    return 0;
}
[22:42:38] 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值