一、简介
算法:先用所给数组构建堆,然后从堆中依次删除最大 ( 小 ) 值,各元素的删除顺序即各元素的排序。
二叉堆见 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;
}