排序七之堆排序

Heap Sort

一种基于选择排序思想,利用堆结构和二叉树的一些性质来完成数据排序的排序算法。

 堆排序的关键是构造堆结构,准确而言,堆结构即是一个完全二叉树,树中的每一个节点对应原始数据的一个记录。每个节点应满足以下条件:

1)从小到大排序:要求非叶结点的数据要大于或等于其左、右子节点的数据。

2)从大到小排序:要求非叶节点的数据要小于或等于其左、右子节点的数据。

一个完整的堆排序需要反复经过两个步骤:构造堆结构和堆排序的输出。

构造堆结构过程:

对于一个非叶结点Ai,这里假定Ai的左子树与右子树已经进行了筛运算,即已构成堆结构;

1:比较Ai的左子树与右子树的最大值,将最大值放在Aj中。

2:将Ai的数据与Aj的数据进行比较,如果Ai大于Aj表示以Ai为根的子树已构成堆结构,便可以终止运算。

3:如果Ai小于Aj,则将Ai与Aj互换位置。

4:经过第三步后,可能会破坏以Ai为根的堆,因为此时Ai的值为原来的Aj。下面以Aj为根重复前面的步骤,直到满足堆结构的定义,即父节点大于子节点。这样一Aj为根的子树就被调整为一个堆结构。

堆排序的输出过程:

1:将堆结构的根节点放到数组的最后。

2:除最后一个节点外的其他节点重新执行前面的构造堆过程。

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define SIZE 10
void HeapSort(int *a,int n)
{
    int i,j,h,k;
    int t;
    for(i=n/2-1;i>=0;i--)
    {
        while(2*i+1<n)
        {
            j=2*i+1;
            if((j+1)<n)
            {
                if(a[j]<a[j+1])
                    j++;
            }
            if(a[i]<a[j])
            {
                t=a[i];
                a[i]=a[j];
                a[j]=t;
                i=j;
            }
            else{break;}
        }
    }
    for(i=n-1;i>0;i--)
    {
       t=a[0];
       a[0]=a[i];
       a[i]=t;
       k=0;
       while(2*k+1<i)
       {
           j=2*k+1;
           if((j+1)<i)
           {
               if(a[j]<a[j+1])
                j++;
           }
           if(a[k]<a[j])
           {
               t=a[k];
               a[k]=a[j];
               a[j]=t;
               k=j;
           }
           else{break;}
       }
    }
}
int main()
{
    int i;
    int shuzu[SIZE];
    srand(time(NULL));
    for(i=0;i<SIZE;i++)
        shuzu[i]=rand()/1000+100;
    printf("排序后的数组为:\n");
    for(i=0;i<SIZE;i++)
        printf("%d ",shuzu[i]);
    printf("\n");
    HeapSort(shuzu,SIZE);
    printf("排序后的数组为:\n");
    for(i=0;i<SIZE;i++)
        printf("%d ",shuzu[i]);
    printf("\n");
    return 0;
}










 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值