- 完全二叉树左右孩子下标的计算
左图为常规版本(下标从1开始),右图为Heap Sort中使用的版本(下标从0开始)
- 维护最大堆性质
定义函数max_heapify
,其作用为:在数组范围A[0..heap_size - 1]
中,调整以节点i
为根的子树,使之满足最大堆的性质
void max_heapify( vector<int> &A, int i, int heap_size )
{
int l = 2 * ( i + 1 ) - 1, r = 2 * ( i + 1 ); // 计算左右孩子节点的下标
int max_index = i; // 存放A[i],A[l],A[r]中最大的那个节点的下标
if( l < heap_size && A[l] > A[max_index] ) // 注意判断下标l是否超出范围
max_index = l;
if( r < heap_size && A[r] > A[max_index] ) // 注意判断下标r是否超出范围
max_index = r;
if( max_index != i )
{
swap( A[i], A[max_index] );
max_heapify( A, max_index, heap_size );
}
}
- 初始时对整个数组建立最大堆
逆序遍历每个元素,调用max_heapify( A, i, A.size() )
for( int i = A.size() - 1; i >= 0; i-- )
max_heapify( A, i, A.size() ); // 初始建堆时,heap_size = n
- 每一趟排序
在最大堆中,最大元素一定是A[0]
,然后把A[0]
和A[heap_size - 1]
交换,heap_size
减1
,此时A[0]
破坏了最大堆性质,需要调用max_heapify( A, 0, heap_size )
- 完整heap_sort函数
void heap_sort( vector<int> &A )
{
for( int i = A.size() - 1; i >= 0; i-- )
max_heapify( A, i, A.size() );
int heap_size = A.size();
while( heap_size > 1 )
{
swap( A[0], A[heap_size - 1] );
heap_size--;
max_heapify( A, 0, heap_size );
}
}
- 完整代码如下
#include <stdio.h>
#include <time.h>
#include <vector>
#include <algorithm>
#define MAXN 50
using namespace std;
void display( vector<int>& s )
{
for( int i = 0; i < s.size(); i++ )
printf( "%d ", s[i] );
printf( "\n" );
}
bool check( vector<int>& s1, vector<int>& s2 )
{
for( int i = 0; i < s1.size(); i++ )
if( s1[i] != s2[i] )
return false;
return true;
}
void max_heapify( vector<int> &A, int i, int heap_size )
{
int l = 2 * ( i + 1 ) - 1, r = 2 * ( i + 1 ); // 计算左右孩子节点的下标
int max_index = i; // 存放A[i],A[l],A[r]中最大的那个节点的下标
if( l < heap_size && A[l] > A[max_index] ) // 注意判断下标l是否超出范围
max_index = l;
if( r < heap_size && A[r] > A[max_index] ) // 注意判断下标r是否超出范围
max_index = r;
if( max_index != i )
{
swap( A[i], A[max_index] );
max_heapify( A, max_index, heap_size );
}
}
void heap_sort( vector<int> &A )
{
for( int i = A.size() - 1; i >= 0; i-- )
max_heapify( A, i, A.size() );
int heap_size = A.size();
while( heap_size > 1 )
{
swap( A[0], A[heap_size - 1] );
heap_size--;
max_heapify( A, 0, heap_size );
}
}
int main()
{
srand( (unsigned)time(NULL) );
int nums[MAXN];
for( int i = 0; i < MAXN; i++ )
nums[i] = rand() % 100;
vector<int> s1( nums, nums + MAXN );
vector<int> s2( nums, nums + MAXN );
heap_sort(s1);
sort( s2.begin(), s2.end() );
printf( "s1: " );
display(s1);
printf( "s2: " );
display(s2);
printf( "Result: %s\n", check( s1, s2 ) ? "Accepted" : "Wrong Answer" );
return 0;
}