您的位置:首页 > 其它

堆排序

2008-08-21 16:49 106 查看
因为堆是完全二元树,因此将堆以数组形式存储非常方便。设堆大小为N,i是其中一个元素,则这种堆满足的关系为:对所有的i <= n/2 - 1有a[i] <= a[2*i],a[i] <= a[2*i+1]。当然这是小根堆,大根堆将<=改为>=即可。于是堆的第一个元素为最小元素,要实现排序只要依次取第一个元素,并用最后一个元素替代之。这样之后的只有第一个元素不符合堆定义,需要将它下推到合适位置。完成该功能的函数如下
//将堆顶元素下推至合适位置。a为堆数组,n为堆大小,i为堆顶元素下标
void push(int a[], int n, int i)
{
int t;
while( i < n/2 ){
t = 2*i + 2 < n -1 ? 2*i + 2 : n - 1;//令t为i的右儿子,没右儿子则为n,此时也即左儿子
if( a[2*i + 1] < a[t])
t = 2*i + 1;//令t为i的较小的儿子
if( a[i] > a[t]){
//交换元素
a[i] = a[i] ^ a[t];
a[t] = a[t] ^ a[i];
a[i] = a[i] ^ a[t];

i = t;
}
else
break;
}
}
现在问题是如何将初始数组整理成堆。实际上利用上述下推函数即可简单地整理,从堆的最后一个非叶结点开始依次向前遍历,每次将当前元素作为堆的顶元素调用上述函数,因为此时当前元素以后的元素都符合堆的定义。
至此堆排序可以实现如下:
//堆排序。 a为堆数组,n为堆大小
void HeapSort(int a[], int n)
{
int i;
//初始堆整理
for(i = n/2 - 1; i >= 0; i--)
push(a,n,i);
//开始排序,排序后数组元素按从大到小排列
for(i = n - 1; i > 0; i--){
//将堆顶元素(即最小元素)与最后元素交换
a[0] = a[0] ^ a[i];
a[i] = a[i] ^ a[0];
a[0] = a[0] ^ a[i];

push(a,i , 0);//重新整理堆,每循环一次此堆大小减1
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: