1. 堆
(1)形状:完全二叉树。
节点i : Parent = i/2 ; Left = 2i; Right = 2i + 1
(2)根最大(最小)——大根堆(小根堆),左右子树没有大小关系
2. 算法的思想
(1)由于跟最大(最小),所以每次输出根
(2)在对堆进行调整,
(3)重复(1)(2)知道结束
所以算法的重点就是如何建立堆和怎样高效的调整
3. 调整HeapAdjust
//大根堆
//a[0] 不使用
void HeapAdjust( int a[], int i, int size )
{
int l = 2*i;
int r = l+1;
int max = i;
if( i < size/2 ) // leaf不需要调整
{
//从i, r, l中找到max
if( l<=size && a[l]>max )
max = l;
if( r<=size && a[r] > max )
max = r;
if( max != i )
{
swap( a[i], a[max] );
HeapAdjust( a, max, size );
}
}
}
4. 堆的建立
//a[0] 不使用
void BuildHeap( int a[], int size )
{
for(int i = size/2; i>=1; i++ )
{
HeapAdjust( a, i, size );
}
}
5. 堆排序
void HeapSort( int a[], int size )
{
BuildHeap( a, size );
for( int i=size; i>=1; i-- )
{
cout<<a[i]<<" ";
swap( a[1], a[i] );
HeapAdjust( a, 1, i-1 );
}
}
6. 算法分析
最好: nlog(n)
最坏:nlog(n)
平均:nlog(n)
空间复杂度:1
稳定性:非
由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。
堆在获取数据的最大值or最小值比较有优势
===============================================================================
分类 | 基础排序O(n^2) | 高级排序O(nlogn) |
交换 | 冒泡排序 | 快排 |
插入 | 插入排序 | 希尔 |
选择 | 选择排序 | 堆排序 |