堆排序( 内部排序 续 )
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();
}
堆:假设为大根堆,则 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();
}
相关文章推荐
- java五种内部排序(直接插入排序、希尔排序、快速排序、堆排序、归并排序)
- 八大内部排序 -- 堆排序
- 内部排序--堆排序
- 第十五周内部排序(2)项目1---(6)堆排序
- 排序专题(四) / 不稳定的内部排序 / 堆排序
- 2015年大二上-数据结构-内部排序-(6)-堆排序
- 六、内部排序综合(九种)—插入类排序(直接插入、折半插入、希尔排序);交换类排序(冒泡、快速);选择类排序(简单选择、堆排序);二路归并排序;基数排序
- 【内部排序】七:堆排序(Heap Sort)详解与代码(超详细注释版)
- 内部排序 ——第4波——————【堆排序】
- 10-9-堆排序-内部排序-第10章-《数据结构》课本源码-严蔚敏吴伟民版
- 数据结构_内部排序_希尔排序_快速排序_堆排序_归并排序_地址排序
- C++代码,数据结构-内部排序-选择排序-堆排序
- 堆排序(Heapsort)之Java实现
- 堆排序
- 数据结构之二叉堆(构建堆,堆排序)-(七)
- java 堆排序的实现
- 堆栈 ——堆排序
- 最大堆的插入 删除 初始化 堆排序
- 堆排序
- 排序算法——堆排序