您的位置:首页 > 其它

堆排序( 内部排序 续 )

2007-05-31 21:00 239 查看
昨天老师讲了最后一个内部排序方法:堆排序。刚开始听的时候,比较晕。回来自己想了一会儿,豁然开朗...呵呵。真是佩服那些做算法研究的人。牛X。

堆:假设为大根堆,则 a[i] >= max{ a[2i+1], a[2i+2] } , a[i] 为 parent, a[2i+1], a[2i+2] 为其左/右儿子。

堆排序: 选择排序的优化。逻辑抽象(顺序地为数组元素下标编号)出一颗完全二叉树(自上而下 && 从左到右, 除最后一层叶子外,其余都为满树)。然后循环取出根节点+调节堆。堆排序在最坏情况下的时间复杂度为 nlg(n),而且其空间利用率相对高,除了一个temp外,几乎没有花费另外的存储空间,这点远远好于归并排序。

堆排序在一维简单数组上的实现:
#include <iostream>
using namespace std;

// Pre: low 到 high 之间除了low 以外都符合堆。
// Post: low 到 high 都满足堆条件。
void heapify( int a[], int low, int high )
{
bool fini=false; // fini 代表 finished, bool flag。
int temp = a[low]; int i = low; // 把 a[low], 和 low 先备份一下。
int j = 2*low +1;

// 找到第一个<= a[low] 的 位置。
while( j<=high && !fini )
{
if( j<high && a[j]<a[j+1] )
j++;
if( a[j] <= a[low] )
fini = true;
else { a[i]=a[j]; i=j; j = 2*j+1; }
}
a[i] = temp; // not a[j] = temp;
}

void heap_sort( int a[], int n ) // l_n : stands for last_unsorted.
{
// for 循环建堆。 没有必要从 n-1 开始,因为叶子肯定是满足堆结构的,我们从第一个“可能”不满足对结构的位置(n/2 -1 开始)
for( int i= n/2 -1; i>=0; --i )
heapify( a, i, n-1 );

for( int l_n = n-1; l_n >=1 ; --l_n )
{
swap( a[0], a[l_n] );
heapify( a, 0, l_n-1 );
}
}

void main()
{
int a[5]= { 2, 1, 7, 9, 7 };
heap_sort( a, 5 );
for( int i =0; i<5; ++i )
cout<<a[i]<<" "<<flush;
cout<<endl;

cin.get();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: