堆排序( heap sort )

一、简介

算法:先用所给数组构建堆,然后从堆中依次删除最大 ( 小 ) 值,各元素的删除顺序即各元素的排序。

二叉堆见 https://blog.csdn.net/weixin_38096504/article/details/104435748

堆排序性能极其稳定,平均它使用的比较只比最坏情形界指出的略少。

最坏时间复杂度:O( NlogN )

最好时间复杂度:O( NlogN )

平均时间复杂度:O( NlogN )

二、堆排序操作

 

为了避免使用第二个数组存放删除的数,我们将 deleteMax 之后,堆减少的1个位置( 位于堆最后的单元 ),存放刚刚删去的元素。

三、代码

/*
 * @Author: lsyy
 * @Date: 2020-02-11 16:31:25
 * @LastEditTime: 2020-02-27 16:06:46
 * @LastEditors: Please set LastEditors
 * @Description: 堆排序
 * @FilePath: \insertion sort\Src\main.cpp
 */



#include <iostream>
#include <string>
#include <functional>
#include <queue>
#include <vector>


/**
 * @description: 堆排序内部方法 获得左儿子
 * @param {type} i 堆中父节点下标  
 * @return: 返回左儿子下标
 */
inline int leftChild( int i )
{
    return 2 * i + 1;
}
/**
 * @description: 下滤
 * @param {type} a 排序数组 i 开始下滤的位置 n 是二叉堆的逻辑大小
 *                ( 因为每次要把删除的值由后向前插入到数组中 )
 * @return: null
 */
template < typename Comparable >
void percDown( std::vector<Comparable> & a, int i, int n )
{
    int child;
    Comparable tmp;
    for( tmp = std::move( a[ i ] ); leftChild( i ) < n; i = child )
    {
        child = leftChild( i );
        if( child != n - 1 && a[ child ] < a[ child + 1 ] ) // 寻找一个值大的儿子
            child ++;   
        if( tmp < a[ child ] )
            a[ i ] = std::move( a[ child ] );
        else
            break;
    }
    a[ i ] = std::move( tmp );
}
/**
 * @description: 堆排序算法 时间复杂度O(NlogN)
 * @param {type} a 排序数组  
 * @return: null
 */
template < typename Comparable >
void heapsort( std::vector<Comparable> & a )
{
    for( int i = a.size( ) / 2 - 1; i >= 0; --i )           // 构建堆
        percDown( a, i, a.size( ) );
    for( int j = a.size( ) - 1; j > 0; j-- )                // 删除最大元素
    {
        std::swap( a[ 0 ], a[ j ] );
        percDown( a, 0, j );
    }
}
int main( )
{
    int a[] = {1,8,7,5,90,8,4,2,7,6};
    std::vector<int> iv(a,a+sizeof(a)/sizeof(int));
    heapsort( iv );
    return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值