堆排序

堆是一种数据结构,是完全二叉树在数组中的存储。这棵完全二叉树满足:任何一个非叶节点的值都不大于(或不小于)其左右孩子的节点的值。若父亲的值大,孩子的值小,这样的堆叫做大顶堆;若父亲的值小,孩子的值大,则这样的堆叫做小顶堆。
由堆得定义知道,代表堆得这棵完全二叉树的根节点的值是最大(最小的),然后将找出的这个值交换到序列的最后(最前),这样有序序列元素增加1个,无序序列元素减少1个,对无序序列重复这样的操作,由此实现排序。

实现代码如下,

#include <iostream>
using namespace std;
void sift(int nums[],int low,int high)//调整堆
{
    int i=low,j=low*2;
    int temp=nums[i];
    while(j<=high)
    {
        if( j<high && nums[j]<nums[j+1] )//右节点若存在,且右节点较左节点大
            ++j; //则将j指向较大的节点
        if( temp<nums[j] )//nums[j]子节点比根节点大
        { 
            nums[i]=nums[j];//把子节点调整到根节点的位置上
            i=j;//重新设置根节点。把子节点的位置赋值为根节点
            j=i*2;//j重新指向左子节点
        }
        else //temp>nums[j],则代表以i为根节点的树,已经满足定义了
            break;
    }
    nums[i]=temp;//将i位置赋值为原先"根节点"的值
}
void heapSort(int nums[],int lastPos)
{

    for(int n=lastPos/2;n>=0;--n) //调整为最大堆,从(lastPos/2)位置开始
        sift(nums,n,lastPos);
    for(int i=lastPos;i>0;--i)//调整为堆之后,
    {
        int temp=nums[0]; //nums[0]中存储最大值
        nums[0]=nums[i]; //并把最后的元素调整到第一个元素
        nums[i]=temp;//将最大值调整的最后
        sift(nums,0,i-1);//再次调整堆,使其符合大顶堆得定义
    }      
}
int main()
{
    int nums[]={8,7,6,5,4,3,2,1};
    heapSort(nums,7);//heap排序,下标从0开始,共7个元素。
    for(int i=0;i<8;i++)
        cout<<nums[i]<<" ";
    return 0;
}
复杂度分析

(1)时间复杂度
对于sift() 函数,下标j 走了一条从当前结点(不一定是根节点,但是也有可能从某个叶节点开始调整,比如[1,2,3,4,5] 将从下标为5/2=2的位置开始,而该位置是叶节点),完全二叉树的高度为( (int)log2(n) )+1,对每个节点调整的时间复杂度为O(log2(n)),其中2为底数。对于heapSort() 函数,第一个循环n/2次,第二循环次数为(n-1)。根据大O定义,可知其时间复杂度为O(nlog2(n))
(2)空间复杂度
仅使用有限个变量,所以空间复杂度为O(1)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值