堆的定义:
堆实质上是满足如下性质的完全二叉树(要么左右孩子都有,要么有一个左孩子): 树中任一非叶子结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。关键字均不大于左右孩子称为小根堆,关键字均不小于左右孩子称为大根堆。
用大根堆排序的基本思想:
代码实现:
void heapAdjust(int* a,int i,int size) //堆调整
{
int nChild;
int nTemp;
for(;2*i+1<size;i=nChild)
{
nChild=2*i+1; //子结点的位置=2*(父结点位置)+1
if(nChild<size-1 && a[nChild+1]>a[nChild]) //在左孩子和有孩子中选择较大的
++nChild;
if(a[i]<a[nChild]) //如果较大的子结点大于父结点那么把较大的子结点往上移动,替换它的父结点
{
nTemp=a[i];
a[i]=a[nChild];
a[nChild]=nTemp;
}
else
break;
}
}
void heapSort(int* a,int size)
{
int temp;
for(int i=size/2-1;i>=0;--i) //size/2-1是最后一个非叶节点,此处"/"为整除
heapAdjust(a,i,size); //大顶堆的初始化
for(i=size-1;i>0;--i) //第一个元素和最后一个元素进行交换
{
temp=a[i];
a[i]=a[0];
a[0]=temp;
heapAdjust(a,0,i); //缩小范围,重新建堆
}
}
堆排序是不稳定排序,时间复杂度最差、最好、平均都是O(n*logn)。