好看懂的堆排序(HeapSort)

1、认识大顶堆和小顶堆

(1)大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列。

(2)小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列。

2、基本思想:先把数组构造成一个大顶堆(父亲节点大于其子节点),然后把堆顶(数组最大值,

数组第一个元素)和数组最后一个元素交换,这样就把最大值放到了数组最后边。把数组长度n-1,

再进行构造堆,把剩余的第二大值放到堆顶,输出堆顶(放到剩余未排序数组最后面)。依次类推,直

至数组排序完成。

3、对一个堆来说,要符合以下两个特点

(1)是一个完全二叉树。

(2)所有父节点的值都要大于(或等于)其子节点的值。

4、堆的重建

(1)移出完全二叉树根节点中的记录,该记录称为待调整记录,此时的根节点接近于空节点。

(2)从空节点的左、右孩子中选出一个关键字较小的记录,如果该记录的关键字小于待调整记录

的关键字,则将该记录上移至空节点中。此时,原来那个关键字较小的子节点相当于空节点。

(3)重复上述移动步骤,直到空节点左、右孩子的关键字均不小于待调整记录的关键字为止,此

时将待调整记录放入空节点即可完成重建。通过上述调整方法,实际上是把待调整记录实现了逐步

向下处理,所以上述过程一般被称为“筛选”法。

5、堆排序的具体步骤

(1)将待排序记录按照堆的定义建立一个初堆,并输出堆顶元素。

(2)调整剩余的记录序列,使用筛选法将前n-i个元素重新筛选,以便建成为一个新堆,然后再输

出堆顶元素。

(3)重复执行步骤(2),实现n-1次筛选,这样新筛选成的堆会越来越小,而新堆后面的有序关键

字会越来越多,最后使待排序记录序列成为一个有序的序列,这个过程被称为堆排序。

6、代码

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

void HeapSort(int a[],int len);
void HeapSort(int a[],int len) //堆排序
{
    int i,j,temp;

    while(len > 1)
    {
        /从最后一个拥有孩子的节点开始判断,此处不懂的画个图就懂了
        for(i = (len/2-1);i >= 0;i--)/
        {
            if(a[i] < a[2*i+2] && (2*i+2)<(len-1))//判断它的右孩子
            {
                temp = a[i];
                a[i] = a[2*i+2];
                a[2*i+2] = temp;
            }
            if(a[i] < a[2*i+1])//判断它的左孩子
            {
                temp = a[i];
                a[i] = a[2*i+1];
                a[2*i+1] = temp;
            }
        }
        //构成大顶堆后,把第一个元素放到数组后面
        temp = a[len-1];
        a[len-1] = a[0];
        a[0] = temp;
        len--;
    }
}
int main(int argc, char *argv[])
{ 
    int a[10] = {0};
    int i = 0;
    srand((unsigned)time(NULL));//随机数
    for(i = 0;i < sizeof(a)/sizeof(a[0]);i++)
        a[i] = rand()%100+1;

    printf("原始序列为\n");
    i = 0;
    while(i < sizeof(a)/sizeof(a[0]))
    {
        printf("%d ",a[i]);
        i++;
    }
    printf("\n");

    HeapSort(a,sizeof(a)/sizeof(a[0]));

    printf("排序后的序列为\n");
    i = 0;
    while(i < sizeof(a)/sizeof(a[0]))
    {
        printf("%d ",a[i]);
        i++;
    }
    printf("\n");
    return 0;
} 

7、运行结果

原始序列为
76 58 46 32 22 69 19 28 97 5 
排序后的序列为
5 19 22 28 32 46 58 69 76 97

由此可见,完成堆排序。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值