八大排序算法之六——堆排序

1、基本原理。

堆排序是一种树形构造排序,是对直接选择排序的有效改进。

堆的定义:具有n个元素的序列(a[0],a[1],...,a[n-1]),当且仅当满足(a[i]>=a[2*i],a[i]>=a[2*i+1])或者(a[i]<=a[2*i],a[i]<=a[2*i+1])时称之为堆。由堆的定义可以很直观的看出,堆顶元素必定是最大(小)值,完全二叉树可以很直观的表示堆的结构。堆顶为根,其它为左子树、右子树。堆排序主要分为两个步骤进行。

step 1、从右至左,从下到上。从第一个非叶子的节点为根节点(假定有n个元素,则第一个非叶子节点的下标为n/2-1)开始构建堆,这样到一直到以第一个节点为根节点(编号为0)构建堆时,整个二叉树结构就是一个标准的堆结构。

step 2、经过第一步的调整,整个二叉树就是一个标准的堆结构,因此,根节点就是最大(小)的元素。将根节点与当前堆的最后一个元素交换并将当前堆的最后一个元素除外的元素重新建堆。如此重复n-1次,则堆排序完成。

 
 

2、实现

/**
 * @brief HeapAdjust 在堆内对以下标i为根结点的堆进行调整
 * 即原来除了下标为i的左右子树均为堆结构,调整完成后,以i为根结点的堆也是堆结构
 * @param array  存储堆的数组的起始地址
 * @param i      要调整的结点编号
 * @param length 堆长度
 */
void HeapAdjust(int* array,int i,int length)
{
    int tempData=array[i];
    for(int index=2*i+1;index<length;index=2*index+1)
    {
        //右子树的值大,右子树结点的值向上移动
        if(index<length-1&&array[index]<array[index+1])
        {
            index++;
        }

        if(array[index]>tempData)
        {
            array[i]=array[index];
            i=index;
        }
        else
        {
            break;
        }
    }
    array[i]=tempData;
}

/**
 * @brief heapSort 对序列array[0]到array[length-1]内元素进行堆排序
 * @param array
 * @param length
 */
void heapSort(int* array,int length)
{
    //1、第一步,建堆
    for(int i=length/2-1;i>=0;i--)
        HeapAdjust(array,i,length);

    //2、第二步
    for(int len=length-1;len>0;len--)
    {
        std::swap(array[0],array[len]);
        HeapAdjust(array,0,len);
    }
}

int main()
{
    int a[10]={11,42,53,25,36,6,75,8,26,4};
    std::cout<<"before sort:"<<std::endl;
    for(int i=0;i<10;++i)
        std::cout<<a[i]<<"\t";
    std::cout<<std::endl;

    heapSort(a,10);

    std::cout<<"after sort:"<<std::endl;

    for(int i=0;i<10;++i)
        std::cout<<a[i]<<"\t";
    std::cout<<std::endl;
    return 0;
}

3、运行结果。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值