堆排序(Heap Sort)定义:
共知的时间复杂度O(N*logN)的几种常见排序比如堆,归并,希尔排序,比较复杂的数据形式是堆。堆排序是堆简单选择排序的一种改进,1964年提出的这种数据结构和排序算法。其它几种堆(二项式堆,斐波纳契堆等)用的较少,一般将二叉堆就简称为堆。它主要用到完全二叉树的结构,当所有的根节点都大于或者等于其左右孩子节点的值,则该堆就是大顶堆。反之,就是小顶堆。
在排序之前,需要考虑堆结构的数据存入数组,基本按照层序遍历的方式。排序以大顶堆为例,整个序列的最大值就是堆顶的根节点,将该值移去,与堆数组的末尾元素交换,此时末尾元素就是最大值,然后将剩余的n-1个序列重新构成一个堆,如此,反复执行,就能得到一个有序序列。代码如下:
// 对有序表L 进行对排序
void HeapSort(SqList *L)
{
int i;
for(i=L->lengh/2;i>0;i--)
HeapAjust(L,i,L->length);// 将L构建成一个大顶堆
//
for(i=L->lengh/2;i>1;i--)
{
Swap(L,1,i);// 交换堆顶(1)和未排序子序列的最后一个记录(i)
HeapAjust(L,1,i-1);//将交换后的数据重新构架成一个大顶堆
}
}
上述函数用到交换函数和构建大顶堆的函数,后者代码如下:
void HeapAjust(SqList *L,int s,int m) // 把顺序表中的从s开始到m的元素构建成大顶堆的形式
{
int temp,j;
temp=L->r[s];
for(j=2*s;j<=m;j*=2)// 根节点和孩子节点的取法
{
if(j<m && L-r[j]<L-r[j+1] )
++j;
if(temp>=L->f[j])
break;
s=j;
}
L-r[s]=temp;// 插入最大值元素
}
更形象的表达可以利用大顶堆的二叉树形式来展示如何实现大顶堆的排序(从小到大)。