堆排序

今天学了一下堆排序。
堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。
如果根节点的编号为i,那么它的左孩子的编号为2*i+1,右孩子的编号为2*i+2,

大根堆的要求是每个节点的值都不大于其父节点的值,
Root[i].key>=Lchild[2*i+1].key&&Root[i].key>=Rchild[2*i+2].key
在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。

小根堆指的是父节点的值都不大于其左右孩子的值,
即,Root[i].key<=Lchild[2*i+1].key&&Root[i].key<=Rchild[2*i+2].key
那么最小值就在堆顶。

我们还应该知道什么是完全二叉树和满二叉树
满二叉树是指如下所示的二叉树:
除最后一层外,每一层上的所有结点都有两个子结点。在满二叉树中,每一层上的结点数都达到最大值,即在满二叉树的第k层上有

2 k1  
个结点,且深度为m的满二叉树有
2 m 1 
个结点。


完全二叉树是指如下所示的二叉树:
完全二叉树的节点除了最后一层外,节点都达到最大数,如果最后一层缺少叶子节点,一定是最右边的。

堆排序(升序,大顶堆)就是先把一个带排序的序列构建成堆,这样堆顶元素一定是序列中的最大值,然后把对顶元素和堆的最后一个元素交换,这样,最后一个元素就有序了。
经过堆顶元素和最后一个元素的交换,剩下的(n-1)元素就不再满足大顶堆的性质了,就再次把剩下的元素构建为堆,继续重复交换堆顶元素和最后一个元素,直到所有元素排序完毕。下图只展示了交换出8和9的过程:
这里写图片描述

#include<stdio.h>
void HeapAdjust(int a[],int i,int len);//堆调整
void PRINT(int a[],int len);//数组打印
void HeapSort(int a[],int len);//堆排序
void swap(int *a,int *b);//交换函数

int main()
{
    int a[7]={3,6,1,0,5,7,2};
    PRINT(a,7);
    HeapSort(a,7);
    PRINT(a,7);

    return 0;
}

void PRINT(int a[],int len)//数组打印函数实现
{
    int i;
    for(i=0;i<len;i++)
    {
        printf("%d->",a[i]);
    }

    printf("\n");
}//PRINT函数结束

void swap(int *a,int *b)//交换函数
{
    int t;
    t=*a;
    *a = *b;
    *b = t;
}

void HeapAdjust(int a[],int i,int len)//堆调整函数,i为待调整节点编号,len为数组长度,根节点编号为0
{
    int lc = 2*i + 1;//i节点的左孩子
    int rc = 2*i + 2;//i节点的右孩子

    int max = i;//假设最大值节点的下标为i

    if(2*i+1<len)//只要待调整节点的左孩子的下标不超过数组长度
    {
        a[lc]>a[rc]?max=lc:max=rc;//max取得左右孩子中较大者的下标

        if(max!=i)//如果max!=i,说明最大值下标与开始假设不一致,交换最大值到i节点处

        {
            int t;
            t=a[max];
            a[max]=a[i];
            a[i]=t;

            HeapAdjust(a,max,len);//递归调用,防止交换以后max节点不满足堆性质
        }
    }
}

void HeapSort(int a[],int len)
{
    int i,j;

        for(j=(len-2)/2;j>=0;j--)
                    {
                       HeapAdjust(a,j,len);//调整为堆
                    } 

    for(i=len-1;i>=2;i--)
    {




        swap(&a[0],&a[i]);//交换堆顶与最后一个元素


                       HeapAdjust(a,0,i-1);//重新调整剩余节点为堆

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值