[开心IT面试题] 堆排序

1、基本思想

将数组划分成无序区和有序区,利用大根堆或小根堆思想。

1)首先将无序区elem[0,n-1]建立大根堆,然后将堆首elem[0]与堆尾elem[n-1]交换,堆尾之后为有序区。

2)将新的无序区elem[0,n-2]调整为大根堆,然后将堆首elem[0]与堆尾elem[n-2]交换,堆尾进入有序区。

3)将新的无序区elem[0.n-3]调整为大根堆……重复操作,直到无序区只有一个元素为止,排序结束。


2、堆实质上是满足完全二叉树的性质的:树的任一非叶结点的数据均不大于(或不小于)其左右孩子(若存在)结点的数据。

大根堆:根结点的数据均不小于其左右孩子结点的数据。

小根堆:根结点的数据均不大于其左右孩子结点的数据。

 

3、堆排序是一种不稳定的排序。

时间复杂度O(nlogn)。空间复杂度O(1)。

 

4、代码

将elem[]数组按递增进行堆排序

void Heapify(int elem[], int node, int length)
{
    //记录头结点
    int tempElem = elem[node];
    //左右孩子序号
    int leftChild = 2*node+1;
    int rightChild = 2*node+2;

    while(leftChild < length)
    {
        rightChild = 2*node+2;
        //判断是否存在右孩子,并且右孩子比左孩子大时,用右孩子与头结点比较
        if((rightChild < length) && (elem[rightChild] > elem[leftChild]))
        {
            //将比结点大的孩子与结点交换
            if(elem[rightChild] > tempElem)
            {
                elem[node] = elem[rightChild];
                elem[rightChild] = tempElem;
                node = rightChild;
            }else
            {
                break;
            }
        }else
        {
            if(elem[leftChild] > tempElem)
            {
                elem[node] = elem[leftChild];
                elem[leftChild] = tempElem;
                node = leftChild;
            }else
            {
                break;
            }
        }
        tempElem = elem[node];
        leftChild = 2*node+1;
    }
}

void HeapSort(int elem[], int elemLen)
{
    //建立大根堆,头节点的个数
    for(int i = elemLen/2 - 1; i >= 0; i--)
    {
        Heapify(elem, i, elemLen);
    }

    int tempElem = 0;//交换数据的中间变量
    for(int i = elemLen-1; i > 0; i--)
    {
        //将堆首与堆尾交换
        tempElem = elem[i];
        elem[i] = elem[0];
        elem[0] = tempElem;

        //重新调整交换后的无序区为大根堆
        Heapify(elem, 0, i);
    }
}



 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值